Esempio n. 1
0
        private static void CreateMapUnpackFrom(SerializationContext context, Type targetType, SerializerEmitter emitter, CollectionTraits traits)
        {
            var il           = emitter.GetUnpackFromMethodILGenerator();
            var localHolder  = new LocalVariableHolder(il);
            var instanceType = targetType;

            try
            {
                /*
                 *	if (!unpacker.IsMapHeader)
                 *	{
                 *		throw SerializationExceptions.NewIsNotMapHeader();
                 *	}
                 *
                 *	TDictionary<TKey, TValue> dictionary = new ...;
                 *	this.UnpackToCore(unpacker, dictionary);
                 *	return dictionary;
                 */

                if (targetType.IsInterface || targetType.IsAbstract)
                {
                    instanceType = context.DefaultCollectionTypes.GetConcreteType(targetType);
                    if (instanceType == null)
                    {
                        il.EmitTypeOf(targetType);
                        il.EmitAnyCall(SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod);
                        il.EmitThrow();
                        return;
                    }
                }

                il.EmitAnyLdarg(1);
                il.EmitGetProperty(Metadata._Unpacker.IsMapHeader);
                var endIf = il.DefineLabel("END_IF");
                il.EmitBrtrue_S(endIf);
                il.EmitAnyCall(SerializationExceptions.NewIsNotMapHeaderMethod);
                il.EmitThrow();
                il.MarkLabel(endIf);

                var collection = localHolder.GetDeserializingCollection(instanceType);
                Emittion.EmitConstruction(
                    il,
                    collection,
                    il0 => Emittion.EmitGetUnpackerItemsCountAsInt32(il0, 1, localHolder)
                    );

                EmitInvokeMapUnpackToHelper(targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdloc(collection));

                il.EmitAnyLdloc(collection);
                il.EmitRet();
            }
            finally
            {
                il.FlushTrace();
            }
        }
Esempio n. 2
0
        private static void CreateArrayUnpackFrom(Type targetType, SerializerEmitter emitter, CollectionTraits traits)
        {
            var il          = emitter.GetUnpackFromMethodILGenerator();
            var localHolder = new LocalVariableHolder(il);

            try
            {
                if (targetType.IsInterface || targetType.IsAbstract)
                {
                    il.EmitTypeOf(targetType);
                    il.EmitAnyCall(SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod);
                    il.EmitThrow();
                    return;
                }

                /*
                 *	if (!unpacker.IsArrayHeader)
                 *	{
                 *		throw SerializationExceptions.NewIsNotArrayHeader();
                 *	}
                 *
                 *	TCollection collection = new ...;
                 *	this.UnpackToCore(unpacker, array);
                 *	return collection;
                 */

                il.EmitAnyLdarg(1);
                il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader);
                var endIf = il.DefineLabel("END_IF");
                il.EmitBrtrue_S(endIf);
                il.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod);
                il.EmitThrow();
                il.MarkLabel(endIf);
                var collection = localHolder.GetDeserializingCollection(targetType);
                // Emit newobj, newarr, or call ValueType..ctor()
                Emittion.EmitConstruction(
                    il,
                    collection,
                    il0 => Emittion.EmitGetUnpackerItemsCountAsInt32(il0, 1, localHolder)
                    );

                EmitInvokeArrayUnpackToHelper(targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdloc(collection));

                il.EmitAnyLdloc(collection);
                il.EmitRet();
            }
            finally
            {
                il.FlushTrace();
            }
        }
        private static void CreateArrayUnpackFrom(Type targetType, SerializerEmitter emitter, CollectionTraits traits)
        {
            Action <TracingILGenerator> initialCountLoadingEmitter  = null;
            TracingILGenerator          unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();
            LocalVariableHolder         localHolder = new LocalVariableHolder(unpackFromMethodILGenerator);

            try
            {
                LocalBuilder collection;
                if (targetType.IsInterface || targetType.IsAbstract)
                {
                    unpackFromMethodILGenerator.EmitTypeOf(targetType);
                    unpackFromMethodILGenerator.EmitAnyCall(SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractTypeMethod);
                    unpackFromMethodILGenerator.EmitThrow();
                }
                else
                {
                    unpackFromMethodILGenerator.EmitAnyLdarg(1);
                    unpackFromMethodILGenerator.EmitGetProperty(_Unpacker.IsArrayHeader);
                    Label target = unpackFromMethodILGenerator.DefineLabel("END_IF");
                    unpackFromMethodILGenerator.EmitBrtrue_S(target);
                    unpackFromMethodILGenerator.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod);
                    unpackFromMethodILGenerator.EmitThrow();
                    unpackFromMethodILGenerator.MarkLabel(target);
                    collection = localHolder.GetDeserializingCollection(targetType);
                    if (initialCountLoadingEmitter == null)
                    {
                        initialCountLoadingEmitter = il0 => Emittion.EmitGetUnpackerItemsCountAsInt32(il0, 1, localHolder);
                    }
                    Emittion.EmitConstruction(unpackFromMethodILGenerator, collection, initialCountLoadingEmitter);
                    EmitInvokeArrayUnpackToHelper(targetType, emitter, traits, unpackFromMethodILGenerator, 1, il0 => il0.EmitAnyLdloc(collection));
                    unpackFromMethodILGenerator.EmitAnyLdloc(collection);
                    unpackFromMethodILGenerator.EmitRet();
                }
            }
            finally
            {
                unpackFromMethodILGenerator.FlushTrace();
            }
        }
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder)
        {
            LocalBuilder itemsCount = localHolder.ItemsCount;
            LocalBuilder local      = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);
            for (int i = 0; i < entries.Length; i++)
            {
                Label endOfDeserialization = unpackerIL.DefineLabel("END_IF");
                Label target = unpackerIL.DefineLabel("ELSE");
                unpackerIL.EmitAnyLdloc(local);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBlt(target);
                if (entries[i].Member != null)
                {
                    Emittion.EmitNilImplication(unpackerIL, 1, entries[i].Contract.Name, entries[i].Contract.NilImplication, endOfDeserialization, localHolder);
                }
                unpackerIL.EmitBr(endOfDeserialization);
                unpackerIL.MarkLabel(target);
                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                }
                else if (UnpackHelpers.IsReadOnlyAppendableCollectionMember(entries[i].Member))
                {
                    Emittion.EmitDeserializeCollectionValue(emitter, unpackerIL, 1, result, entries[i].Member, entries[i].Member.GetMemberValueType(), entries[i].Contract.NilImplication, localHolder);
                }
                else
                {
                    Emittion.EmitDeserializeValue(emitter, unpackerIL, 1, result, entries[i], localHolder);
                }
                unpackerIL.EmitAnyLdloc(local);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(local);
                unpackerIL.MarkLabel(endOfDeserialization);
            }
        }
Esempio n. 5
0
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder, Label endOfDeserialization)
        {
            /*
             *  int unpacked = 0;
             *  int itemsCount = unpacker.ItemsCount;
             *
             *  :
             *  if( unpacked >= itemsCount )
             *  {
             *		HandleNilImplication(...);
             *  }
             *  else
             *  {
             *  #if PRIMITIVE
             *		if( !unpacker.ReadT( out local1 ) )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *  #else
             *		if( !unpacker.Read() )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *
             *		local1 = this._serializer1.Unpack
             *	#endif
             *		unpacked++;
             *	}
             *	:
             */

            // TODO: Supports ExtensionObject like round-tripping.

            var itemsCount = localHolder.ItemsCount;
            var unpacked   = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);

            for (int i = 0; i < entries.Length; i++)
            {
                var endIf0 = unpackerIL.DefineLabel("END_IF");
                var else0  = unpackerIL.DefineLabel("ELSE");

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBge(else0);

                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                    // Ignore undefined member -- Nop.
                }
                else if (UnpackHelpers.IsReadOnlyAppendableCollectionMember(entries[i].Member))
                {
                    Emittion.EmitDeserializeCollectionValue(
                        emitter,
                        unpackerIL,
                        1,
                        result,
                        entries[i].Member,
                        entries[i].Member.GetMemberValueType(),
                        entries[i].Contract.NilImplication,
                        localHolder
                        );
                }
                else
                {
                    Emittion.EmitDeserializeValue(
                        emitter,
                        unpackerIL,
                        1,
                        result,
                        entries[i],
                        localHolder
                        );
                }

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(unpacked);

                unpackerIL.EmitBr(endIf0);

                unpackerIL.MarkLabel(else0);

                if (entries[i].Member != null)
                {
                    // Respect nil implication.
                    switch (entries[i].Contract.NilImplication)
                    {
                    case NilImplication.MemberDefault:
                    {
                        unpackerIL.EmitBr(endOfDeserialization);
                        break;
                    }

                    case NilImplication.Null:
                    {
                        if (entries[i].Member.GetMemberValueType().GetIsValueType())
                        {
                            if (Nullable.GetUnderlyingType(entries[i].Member.GetMemberValueType()) == null)
                            {
                                // val type

                                /*
                                 * if( value == null )
                                 * {
                                 *		throw SerializationEceptions.NewValueTypeCannotBeNull( "...", typeof( MEMBER ), typeof( TYPE ) );
                                 * }
                                 */
                                unpackerIL.EmitLdstr(entries[i].Contract.Name);
                                unpackerIL.EmitLdtoken(entries[i].Member.GetMemberValueType());
                                unpackerIL.EmitAnyCall(Metadata._Type.GetTypeFromHandle);
                                unpackerIL.EmitLdtoken(entries[i].Member.DeclaringType);
                                unpackerIL.EmitAnyCall(Metadata._Type.GetTypeFromHandle);
                                unpackerIL.EmitAnyCall(SerializationExceptions.NewValueTypeCannotBeNull3Method);
                                unpackerIL.EmitThrow();
                            }
                            else
                            {
                                // nullable
                                unpackerIL.EmitAnyLdloca(localHolder.GetDeserializedValue(entries[i].Member.GetMemberValueType()));
                                unpackerIL.EmitInitobj(entries[i].Member.GetMemberValueType());
                                unpackerIL.EmitAnyLdloc(result);
                                unpackerIL.EmitAnyLdloc(localHolder.GetDeserializedValue(entries[i].Member.GetMemberValueType()));
                                Emittion.EmitStoreValue(unpackerIL, entries[i].Member);
                            }
                        }
                        else
                        {
                            // ref type
                            unpackerIL.EmitAnyLdloc(result);
                            unpackerIL.EmitLdnull();
                            Emittion.EmitStoreValue(unpackerIL, entries[i].Member);
                        }

                        break;
                    }

                    case NilImplication.Prohibit:
                    {
                        unpackerIL.EmitLdstr(entries[i].Contract.Name);
                        unpackerIL.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                        unpackerIL.EmitThrow();
                        break;
                    }
                    }
                }

                unpackerIL.MarkLabel(endIf0);
            }
        }
Esempio n. 6
0
        private static void CreateTupleUnpackFrom(SerializerEmitter emitter, IList <Type> itemTypes)
        {
            var il          = emitter.GetUnpackFromMethodILGenerator();
            var localHolder = new LocalVariableHolder(il);

            try
            {
                /*
                 *  checked
                 *  {
                 *      if (!unpacker.IsArrayHeader)
                 *      {
                 *          throw SerializationExceptions.NewIsNotArrayHeader();
                 *      }
                 *
                 *      if ((int)unpacker.ItemsCount != n)
                 *      {
                 *          throw SerializationExceptions.NewTupleCardinarityIsNotMatch(n, (int)unpacker.ItemsCount);
                 *      }
                 *
                 *		if (!unpacker.Read())
                 *		{
                 *			throw SerializationExceptions.NewMissingItem(0);
                 *		}
                 *
                 *		DESERIALIZE_VALUE
                 *
                 *			:
                 *
                 *		return new Tuple<...>( item1, ... , new Tuple<...>(...)...);
                 *	}
                 */

                il.EmitAnyLdarg(1);
                il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader);
                var endIf = il.DefineLabel("END_IF");
                il.EmitBrtrue_S(endIf);
                il.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod);
                il.EmitThrow();
                il.MarkLabel(endIf);

                var itemsCount = localHolder.ItemsCount;
                Emittion.EmitGetUnpackerItemsCountAsInt32(il, 1, localHolder);
                il.EmitAnyLdc_I4(itemTypes.Count);
                il.EmitAnyStloc(itemsCount);
                il.EmitAnyLdloc(itemsCount);
                var endIf1 = il.DefineLabel("END_IF1");
                il.EmitBeq_S(endIf1);
                il.EmitAnyLdc_I4(itemTypes.Count);
                il.EmitAnyLdloc(itemsCount);
                il.EmitAnyCall(SerializationExceptions.NewTupleCardinarityIsNotMatchMethod);
                il.EmitThrow();
                il.MarkLabel(endIf1);

                var itemLocals        = new LocalBuilder[itemTypes.Count];
                var useDummyNullables = new bool[itemTypes.Count];

                for (int i = 0; i < itemTypes.Count; i++)
                {
                    if (itemTypes[i] != typeof(MessagePackObject) &&
                        itemTypes[i].GetIsValueType() &&
                        Nullable.GetUnderlyingType(itemTypes[i]) == null)
                    {
                        // Use temporary nullable value for nil implication.
                        itemLocals[i]        = il.DeclareLocal(typeof(Nullable <>).MakeGenericType(itemTypes[i]), "item" + i.ToString(CultureInfo.InvariantCulture));
                        useDummyNullables[i] = true;
                    }
                    else
                    {
                        itemLocals[i] = il.DeclareLocal(itemTypes[i], "item" + i.ToString(CultureInfo.InvariantCulture));
                    }

                    // Tuple member should be NilImplication.MemberDefault.
                    Emittion.EmitDeserializeValueWithoutNilImplication(emitter, il, 1, itemLocals[i], typeof(Tuple), "Item" + (i).ToString(CultureInfo.InvariantCulture), localHolder);
                }

                for (int i = 0; i < itemLocals.Length; i++)
                {
                    if (useDummyNullables[i])
                    {
                        il.EmitAnyLdloca(itemLocals[i]);
                        il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(itemTypes[i]).GetProperty("Value"));
                    }
                    else
                    {
                        il.EmitAnyLdloc(itemLocals[i]);
                    }
                }

                var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes);

                for (int depth = tupleTypeList.Count - 1; 0 <= depth; depth--)
                {
                    il.EmitNewobj(tupleTypeList[depth].GetConstructors().Single());
                }

                il.EmitRet();
            }
            finally
            {
                il.FlushTrace();
            }
        }
Esempio n. 7
0
        private static void EmitUnpackMembersFromArray(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder)
        {
            /*
             *  int unpacked = 0;
             *  int itemsCount = unpacker.ItemsCount;
             *
             *  :
             *  if( unpacked == itemsCount )
             *  {
             *		HandleNilImplication(...);
             *  }
             *  else
             *  {
             *  #if PRIMITIVE
             *		if( !unpacker.ReadT( out local1 ) )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *  #else
             *		if( !unpacker.Read() )
             *		{
             *			throw SerializationExceptions.NewUnexpectedEndOfStreamMethod();
             *		}
             *
             *		local1 = this._serializer1.Unpack
             *	#endif
             *		unpacked++;
             *	}
             *	:
             */

            // TODO: Supports ExtensionObject like round-tripping.

            var itemsCount = localHolder.ItemsCount;
            var unpacked   = unpackerIL.DeclareLocal(typeof(int), "unpacked");

            Emittion.EmitGetUnpackerItemsCountAsInt32(unpackerIL, 1, localHolder);
            unpackerIL.EmitAnyStloc(itemsCount);

            for (int i = 0; i < entries.Length; i++)
            {
                var endIf0 = unpackerIL.DefineLabel("END_IF");
                var else0  = unpackerIL.DefineLabel("ELSE");

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitAnyLdloc(itemsCount);
                unpackerIL.EmitBlt(else0);
                // Tail missing member handling.
                if (entries[i].Member != null)
                {
                    // Respect nil implication.
                    Emittion.EmitNilImplication(unpackerIL, 1, entries[i].Contract.Name, entries[i].Contract.NilImplication, endIf0, localHolder);
                }

                unpackerIL.EmitBr(endIf0);

                unpackerIL.MarkLabel(else0);

                if (entries[i].Member == null)
                {
                    Emittion.EmitGeneralRead(unpackerIL, 1);
                    // Ignore undefined member -- Nop.
                }
                else if (UnpackHelpers.IsReadOnlyAppendableCollectionMember(entries[i].Member))
                {
                    Emittion.EmitDeserializeCollectionValue(
                        emitter,
                        unpackerIL,
                        1,
                        result,
                        entries[i].Member,
                        entries[i].Member.GetMemberValueType(),
                        entries[i].Contract.NilImplication,
                        localHolder
                        );
                }
                else
                {
                    Emittion.EmitDeserializeValue(
                        emitter,
                        unpackerIL,
                        1,
                        result,
                        entries[i],
                        localHolder
                        );
                }

                unpackerIL.EmitAnyLdloc(unpacked);
                unpackerIL.EmitLdc_I4_1();
                unpackerIL.EmitAdd();
                unpackerIL.EmitAnyStloc(unpacked);

                unpackerIL.MarkLabel(endIf0);
            }
        }