@SuppressWarnings("unchecked")
    static Object readObjectFrom(final Input input, final Schema<?> schema,
            Object owner, IdStrategy strategy) throws IOException
    {
        Object value = null;
        final int number = input.readFieldNumber(schema);
        switch (number)
        {
            case ID_BOOL:
                value = BOOL.readFrom(input);
                break;
            case ID_BYTE:
                value = BYTE.readFrom(input);
                break;
            case ID_CHAR:
                value = CHAR.readFrom(input);
                break;
            case ID_SHORT:
                value = SHORT.readFrom(input);
                break;
            case ID_INT32:
                value = INT32.readFrom(input);
                break;
            case ID_INT64:
                value = INT64.readFrom(input);
                break;
            case ID_FLOAT:
                value = FLOAT.readFrom(input);
                break;
            case ID_DOUBLE:
                value = DOUBLE.readFrom(input);
                break;
            case ID_STRING:
                value = STRING.readFrom(input);
                break;
            case ID_BYTES:
                value = BYTES.readFrom(input);
                break;
            case ID_BYTE_ARRAY:
                value = BYTE_ARRAY.readFrom(input);
                break;
            case ID_BIGDECIMAL:
                value = BIGDECIMAL.readFrom(input);
                break;
            case ID_BIGINTEGER:
                value = BIGINTEGER.readFrom(input);
                break;
            case ID_DATE:
                value = DATE.readFrom(input);
                break;

            case ID_ARRAY:
            {
                final ArrayWrapper arrayWrapper = newArrayWrapper(input, schema, false,
                        strategy);

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(arrayWrapper.array, owner);
                }

                strategy.COLLECTION_SCHEMA.mergeFrom(input, arrayWrapper);

                return arrayWrapper.array;
            }
            case ID_OBJECT:
                if (input.readUInt32() != 0)
                    throw new ProtostuffException("Corrupt input.");

                value = new Object();

                break;

            case ID_ARRAY_MAPPED:
            {
                final ArrayWrapper mArrayWrapper = newArrayWrapper(input, schema, true,
                        strategy);

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(mArrayWrapper.array, owner);
                }

                strategy.COLLECTION_SCHEMA.mergeFrom(input, mArrayWrapper);

                return mArrayWrapper.array;
            }
            case ID_CLASS:
                value = strategy.resolveClassFrom(input, false, false);
                break;
            case ID_CLASS_MAPPED:
                value = strategy.resolveClassFrom(input, true, false);
                break;
            case ID_CLASS_ARRAY:
                value = getArrayClass(input, schema,
                        strategy.resolveClassFrom(input, false, true));
                break;
            case ID_CLASS_ARRAY_MAPPED:
                value = getArrayClass(input, schema,
                        strategy.resolveClassFrom(input, true, true));
                break;

            case ID_ENUM:
            {
                final EnumIO<?> eio = strategy.resolveEnumFrom(input);

                if (input.readFieldNumber(schema) != ID_ENUM_VALUE)
                    throw new ProtostuffException("Corrupt input.");

                value = eio.readFrom(input);
                break;
            }
            case ID_ENUM_SET:
            {
                final Collection<?> es = strategy.resolveEnumFrom(input).newEnumSet();

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(es, owner);
                }

                strategy.COLLECTION_SCHEMA.mergeFrom(input, (Collection<Object>) es);

                return es;
            }
            case ID_ENUM_MAP:
            {
                final Map<?, Object> em = strategy.resolveEnumFrom(input).newEnumMap();

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(em, owner);
                }

                strategy.MAP_SCHEMA.mergeFrom(input, (Map<Object, Object>) em);

                return em;
            }
            case ID_COLLECTION:
            {
                final Collection<Object> collection = strategy.resolveCollectionFrom(
                        input).newMessage();

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                strategy.COLLECTION_SCHEMA.mergeFrom(input, collection);

                return collection;
            }
            case ID_MAP:
            {
                final Map<Object, Object> map =
                        strategy.resolveMapFrom(input).newMessage();

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(map, owner);
                }

                strategy.MAP_SCHEMA.mergeFrom(input, map);

                return map;
            }
            case ID_POLYMORPHIC_COLLECTION:
            {
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                final Object collection = PolymorphicCollectionSchema.readObjectFrom(input,
                        strategy.POLYMORPHIC_COLLECTION_SCHEMA, owner, strategy);

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                return collection;
            }
            case ID_POLYMORPHIC_MAP:
            {
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                final Object map = PolymorphicMapSchema.readObjectFrom(input,
                        strategy.POLYMORPHIC_MAP_SCHEMA, owner, strategy);

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(map, owner);
                }

                return map;
            }
            case ID_DELEGATE:
            {
                final HasDelegate<Object> hd = strategy.resolveDelegateFrom(input);
                if (1 != input.readFieldNumber(schema))
                    throw new ProtostuffException("Corrupt input.");

                value = hd.delegate.readFrom(input);
                break;
            }
            case ID_ARRAY_DELEGATE:
            {
                final HasDelegate<Object> hd = strategy.resolveDelegateFrom(input);

                return hd.genericElementSchema.readFrom(input, owner);
            }
            case ID_ARRAY_SCALAR:
            {
                final int arrayId = input.readUInt32(), id = ArraySchemas.toInlineId(arrayId);

                final ArraySchemas.Base arraySchema = ArraySchemas.getSchema(id,
                        ArraySchemas.isPrimitive(arrayId), strategy);

                return arraySchema.readFrom(input, owner);
            }
            case ID_ARRAY_ENUM:
            {
                final EnumIO<?> eio = strategy.resolveEnumFrom(input);

                return eio.genericElementSchema.readFrom(input, owner);
            }
            case ID_ARRAY_POJO:
            {
                final HasSchema<Object> hs = strategy.resolvePojoFrom(input, number);

                return hs.genericElementSchema.readFrom(input, owner);
            }
            case ID_THROWABLE:
                return PolymorphicThrowableSchema.readObjectFrom(input, schema, owner,
                        strategy, number);
            case ID_POJO:
            {
                final Schema<Object> derivedSchema = strategy.resolvePojoFrom(
                        input, number).getSchema();

                final Object pojo = derivedSchema.newMessage();

                if (input instanceof GraphInput)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(pojo, owner);
                }

                derivedSchema.mergeFrom(input, pojo);
                return pojo;
            }
            default:
                throw new ProtostuffException("Corrupt input.  Unknown field number: " + number);
        }

        if (input instanceof GraphInput)
        {
            // update the actual reference.
            ((GraphInput) input).updateLast(value, owner);
        }

        if (input.readFieldNumber(schema) != 0)
            throw new ProtostuffException("Corrupt input.");

        return value;
    }
A schema for dynamic types (fields where the type is {@link Object}).

@author David Yu
@created Feb 1, 2011
protostuff-runtime/src/main/java/io/protostuff/runtime/ObjectSchema.java