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();
            }
        }
Esempio n. 4
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();
            }
        }
		private static void CreateTupleUnpackFrom( SerializerEmitter emitter, IList<Type> itemTypes )
		{
			var il = emitter.GetUnpackFromMethodILGenerator();
			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);
				 *		}
				 *		
				 *		T1 item1;
				 *		if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader)
				 *		{
				 *			item1 = this._serializer0.UnpackFrom(unpacker);
				 *		}
				 *		else
				 *		{
				 *			using (Unpacker subtreeUnpacker = unpacker.ReadSubtree())
				 *			{
				 *				item1 = this._serializer0.UnpackFrom(subtreeUnpacker);
				 *			}
				 *		}
				 *		
				 *		if (!unpacker.Read())
				 *			:
				 *		
				 *		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 = il.DeclareLocal( typeof( int ), "itemsCount" );
				Emittion.EmitGetUnpackerItemsCountAsInt32( il, 1 );
				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 );

				LocalBuilder[] itemLocals = new LocalBuilder[ itemTypes.Count ];
				int i = 0;
				Action<TracingILGenerator, int> unpackerReading =
					( il1, unpacker ) =>
					{
						il1.EmitAnyLdarg( unpacker );
						il1.EmitAnyCall( Metadata._Unpacker.Read );
						var endIf0 = il1.DefineLabel( "END_IF0" );
						il1.EmitBrtrue_S( endIf0 );
						il1.EmitAnyLdc_I4( i );
						il1.EmitAnyCall( SerializationExceptions.NewMissingItemMethod );
						il1.EmitThrow();
						il1.MarkLabel( endIf0 );
					};

				for ( ; i < itemTypes.Count; i++ )
				{
					itemLocals[ i ] = il.DeclareLocal( itemTypes[ i ], "item" + i );
					Emittion.EmitDeserializeValue( emitter, il, 1, itemLocals[ i ], NilImplication.MemberDefault, unpackerReading );
				}

				foreach ( var item in itemLocals )
				{
					il.EmitAnyLdloc( item );
				}

				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();
			}
		}
		private static void CreateMapUnpackFrom( Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			var il = emitter.GetUnpackFromMethodILGenerator();
			try
			{
				/*
				 *	if (!unpacker.IsMapHeader)
				 *	{
				 *		throw SerializationExceptions.NewIsNotMapHeader();
				 *	}
				 *	
				 *	TDictionary<TKey, TValue> dictionary = new ...;
				 *	this.UnpackToCore(unpacker, dictionary);
				 *	return dictionary;
				 */

				if ( targetType.IsInterface || targetType.IsAbstract )
				{
					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 = il.DeclareLocal( targetType, "collection" );
				Emittion.EmitConstruction(
					il,
					collection,
					il0 => Emittion.EmitGetUnpackerItemsCountAsInt32( il0, 1 )
				);

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

				il.EmitAnyLdloc( collection );
				il.EmitRet();
			}
			finally
			{
				il.FlushTrace();
			}
		}
		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();
			}
		}
		private static void CreateArrayUnpackFrom( SerializationContext context, Type targetType, SerializerEmitter emitter, CollectionTraits traits )
		{
			var il = emitter.GetUnpackFromMethodILGenerator();
			var localHolder = new LocalVariableHolder( il );
			var instanceType = targetType;

			try
			{
				if ( targetType.IsInterface || targetType.IsAbstract )
				{
					instanceType = context.DefaultCollectionTypes.GetConcreteType( targetType );
					if ( instanceType == null )
					{
						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( instanceType );
				// 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();
			}
		}
        protected sealed override MessagePackSerializer <TObject> CreateSerializer(SerializingMember[] entries)
        {
            MessagePackSerializer <TObject> serializer;

            using (SerializerEmitter emitter = this._generatorManager.CreateEmitter(typeof(TObject), this._emitterFlavor))
            {
                try
                {
                    TracingILGenerator packToMethodILGenerator = emitter.GetPackToMethodILGenerator();
                    try
                    {
                        if (typeof(IPackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).IsValueType)
                            {
                                packToMethodILGenerator.EmitAnyLdarga(2);
                            }
                            else
                            {
                                packToMethodILGenerator.EmitAnyLdarg(2);
                            }
                            packToMethodILGenerator.EmitAnyLdarg(1);
                            packToMethodILGenerator.EmitLdnull();
                            packToMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single <MethodInfo>());
                            packToMethodILGenerator.EmitRet();
                        }
                        else
                        {
                            this.EmitPackMembers(emitter, packToMethodILGenerator, entries);
                        }
                    }
                    finally
                    {
                        packToMethodILGenerator.FlushTrace();
                    }
                    TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator();
                    try
                    {
                        LocalBuilder target = unpackFromMethodILGenerator.DeclareLocal(typeof(TObject), "result");
                        Emittion.EmitConstruction(unpackFromMethodILGenerator, target, null);
                        if (typeof(IUnpackable).IsAssignableFrom(typeof(TObject)))
                        {
                            if (typeof(TObject).GetIsValueType())
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloca(target);
                            }
                            else
                            {
                                unpackFromMethodILGenerator.EmitAnyLdloc(target);
                            }
                            unpackFromMethodILGenerator.EmitAnyLdarg(1);
                            unpackFromMethodILGenerator.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single <MethodInfo>());
                        }
                        else
                        {
                            EmittingSerializerBuilder <TObject> .EmitUnpackMembers(emitter, unpackFromMethodILGenerator, entries, target);
                        }
                        unpackFromMethodILGenerator.EmitAnyLdloc(target);
                        unpackFromMethodILGenerator.EmitRet();
                    }
                    finally
                    {
                        unpackFromMethodILGenerator.FlushTrace();
                    }
                    serializer = emitter.CreateInstance <TObject>(base.Context);
                }
                finally
                {
                    emitter.FlushTrace();
                }
            }
            return(serializer);
        }