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(); } }
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(); } }
protected override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { var localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(Metadata._Packer.PackArrayHeader); packerIL.EmitPop(); foreach (var member in entries) { if (member.Member == null) { // missing member, always nil packerIL.EmitAnyLdarg(1); packerIL.EmitAnyCall(Metadata._Packer.PackNull); packerIL.EmitPop(); } else { Emittion.EmitSerializeValue( emitter, packerIL, 1, member.Member.GetMemberValueType(), member.Member.Name, member.Contract.NilImplication, il => { if (typeof(TObject).IsValueType) { il.EmitAnyLdarga(2); } else { il.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il, member.Member); }, localHolder ); } } packerIL.EmitRet(); }
protected sealed override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { var localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(Metadata._Packer.PackMapHeader); packerIL.EmitPop(); foreach (var entry in entries) { if (entry.Member == null) { // skip undefined member. continue; } packerIL.EmitAnyLdarg(1); packerIL.EmitLdstr(entry.Contract.Name); packerIL.EmitAnyCall(Metadata._Packer.PackString); packerIL.EmitPop(); Emittion.EmitSerializeValue( emitter, packerIL, 1, entry.Member.GetMemberValueType(), entry.Contract.Name, entry.Contract.NilImplication, il0 => { if (typeof(TObject).IsValueType) { il0.EmitAnyLdarga(2); } else { il0.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il0, entry.Member); }, localHolder ); } packerIL.EmitRet(); }
private static void EmitUnpackMembersFromMap(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder) { Label label = unpackerIL.DefineLabel("BEGIN_LOOP"); Label target = unpackerIL.DefineLabel("END_LOOP"); unpackerIL.MarkLabel(label); LocalBuilder memberName = localHolder.MemberName; unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitAnyLdloca(memberName); unpackerIL.EmitAnyCall(_Unpacker.ReadString); unpackerIL.EmitBrfalse(target); LocalBuilder unpackedData = localHolder.UnpackedData; LocalBuilder unpackedDataValue = localHolder.UnpackedDataValue; for (int i = 0; i < entries.Length; i++) { if (entries[i].Contract.Name != null) { unpackerIL.EmitAnyLdloc(memberName); unpackerIL.EmitLdstr(entries[i].Contract.Name); unpackerIL.EmitAnyCall(_String.op_Equality); Label label3 = unpackerIL.DefineLabel("END_IF_MEMBER_" + i); unpackerIL.EmitBrfalse(label3); 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.EmitBr(label); unpackerIL.MarkLabel(label3); } } unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitCallvirt(_Unpacker.Read); unpackerIL.EmitPop(); unpackerIL.EmitBr(label); unpackerIL.MarkLabel(target); }
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(); } }
protected override void EmitPackMembers(SerializerEmitter emitter, TracingILGenerator packerIL, SerializingMember[] entries) { LocalVariableHolder localHolder = new LocalVariableHolder(packerIL); packerIL.EmitAnyLdarg(1); packerIL.EmitAnyLdc_I4(entries.Length); packerIL.EmitAnyCall(_Packer.PackArrayHeader); packerIL.EmitPop(); SerializingMember[] memberArray = entries; for (int i = 0; i < memberArray.Length; i++) { Action <TracingILGenerator> loadValueEmitter = null; SerializingMember member = memberArray[i]; if (member.Member == null) { packerIL.EmitAnyLdarg(1); packerIL.EmitAnyCall(_Packer.PackNull); packerIL.EmitPop(); } else { if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il) { if (typeof(TObject).IsValueType) { il.EmitAnyLdarga(2); } else { il.EmitAnyLdarg(2); } Emittion.EmitLoadValue(il, member.Member); }; } Emittion.EmitSerializeValue(emitter, packerIL, 1, member.Member.GetMemberValueType(), member.Member.Name, member.Contract.NilImplication, loadValueEmitter, localHolder); } } packerIL.EmitRet(); }
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); } }
private static void CreateMapPack(Type targetType, SerializerEmitter emiter, CollectionTraits traits) { var il = emiter.GetPackToMethodILGenerator(); var localHolder = new LocalVariableHolder(il); 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 = localHolder.GetSerializingCollection(targetType); var item = localHolder.GetSerializingCollectionItem(traits.ElementType); 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 = localHolder.PackingCollectionCount; 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); }, localHolder ); Emittion.EmitSerializeValue( emiter, il0, 1, traits.ElementType.GetGenericArguments()[1], null, NilImplication.MemberDefault, il1 => { il1.EmitAnyLdloca(item); il1.EmitGetProperty(valueProperty); }, localHolder ); } 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)); }, localHolder ); Emittion.EmitSerializeValue( emiter, il0, 1, typeof(MessagePackObject), null, NilImplication.MemberDefault, il1 => { il0.EmitAnyLdloca(item); il0.EmitGetProperty(Metadata._DictionaryEntry.Value); il0.EmitUnbox_Any(typeof(MessagePackObject)); }, localHolder ); } } ); il.EmitRet(); } finally { il.FlushTrace(); } }
/// <summary> /// Emits the deserialize collection value. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="target">The target collection variable.</param> /// <param name="member">The deserializing member metadata which holds the collection.</param> /// <param name="memberType">Type of the deserializing member.</param> /// <param name="nilImplication">The nil implication.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeCollectionValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder target, MemberInfo member, Type memberType, NilImplication nilImplication, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(target != null); Contract.Requires(member != null); Contract.Requires(memberType != null); Contract.Requires(localHolder != null); var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); EmitGeneralRead(il, unpackerArgumentIndex); 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 = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._Nullable <MessagePackObject> .Value); var dataValue = localHolder.UnpackedDataValue; il.EmitAnyStloc(dataValue); il.EmitAnyLdloca(dataValue); il.EmitGetProperty(Metadata._MessagePackObject.IsNil); il.EmitBrtrue(endOfDeserialization); break; } case NilImplication.Null: case NilImplication.Prohibit: { /* * // for Prohibit * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } * * // for Null, and * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewReadOnlyMemberItemsMustNotBeNullMethod( "..." ); * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.Data); var data = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._Nullable <MessagePackObject> .Value); var dataValue = localHolder.UnpackedDataValue; 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 { // Because result member is readonly collection, so the member will not be null if packed value was nil. 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, result ) ) * } * * 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 = localHolder.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); }
/// <summary> /// Creates serializer for <typeparamref name="TObject"/>. /// </summary> /// <param name="entries">Serialization target members. This will not be <c>null</c> nor empty.</param> /// <returns> /// <see cref="MessagePackSerializer{T}"/>. This value will not be <c>null</c>. /// </returns> protected sealed override MessagePackSerializer <TObject> CreateSerializer(SerializingMember[] entries) { using (var emitter = this._generatorManager.CreateEmitter(typeof(TObject), this._emitterFlavor)) { try { var packerIL = emitter.GetPackToMethodILGenerator(); try { if (typeof(IPackable).IsAssignableFrom(typeof(TObject))) { if (typeof(TObject).IsValueType) { packerIL.EmitAnyLdarga(2); } else { packerIL.EmitAnyLdarg(2); } packerIL.EmitAnyLdarg(1); packerIL.EmitLdnull(); packerIL.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single()); packerIL.EmitRet(); } else { this.EmitPackMembers(emitter, packerIL, entries); } } finally { packerIL.FlushTrace(); } var unpackerIL = emitter.GetUnpackFromMethodILGenerator(); try { // TODO: For big struct, use Dictionary<String,SM> var result = unpackerIL.DeclareLocal(typeof(TObject), "result"); Emittion.EmitConstruction(unpackerIL, result, null); if (typeof(IUnpackable).IsAssignableFrom(typeof(TObject))) { if (typeof(TObject).GetIsValueType()) { unpackerIL.EmitAnyLdloca(result); } else { unpackerIL.EmitAnyLdloc(result); } unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitCall(typeof(TObject).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single()); } else { EmitUnpackMembers(emitter, unpackerIL, entries, result); } unpackerIL.EmitAnyLdloc(result); unpackerIL.EmitRet(); } finally { unpackerIL.FlushTrace(); } return(emitter.CreateInstance <TObject>(this.Context)); } finally { emitter.FlushTrace(); } } }
private static void EmitUnpackMembersFromMap(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result, LocalVariableHolder localHolder) { /* * var memberName = unpacker.Data.AsString(); * if( memberName == "A" ) * { * if( !unpacker.Read() ) * { * throw SerializationExceptions.NewUnexpectedStreamEndsException(); * } * * isAFound = true; * } * : */ var beginLoop = unpackerIL.DefineLabel("BEGIN_LOOP"); var endLoop = unpackerIL.DefineLabel("END_LOOP"); unpackerIL.MarkLabel(beginLoop); var memberName = localHolder.MemberName; unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitAnyLdloca(memberName); unpackerIL.EmitAnyCall(Metadata._Unpacker.ReadString); unpackerIL.EmitBrfalse(endLoop); for (int i = 0; i < entries.Length; i++) { if (entries[i].Contract.Name == null) { // skip undefined member continue; } // TODO: binary comparison // Is it current member? unpackerIL.EmitAnyLdloc(memberName); unpackerIL.EmitLdstr(entries[i].Contract.Name); unpackerIL.EmitAnyCall(Metadata._String.op_Equality); var endIfCurrentMember = unpackerIL.DefineLabel("END_IF_MEMBER_" + i); unpackerIL.EmitBrfalse(endIfCurrentMember); // Deserialize value 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 ); } // TOOD: Record for missing check unpackerIL.EmitBr(beginLoop); unpackerIL.MarkLabel(endIfCurrentMember); } // Drain next value with unpacker.Read() unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitCallvirt(Metadata._Unpacker.Read); unpackerIL.EmitPop(); unpackerIL.EmitBr(beginLoop); unpackerIL.MarkLabel(endLoop); }
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); } }
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 CreateTuplePack(SerializerEmitter emiter, Type tupleType, IList <Type> itemTypes, Action <TracingILGenerator, LocalBuilder> loadTupleEmitter) { var il = emiter.GetPackToMethodILGenerator(); var localHolder = new LocalVariableHolder(il); 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); }, localHolder ); } il.EmitRet(); } finally { il.FlushTrace(); } }
private static void CreatePackArrayProceduresCore(Type targetType, SerializerEmitter emitter, CollectionTraits traits) { var il = emitter.GetPackToMethodILGenerator(); var localHolder = new LocalVariableHolder(il); try { // Array if (targetType.IsArray) { /* * // array * packer.PackArrayHeader( length ); * for( int i = 0; i < length; i++ ) * { * this._serializer.PackTo( packer, collection[ i ] ); * } */ var length = localHolder.PackingCollectionCount; 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); }, localHolder ) ); } 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 = localHolder.GetSerializingCollection(traits.ElementType.MakeArrayType()); EmitLoadTarget(targetType, il, 2); il.EmitAnyCall(Metadata._Enumerable.ToArray1Method.MakeGenericMethod(traits.ElementType)); il.EmitAnyStloc(array); var length = localHolder.PackingCollectionCount; 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); }, localHolder ) ); } else { /* * // Enumerable * packer.PackArrayHeader( collection.Count ); * foreach( var item in list ) * { * this._serializer.PackTo( packer, array[ i ] ); * } */ var collection = localHolder.GetSerializingCollection(targetType); // This instruction always ldarg, not to be ldarga il.EmitAnyLdarg(2); il.EmitAnyStloc(collection); var count = localHolder.PackingCollectionCount; 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(), localHolder ) ); } il.EmitRet(); } finally { il.FlushTrace(); } }
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); } }
private static void CreateMapPack(Type targetType, SerializerEmitter emiter, CollectionTraits traits) { TracingILGenerator packToMethodILGenerator = emiter.GetPackToMethodILGenerator(); LocalVariableHolder localHolder = new LocalVariableHolder(packToMethodILGenerator); try { < > c__DisplayClass20 class3; LocalBuilder serializingCollection = localHolder.GetSerializingCollection(targetType); LocalBuilder item = localHolder.GetSerializingCollectionItem(traits.ElementType); PropertyInfo keyProperty = traits.ElementType.GetProperty("Key"); PropertyInfo valueProperty = traits.ElementType.GetProperty("Value"); packToMethodILGenerator.EmitAnyLdarg(2); packToMethodILGenerator.EmitAnyStloc(serializingCollection); LocalBuilder packingCollectionCount = localHolder.PackingCollectionCount; EmitLoadTarget(targetType, packToMethodILGenerator, serializingCollection); packToMethodILGenerator.EmitGetProperty(traits.CountProperty); packToMethodILGenerator.EmitAnyStloc(packingCollectionCount); packToMethodILGenerator.EmitAnyLdarg(1); packToMethodILGenerator.EmitAnyLdloc(packingCollectionCount); packToMethodILGenerator.EmitAnyCall(_Packer.PackMapHeader); packToMethodILGenerator.EmitPop(); Emittion.EmitForEach(packToMethodILGenerator, traits, serializingCollection, delegate(TracingILGenerator il0, Action getCurrentEmitter) { Action <TracingILGenerator> loadValueEmitter = null; Action <TracingILGenerator> action2 = null; Action <TracingILGenerator> action3 = null; Action <TracingILGenerator> action4 = null; < > c__DisplayClass20 class1 = class3; if (traits.ElementType.IsGenericType) { Contract.Assert(traits.ElementType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)); getCurrentEmitter(); il0.EmitAnyStloc(item); if (loadValueEmitter == null) { loadValueEmitter = delegate(TracingILGenerator il1) { il1.EmitAnyLdloca(item); il1.EmitGetProperty(keyProperty); }; } Emittion.EmitSerializeValue(emiter, il0, 1, traits.ElementType.GetGenericArguments()[0], null, NilImplication.MemberDefault, loadValueEmitter, localHolder); if (action2 == null) { action2 = delegate(TracingILGenerator il1) { il1.EmitAnyLdloca(item); il1.EmitGetProperty(valueProperty); }; } Emittion.EmitSerializeValue(emiter, il0, 1, traits.ElementType.GetGenericArguments()[1], null, NilImplication.MemberDefault, action2, localHolder); } else { Contract.Assert(traits.ElementType == typeof(DictionaryEntry)); getCurrentEmitter(); il0.EmitAnyStloc(item); if (action3 == null) { action3 = delegate(TracingILGenerator il1) { il0.EmitAnyLdloca(item); il0.EmitGetProperty(_DictionaryEntry.Key); il0.EmitUnbox_Any(typeof(MessagePackObject)); }; } Emittion.EmitSerializeValue(emiter, il0, 1, typeof(MessagePackObject), null, NilImplication.MemberDefault, action3, localHolder); if (action4 == null) { action4 = delegate(TracingILGenerator il1) { il0.EmitAnyLdloca(item); il0.EmitGetProperty(_DictionaryEntry.Value); il0.EmitUnbox_Any(typeof(MessagePackObject)); }; } Emittion.EmitSerializeValue(emiter, il0, 1, typeof(MessagePackObject), null, NilImplication.MemberDefault, action4, localHolder); } });
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); }