private static void CreatePacking(SerializerEmitter emitter) { Action <TracingILGenerator> loadValueEmitter = null; TracingILGenerator il = emitter.GetPackToMethodILGenerator(); try { Label target = il.DefineLabel("END_IF"); Label label2 = il.DefineLabel("END_METHOD"); il.EmitAnyLdarga(2); il.EmitGetProperty(NullableMessagePackSerializer <T> ._nullableTHasValueProperty); il.EmitBrtrue_S(target); il.EmitAnyLdarg(1); il.EmitAnyCall(NullableMessagePackSerializer.PackerPackNull); il.EmitPop(); il.EmitBr_S(label2); il.MarkLabel(target); if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il0) { il0.EmitAnyLdarga(2); il.EmitGetProperty(NullableMessagePackSerializer <T> ._nullableTValueProperty); }; } Emittion.EmitSerializeValue(emitter, il, 1, NullableMessagePackSerializer <T> ._nullableTValueProperty.PropertyType, null, NilImplication.MemberDefault, loadValueEmitter, new LocalVariableHolder(il)); il.MarkLabel(label2); il.EmitRet(); } finally { il.FlushTrace(); emitter.FlushTrace(); } }
internal NullableMessagePackSerializer(SerializationContext context, EmitterFlavor emitterFlavor) { if (context == null) { throw new ArgumentNullException("context"); } if (NullableMessagePackSerializer <T> ._nullableTImplicitOperator == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "'{0}' is not nullable type.", new object[] { typeof(T) })); } SerializerEmitter emitter = SerializationMethodGeneratorManager.Get().CreateEmitter(typeof(T), emitterFlavor); NullableMessagePackSerializer <T> .CreatePacking(emitter); NullableMessagePackSerializer <T> .CreateUnpacking(emitter); this._underlying = emitter.CreateInstance <T>(context); }
private static void CreateUnpacking(SerializerEmitter emitter) { TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator(); try { LocalBuilder local = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject?), "mayBeNullData"); LocalBuilder builder2 = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject), "data"); LocalBuilder builder3 = unpackFromMethodILGenerator.DeclareLocal(typeof(T), "result"); LocalBuilder result = unpackFromMethodILGenerator.DeclareLocal(NullableMessagePackSerializer <T> ._nullableTValueProperty.PropertyType, "value"); Label target = unpackFromMethodILGenerator.DefineLabel("END_IF"); Label label2 = unpackFromMethodILGenerator.DefineLabel("END_METHOD"); unpackFromMethodILGenerator.EmitAnyLdarg(1); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.UnpackerDataProperty); unpackFromMethodILGenerator.EmitAnyStloc(local); unpackFromMethodILGenerator.EmitAnyLdloca(local); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.Nullable_MessagePackObject_ValueProperty); unpackFromMethodILGenerator.EmitAnyStloc(builder2); unpackFromMethodILGenerator.EmitAnyLdloca(builder2); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.MessagePackObject_IsNilProperty); unpackFromMethodILGenerator.EmitBrfalse_S(target); unpackFromMethodILGenerator.EmitAnyLdloca(builder3); unpackFromMethodILGenerator.EmitInitobj(builder3.LocalType); unpackFromMethodILGenerator.EmitBr_S(label2); unpackFromMethodILGenerator.MarkLabel(target); Emittion.EmitUnpackFrom(emitter, unpackFromMethodILGenerator, result, 1); unpackFromMethodILGenerator.EmitAnyLdloc(result); unpackFromMethodILGenerator.EmitAnyCall(NullableMessagePackSerializer <T> ._nullableTImplicitOperator); unpackFromMethodILGenerator.EmitAnyStloc(builder3); unpackFromMethodILGenerator.MarkLabel(label2); unpackFromMethodILGenerator.EmitAnyLdloc(builder3); unpackFromMethodILGenerator.EmitRet(); } finally { unpackFromMethodILGenerator.FlushTrace(); emitter.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 ], null, null, 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 CreateTupleUnpack( SerializerEmitter emitter, IList<Type> itemTypes ) { CreateTupleUnpackFrom( emitter, itemTypes ); }
private static void CreateTuplePack( SerializerEmitter emiter, Type tupleType, IList<Type> itemTypes, Action<TracingILGenerator, LocalBuilder> loadTupleEmitter ) { var il = emiter.GetPackToMethodILGenerator(); try { /* * packer.PackArrayHeader( cardinarity ); * _serializer0.PackTo( packer, tuple.Item1 ); * : * _serializer6.PackTo( packer, tuple.item7 ); * _serializer7.PackTo( packer, tuple.Rest.Item1 ); */ var tuple = il.DeclareLocal( tupleType, "tuple" ); loadTupleEmitter( il, tuple ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdc_I4( itemTypes.Count ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); var tupleTypeList = TupleItems.CreateTupleTypeList( itemTypes ); int depth = -1; for ( int i = 0; i < itemTypes.Count; i++ ) { if ( i % 7 == 0 ) { depth++; } Emittion.EmitSerializeValue( emiter, il, 1, itemTypes[ i ], null, NilImplication.MemberDefault, il0 => { il0.EmitAnyLdloc( tuple ); for ( int j = 0; j < depth; j++ ) { // .TRest.TRest ... var rest = tupleTypeList[ j ].GetProperty( "Rest" ); il0.EmitGetProperty( rest ); } var itemn = tupleTypeList[ depth ].GetProperty( "Item" + ( ( i % 7 ) + 1 ) ); #if DEBUG Contract.Assert( itemn != null, tupleTypeList[ depth ].GetFullName() + "::Item" + ( ( i % 7 ) + 1 ) + " [ " + depth + " ] @ " + i ); #endif il0.EmitGetProperty( itemn ); } ); } il.EmitRet(); } finally { il.FlushTrace(); } }
private static void EmitInvokeMapUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting ) { il.EmitAnyLdarg( unpackerArgumentIndex ); if ( traits.ElementType.IsGenericType ) { var keyType = traits.ElementType.GetGenericArguments()[ 0 ]; var valueType = traits.ElementType.GetGenericArguments()[ 1 ]; var keySerializerGetting = emitter.RegisterSerializer( keyType ); var valueSerializerGetting = emitter.RegisterSerializer( valueType ); keySerializerGetting( il, 0 ); valueSerializerGetting( il, 0 ); loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } il.EmitAnyCall( Metadata._UnpackHelpers.UnpackMapTo_2.MakeGenericMethod( keyType, valueType ) ); } else { loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericMapTo ); } }
private static void CreateMapUnpackTo( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetUnpackToMethodILGenerator(); try { EmitInvokeMapUnpackToHelper( targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdarg( 2 ) ); il.EmitRet(); } finally { il.FlushTrace(); } }
public static void EmitDeserializeValue( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, LocalBuilder isUnpacked, string memberName, NilImplication nilImplication, Action<TracingILGenerator, int> customUnpackerReading ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( unpackerArgumentIndex >= 0 ); Contract.Requires( value != null ); if ( customUnpackerReading != null ) { customUnpackerReading( il, unpackerArgumentIndex ); } var endOfDeserialization = il.DefineLabel( "END_OF_DESERIALIZATION" ); if ( memberName != null ) { switch ( nilImplication ) { case NilImplication.MemberDefault: { /* * if( unpacker.Data.Value.IsNil ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.Data ); var data = il.DeclareLocal( typeof( MessagePackObject? ), "data" ); il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._Nullable<MessagePackObject>.Value ); var dataValue = il.DeclareLocal( typeof( MessagePackObject ), "dataValue" ); il.EmitAnyStloc( dataValue ); il.EmitAnyLdloca( dataValue ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); il.EmitBrtrue( endOfDeserialization ); break; } case NilImplication.Prohibit: { /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.Data ); var data = il.DeclareLocal( typeof( MessagePackObject? ), "data" ); il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._Nullable<MessagePackObject>.Value ); var dataValue = il.DeclareLocal( typeof( MessagePackObject ), "dataValue" ); il.EmitAnyStloc( dataValue ); il.EmitAnyLdloca( dataValue ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); var endIf0 = il.DefineLabel( "END_IF0" ); il.EmitBrfalse_S( endIf0 ); il.EmitLdstr( memberName ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); il.MarkLabel( endIf0 ); break; } } } /* * * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree ) * { * valueN = GET_SERIALIZER.UnpackFrom( unpacker ); * } * } * * isValueNUnpacked = true; * END_OF_DESERIALIZATION: */ var then = il.DefineLabel( "THEN" ); var endIf = il.DefineLabel( "END_IF" ); var serializerGetter = emitter.RegisterSerializer( value.LocalType ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsArrayHeader ); il.EmitBrtrue_S( then ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsMapHeader ); il.EmitBrtrue_S( then ); // else serializerGetter( il, 0 ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitAnyCall( typeof( MessagePackSerializer<> ).MakeGenericType( value.LocalType ).GetMethod( "UnpackFrom" ) ); il.EmitAnyStloc( value ); il.EmitBr_S( endIf ); // then var subtreeUnpacker = il.DeclareLocal( typeof( Unpacker ), "subtreeUnpacker" ); il.MarkLabel( then ); EmitUnpackerBeginReadSubtree( il, unpackerArgumentIndex, subtreeUnpacker ); serializerGetter( il, 0 ); il.EmitAnyLdloc( subtreeUnpacker ); il.EmitAnyCall( typeof( MessagePackSerializer<> ).MakeGenericType( value.LocalType ).GetMethod( "UnpackFrom" ) ); il.EmitAnyStloc( value ); EmitUnpackerEndReadSubtree( il, subtreeUnpacker ); il.MarkLabel( endIf ); if ( isUnpacked != null ) { il.EmitLdc_I4_1(); il.EmitAnyStloc( isUnpacked ); } il.MarkLabel( endOfDeserialization ); }
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 CreateMapUnpack( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateMapUnpackFrom( targetType, emitter, traits ); CreateMapUnpackTo( targetType, emitter, traits ); }
private static void CreateMapPack( Type targetType, SerializerEmitter emiter, CollectionTraits traits ) { var il = emiter.GetPackToMethodILGenerator(); try { /* * int count = ((ICollection<KeyValuePair<string, DateTime>>)dictionary).Count; * packer.PackMapHeader(count); * foreach (KeyValuePair<string, DateTime> current in dictionary) * { * this._serializer0.PackTo(packer, current.Key); * this._serializer1.PackTo(packer, current.Value); * } */ var collection = il.DeclareLocal( targetType, "collection" ); var item = il.DeclareLocal( traits.ElementType, "item" ); var keyProperty = traits.ElementType.GetProperty( "Key" ); var valueProperty = traits.ElementType.GetProperty( "Value" ); // This instruction is always ldarg, not to be ldarga. il.EmitAnyLdarg( 2 ); il.EmitAnyStloc( collection ); var count = il.DeclareLocal( typeof( int ), "count" ); EmitLoadTarget( targetType, il, collection ); il.EmitGetProperty( traits.CountProperty ); il.EmitAnyStloc( count ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( count ); il.EmitAnyCall( Metadata._Packer.PackMapHeader ); il.EmitPop(); Emittion.EmitForEach( il, traits, collection, ( il0, getCurrentEmitter ) => { if ( traits.ElementType.IsGenericType ) { Contract.Assert( traits.ElementType.GetGenericTypeDefinition() == typeof( KeyValuePair<,> ) ); getCurrentEmitter(); il0.EmitAnyStloc( item ); Emittion.EmitSerializeValue( emiter, il0, 1, traits.ElementType.GetGenericArguments()[ 0 ], null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloca( item ); il1.EmitGetProperty( keyProperty ); } ); Emittion.EmitSerializeValue( emiter, il0, 1, traits.ElementType.GetGenericArguments()[ 1 ], null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloca( item ); il1.EmitGetProperty( valueProperty ); } ); } else { Contract.Assert( traits.ElementType == typeof( DictionaryEntry ) ); getCurrentEmitter(); il0.EmitAnyStloc( item ); Emittion.EmitSerializeValue( emiter, il0, 1, typeof( MessagePackObject ), null, NilImplication.MemberDefault, il1 => { il0.EmitAnyLdloca( item ); il0.EmitGetProperty( Metadata._DictionaryEntry.Key ); il0.EmitUnbox_Any( typeof( MessagePackObject ) ); } ); Emittion.EmitSerializeValue( emiter, il0, 1, typeof( MessagePackObject ), null, NilImplication.MemberDefault, il1 => { il0.EmitAnyLdloca( item ); il0.EmitGetProperty( Metadata._DictionaryEntry.Value ); il0.EmitUnbox_Any( typeof( MessagePackObject ) ); } ); } } ); il.EmitRet(); } finally { il.FlushTrace(); } }
private static void EmitInvokeArrayUnpackToHelper( Type targetType, SerializerEmitter emitter, CollectionTraits traits, TracingILGenerator il, int unpackerArgumentIndex, Action<TracingILGenerator> loadCollectionEmitting ) { il.EmitAnyLdarg( unpackerArgumentIndex ); var serializerGetting = emitter.RegisterSerializer( traits.ElementType ); if ( targetType.IsArray ) { // Array /* * UnpackHelpers.UnpackArrayTo( unpacker, GET_SERIALIZER, collection ); */ serializerGetting( il, 0 ); loadCollectionEmitting( il ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackArrayTo_1.MakeGenericMethod( traits.ElementType ) ); } else if ( targetType.IsGenericType ) { serializerGetting( il, 0 ); loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) ) { // with void Add( T item ) /* * Action<T> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition ); */ var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<> ).MakeGenericType( itemType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_1.MakeGenericMethod( itemType ) ); } else { // with TDiscarded Add( T item ) /* * Func<T, TDiscarded> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, GET_SERIALIZER, collection, addition ); */ var itemType = traits.AddMethod.GetParameters()[ 0 ].ParameterType; var discardingType = traits.AddMethod.ReturnType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( itemType, discardingType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackCollectionTo_2.MakeGenericMethod( itemType, discardingType ) ); } } else { loadCollectionEmitting( il ); if ( targetType.IsValueType ) { il.EmitBox( targetType ); } if ( traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof( void ) ) { // with void Add( object item ) /* * Action<object> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition ); */ EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Action<object> ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo ); } else { // with TDiscarded Add( object item ) /* * Func<TDiscarded> addition = TCollection.Add * UnpackHelpers.UnpackCollectionTo( unpacker, collection, addition ); */ var discardingType = traits.AddMethod.ReturnType; EmitNewDelegate( il, targetType, traits.AddMethod, loadCollectionEmitting, typeof( Func<,> ).MakeGenericType( typeof( object ), discardingType ) ); il.EmitAnyCall( Metadata._UnpackHelpers.UnpackNonGenericCollectionTo_1.MakeGenericMethod( discardingType ) ); } } }
private static void CreateUnpackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateArrayUnpackFrom( targetType, emitter, traits ); CreateArrayUnpackTo( targetType, emitter, traits ); }
public static void EmitDeserializeCollectionValue( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder target, MemberInfo member, Type memberType, NilImplication nilImplication ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( unpackerArgumentIndex >= 0 ); Contract.Requires( target != null ); Contract.Requires( member != null ); Contract.Requires( memberType != null ); var endOfDeserialization = il.DefineLabel( "END_OF_DESERIALIZATION" ); switch ( nilImplication ) { case NilImplication.MemberDefault: { /* * if( unpacker.Data.Value.IsNil ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.Data ); var data = il.DeclareLocal( typeof( MessagePackObject? ), "data" ); il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._Nullable<MessagePackObject>.Value ); var dataValue = il.DeclareLocal( typeof( MessagePackObject ), "dataValue" ); il.EmitAnyStloc( dataValue ); il.EmitAnyLdloca( dataValue ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); il.EmitBrtrue( endOfDeserialization ); break; } case NilImplication.Null: case NilImplication.Prohibit: { /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.Data ); var data = il.DeclareLocal( typeof( MessagePackObject? ), "data" ); il.EmitAnyStloc( data ); il.EmitAnyLdloca( data ); il.EmitGetProperty( Metadata._Nullable<MessagePackObject>.Value ); var dataValue = il.DeclareLocal( typeof( MessagePackObject ), "dataValue" ); il.EmitAnyStloc( dataValue ); il.EmitAnyLdloca( dataValue ); il.EmitGetProperty( Metadata._MessagePackObject.IsNil ); var endIf0 = il.DefineLabel( "END_IF0" ); il.EmitBrfalse_S( endIf0 ); il.EmitLdstr( member.Name ); if ( nilImplication == NilImplication.Prohibit ) { il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); } else { il.EmitAnyCall( SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNullMethod ); } il.EmitThrow(); il.MarkLabel( endIf0 ); break; } } /* * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * throw new SerializatonException( "Cannot deserialize..." ); * } * * using( var subtreeUnpacker = unpacker.ReadSubtree() ) * { * GET_SERIALIZER.UnpackTo( unpacker, target ) ) * } * * END_OF_DESERIALIZATION: */ var endIf = il.DefineLabel( "THEN" ); var serializerGetter = emitter.RegisterSerializer( memberType ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsArrayHeader ); il.EmitBrtrue_S( endIf ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsMapHeader ); il.EmitBrtrue_S( endIf ); // else il.EmitLdstr( member.Name ); il.EmitAnyCall( SerializationExceptions.NewStreamDoesNotContainCollectionForMemberMethod ); il.EmitThrow(); // then var subtreeUnpacker = il.DeclareLocal( typeof( Unpacker ), "subtreeUnpacker" ); il.MarkLabel( endIf ); EmitUnpackerBeginReadSubtree( il, unpackerArgumentIndex, subtreeUnpacker ); serializerGetter( il, 0 ); il.EmitAnyLdloc( subtreeUnpacker ); il.EmitAnyLdloc( target ); Emittion.EmitLoadValue( il, member ); il.EmitAnyCall( typeof( MessagePackSerializer<> ).MakeGenericType( memberType ).GetMethod( "UnpackTo", new[] { typeof( Unpacker ), memberType } ) ); EmitUnpackerEndReadSubtree( il, subtreeUnpacker ); il.MarkLabel( endOfDeserialization ); }
private static void CreatePackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { var il = emitter.GetPackToMethodILGenerator(); try { // Array if ( targetType.IsArray ) { /* * // array * packer.PackArrayHeader( length ); * for( int i = 0; i < length; i++ ) * { * this._serializer.PackTo( packer, collection[ i ] ); * } */ var length = il.DeclareLocal( typeof( int ), "length" ); il.EmitAnyLdarg( 2 ); il.EmitLdlen(); il.EmitAnyStloc( length ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( length ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitFor( il, length, ( il0, i ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdarg( 2 ); il1.EmitAnyLdloc( i ); il1.EmitLdelem( traits.ElementType ); } ); } ); } else if ( traits.CountProperty == null ) { /* * array = collection.ToArray(); * packer.PackArrayHeader( length ); * for( int i = 0; i < length; i++ ) * { * this._serializer.PackTo( packer, array[ i ] ); * } */ var array = il.DeclareLocal( traits.ElementType.MakeArrayType(), "array" ); EmitLoadTarget( targetType, il, 2 ); il.EmitAnyCall( Metadata._Enumerable.ToArray1Method.MakeGenericMethod( traits.ElementType ) ); il.EmitAnyStloc( array ); var length = il.DeclareLocal( typeof( int ), "length" ); il.EmitAnyLdloc( array ); il.EmitLdlen(); il.EmitAnyStloc( length ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( length ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitFor( il, length, ( il0, i ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloc( array ); il1.EmitAnyLdloc( i ); il1.EmitLdelem( traits.ElementType ); } ); } ); } else { /* * // Enumerable * packer.PackArrayHeader( collection.Count ); * foreach( var item in list ) * { * this._serializer.PackTo( packer, array[ i ] ); * } */ var collection = il.DeclareLocal( targetType, "collection" ); // This instruction always ldarg, not to be ldarga il.EmitAnyLdarg( 2 ); il.EmitAnyStloc( collection ); var count = il.DeclareLocal( typeof( int ), "count" ); EmitLoadTarget( targetType, il, 2 ); il.EmitGetProperty( traits.CountProperty ); il.EmitAnyStloc( count ); il.EmitAnyLdarg( 1 ); il.EmitAnyLdloc( count ); il.EmitAnyCall( Metadata._Packer.PackArrayHeader ); il.EmitPop(); Emittion.EmitForEach( il, traits, collection, ( il0, getCurrentEmitter ) => { Emittion.EmitSerializeValue( emitter, il0, 1, traits.ElementType, null, NilImplication.MemberDefault, _ => getCurrentEmitter() ); } ); } il.EmitRet(); } finally { il.FlushTrace(); } }
public static void EmitSerializeValue( SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action<TracingILGenerator> loadValueEmitter ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( packerArgumentIndex >= 0 ); Contract.Requires( valueType != null ); Contract.Requires( loadValueEmitter != null ); /* * var serializingValue = LOAD_VALUE; * NULL_PROHIBIT_HANDLING * GET_SERIALIZER.PackTo( packer, serializingValue ); */ var value = il.DeclareLocal( valueType, "serializingValue" ); loadValueEmitter( il ); il.EmitAnyStloc( value ); if ( memberName != null && nilImplication == NilImplication.Prohibit ) { /* * if( serializingValue == null )( * { * throw SerializationExceptions.NewNullIsProhibited(); * } */ if ( !valueType.IsValueType ) { il.EmitAnyLdloc( value ); var endIf = il.DefineLabel( "END_IF" ); il.EmitBrtrue_S( endIf ); il.EmitLdstr( memberName ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); il.MarkLabel( endIf ); } else if ( Nullable.GetUnderlyingType( valueType ) != null ) { il.EmitAnyLdloca( value ); il.EmitGetProperty( typeof( Nullable<> ).MakeGenericType( Nullable.GetUnderlyingType( valueType ) ).GetProperty( "HasValue" ) ); var endIf = il.DefineLabel( "END_IF" ); il.EmitBrtrue_S( endIf ); il.EmitLdstr( memberName ); il.EmitAnyCall( SerializationExceptions.NewNullIsProhibitedMethod ); il.EmitThrow(); il.MarkLabel( endIf ); } } var serializerGetter = emitter.RegisterSerializer( valueType ); serializerGetter( il, 0 ); il.EmitAnyLdarg( packerArgumentIndex ); il.EmitAnyLdloc( value ); il.EmitAnyCall( typeof( MessagePackSerializer<> ).MakeGenericType( valueType ).GetMethod( "PackTo" ) ); }