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); } }
protected sealed override void ResetCore(Type targetType, Type baseClass) { // Note: baseClass is always null this class hiearchy. var targetTypeDefinition = TypeDefinition.Object(targetType); this.Packer = ILConstruct.Argument(1, TypeDefinition.PackerType, "packer"); this.PackToTarget = ILConstruct.Argument(2, targetTypeDefinition, "objectTree"); this.NullCheckTarget = ILConstruct.Argument(1, targetTypeDefinition, "objectTree"); this.Unpacker = ILConstruct.Argument(1, TypeDefinition.UnpackerType, "unpacker"); this.IndexOfItem = ILConstruct.Argument(3, TypeDefinition.Int32Type, "indexOfItem"); this.ItemsCount = ILConstruct.Argument(4, TypeDefinition.Int32Type, "itemsCount"); this.UnpackToTarget = ILConstruct.Argument(2, targetTypeDefinition, "collection"); var traits = targetType.GetCollectionTraits(CollectionTraitOptions.Full, this.SerializationContext.CompatibilityOptions.AllowNonCollectionEnumerableTypes); if (traits.ElementType != null) { this.CollectionToBeAdded = ILConstruct.Argument(1, targetTypeDefinition, "collection"); this.ItemToAdd = ILConstruct.Argument(2, traits.ElementType, "item"); if (traits.DetailedCollectionType == CollectionDetailedKind.GenericDictionary #if !NETFX_35 && !UNITY && !NETFX_40 && !SILVERLIGHT || traits.DetailedCollectionType == CollectionDetailedKind.GenericReadOnlyDictionary #endif // !NETFX_35 && !UNITY && !NETFX_40 && !SILVERLIGHT ) { this.KeyToAdd = ILConstruct.Argument(2, traits.ElementType.GetGenericArguments()[0], "key"); this.ValueToAdd = ILConstruct.Argument(3, traits.ElementType.GetGenericArguments()[1], "value"); } this.InitialCapacity = ILConstruct.Argument(1, TypeDefinition.Int32Type, "initialCapacity"); } this._emitter = null; this._ilGeneratorStack.Clear(); }
private static void EmitUnpackMembers(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result) { /* * #if T is IUnpackable * result.UnpackFromMessage( unpacker ); * #else * if( unpacker.IsArrayHeader ) * { * ... * } * else * { * ... * } * #endif */ var localHolder = new LocalVariableHolder(unpackerIL); unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitGetProperty(Metadata._Unpacker.IsArrayHeader); var @else = unpackerIL.DefineLabel("ELSE"); var endif = unpackerIL.DefineLabel("END_IF"); unpackerIL.EmitBrfalse(@else); EmitUnpackMembersFromArray(emitter, unpackerIL, entries, result, localHolder, endif); unpackerIL.EmitBr(endif); unpackerIL.MarkLabel(@else); EmitUnpackMembersFromMap(emitter, unpackerIL, entries, result, localHolder); unpackerIL.MarkLabel(endif); }
public static void EmitUnpackFrom(SerializerEmitter emitter, TracingILGenerator il, LocalBuilder result, LocalBuilder unpacker) { emitter.RegisterSerializer(result.LocalType)(il, 0); il.EmitAnyLdloc(unpacker); il.EmitAnyCall(_UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod(new Type[] { result.LocalType })); il.EmitAnyStloc(result); }
/// <summary> /// Emits deserializing value instructions. /// </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="value">The value local variable which stores unpacked value.</param> /// <param name="targetType">The type of deserialzing type.</param> /// <param name="memberName">The name of the member.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValueWithoutNilImplication(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, string memberName, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(value != null); var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); /* * * 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: */ // Nil implication is not needed. EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, targetType, null, memberName, endOfDeserialization, localHolder); il.MarkLabel(endOfDeserialization); }
protected sealed override void ResetCore(Type targetType, Type baseClass) { // Note: baseClass is always null this class hiearchy. this.Packer = ILConstruct.Argument(1, typeof(Packer), "packer"); this.PackToTarget = ILConstruct.Argument(2, targetType, "objectTree"); this.Unpacker = ILConstruct.Argument(1, typeof(Unpacker), "unpacker"); this.IndexOfItem = ILConstruct.Argument(3, typeof(int), "indexOfItem"); this.ItemsCount = ILConstruct.Argument(4, typeof(int), "itemsCount"); this.UnpackToTarget = ILConstruct.Argument(2, targetType, "collection"); var traits = targetType.GetCollectionTraits(CollectionTraitOptions.Full); if (traits.ElementType != null) { this.CollectionToBeAdded = ILConstruct.Argument(1, targetType, "collection"); this.ItemToAdd = ILConstruct.Argument(2, traits.ElementType, "item"); if (traits.DetailedCollectionType == CollectionDetailedKind.GenericDictionary #if !NETFX_35 && !UNITY && !NETFX_40 && !SILVERLIGHT || traits.DetailedCollectionType == CollectionDetailedKind.GenericReadOnlyDictionary #endif // !NETFX_35 && !UNITY && !NETFX_40 && !SILVERLIGHT ) { this.KeyToAdd = ILConstruct.Argument(2, traits.ElementType.GetGenericArguments()[0], "key"); this.ValueToAdd = ILConstruct.Argument(3, traits.ElementType.GetGenericArguments()[1], "value"); } this.InitialCapacity = ILConstruct.Argument(1, typeof(int), "initialCapacity"); } this._emitter = null; this._ilGeneratorStack.Clear(); }
private static void EmitDeserializeValueCore(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember?member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder) { MethodInfo directReadMethod = _Unpacker.GetDirectReadMethod(value.LocalType); if ((directReadMethod != null) && (!member.HasValue || !UnpackHelpers.IsReadOnlyAppendableCollectionMember(member.Value.Member))) { LocalBuilder isDeserializationSucceeded = localHolder.IsDeserializationSucceeded; il.EmitLdc_I4_0(); il.EmitAnyStloc(isDeserializationSucceeded); il.BeginExceptionBlock(); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitAnyLdloca(value); il.EmitAnyCall(directReadMethod); il.EmitAnyStloc(isDeserializationSucceeded); il.BeginCatchBlock(typeof(MessageTypeException)); LocalBuilder catchedException = localHolder.GetCatchedException(typeof(MessageTypeException)); il.EmitAnyStloc(catchedException); il.EmitTypeOf(targetType); il.EmitLdstr(memberName); il.EmitAnyLdloc(catchedException); il.EmitAnyCall(SerializationExceptions.NewFailedToDeserializeMemberMethod); il.EmitThrow(); il.EndExceptionBlock(); Label target = il.DefineLabel("END_IF"); il.EmitAnyLdloc(isDeserializationSucceeded); il.EmitBrtrue_S(target); il.EmitAnyCall(SerializationExceptions.NewUnexpectedEndOfStreamMethod); il.EmitThrow(); il.MarkLabel(target); if (member.HasValue) { EmitNilImplicationForPrimitive(il, member.Value, value, endOfDeserialization); } } else { EmitGeneralRead(il, unpackerArgumentIndex); if (member.HasValue) { EmitNilImplication(il, unpackerArgumentIndex, member.Value.Contract.Name, member.Value.Contract.NilImplication, endOfDeserialization, localHolder); } Label label2 = il.DefineLabel("THEN_IF_COLLECTION"); Label label3 = il.DefineLabel("END_IF_COLLECTION"); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.IsArrayHeader); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.IsMapHeader); il.EmitOr(); il.EmitBrtrue_S(label2); EmitUnpackFrom(emitter, il, value, unpackerArgumentIndex); il.EmitBr_S(label3); LocalBuilder subtreeUnpacker = localHolder.SubtreeUnpacker; il.MarkLabel(label2); EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker); EmitUnpackFrom(emitter, il, value, subtreeUnpacker); EmitUnpackerEndReadSubtree(il, subtreeUnpacker); il.MarkLabel(label3); } }
/// <summary> /// Emits unpacking method with flavor specific getter. /// </summary> /// <param name="emitter">SerializerEmitter which knows the emittion flavor.</param> /// <param name="il">The il generator.</param> /// <param name="result">A variable wich stores unpacked result.</param> /// <param name="unpacker">The local variable which stores current Unpacker.</param> public static void EmitUnpackFrom(SerializerEmitter emitter, TracingILGenerator il, LocalBuilder result, LocalBuilder unpacker) { var serializerGetter = emitter.RegisterSerializer(result.LocalType); serializerGetter(il, 0); il.EmitAnyLdloc(unpacker); il.EmitAnyCall(Metadata._UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod(result.LocalType)); il.EmitAnyStloc(result); }
/// <summary> /// Emits the serializing value instructions. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="packerArgumentIndex">Index of the packer argument.</param> /// <param name="valueType">Type of the current member value.</param> /// <param name="memberName">Name of the current member.</param> /// <param name="nilImplication">The nil implication of the current member.</param> /// <param name="loadValueEmitter">The delegate which emits case specific value loading instructions.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitSerializeValue(SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action <TracingILGenerator> loadValueEmitter, LocalVariableHolder localHolder) { 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 = localHolder.GetSerializingValue(valueType); 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")); }
/// <summary> /// Resets internal states for specified target type. /// </summary> /// <param name="targetType">Type of the serialization target.</param> protected sealed override void ResetCore(Type targetType) { this.Packer = ILConstruct.Argument(1, typeof(Packer), "packer"); this.PackToTarget = ILConstruct.Argument(2, targetType, "objectTree"); this.Unpacker = ILConstruct.Argument(1, typeof(Unpacker), "unpacker"); this.UnpackToTarget = ILConstruct.Argument(2, targetType, "collection"); this._emitter = null; this._enumEmitter = null; }
public static SerializerEmitter CreateArraySerializerCore(Type targetType, EmitterFlavor emitterFlavor) { Contract.Requires(targetType != null); SerializerEmitter emitter = SerializationMethodGeneratorManager.Get().CreateEmitter(targetType, emitterFlavor); CollectionTraits collectionTraits = targetType.GetCollectionTraits(); CreatePackArrayProceduresCore(targetType, emitter, collectionTraits); CreateUnpackArrayProceduresCore(targetType, emitter, collectionTraits); return(emitter); }
public static void EmitDeserializeValueWithoutNilImplication(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, string memberName, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(value != null); Label endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, targetType, null, memberName, endOfDeserialization, localHolder); il.MarkLabel(endOfDeserialization); }
public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder) { LocalBuilder deserializedValue; Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(result != null); Label endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); bool flag = false; if (member.Member.GetMemberValueType().GetIsValueType() && (Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)) { deserializedValue = localHolder.GetDeserializedValue(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() })); flag = true; } else { deserializedValue = localHolder.GetDeserializedValue(member.Member.GetMemberValueType()); } if (deserializedValue.LocalType.GetIsValueType()) { il.EmitAnyLdloca(deserializedValue); il.EmitInitobj(deserializedValue.LocalType); } else { il.EmitLdnull(); il.EmitAnyStloc(deserializedValue); } EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, deserializedValue, result.LocalType, new SerializingMember?(member), member.Contract.Name, endOfDeserialization, localHolder); if (result.LocalType.IsValueType) { il.EmitAnyLdloca(result); } else { il.EmitAnyLdloc(result); } if (flag) { il.EmitAnyLdloca(deserializedValue); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(new Type[] { member.Member.GetMemberValueType() }).GetProperty("Value")); } else { il.EmitAnyLdloc(deserializedValue); } EmitStoreValue(il, member.Member); il.MarkLabel(endOfDeserialization); }
private static void CreateMapUnpackFrom(Type targetType, SerializerEmitter emitter, CollectionTraits traits) { var il = emitter.GetUnpackFromMethodILGenerator(); var localHolder = new LocalVariableHolder(il); 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 = localHolder.GetDeserializingCollection(targetType); 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 CreateArrayUnpackTo(Type targetType, SerializerEmitter emitter, CollectionTraits traits) { var il = emitter.GetUnpackToMethodILGenerator(); try { EmitInvokeArrayUnpackToHelper(targetType, emitter, traits, il, 1, il0 => il0.EmitAnyLdarg(2)); il.EmitRet(); } finally { il.FlushTrace(); } }
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(); }
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(); }
public sealed override MessagePackSerializer <TObject> CreateMapSerializer() { MessagePackSerializer <TObject> serializer; using (SerializerEmitter emitter = EmittingSerializerBuilderLogics.CreateMapSerializerCore(typeof(TObject), this._emitterFlavor)) { try { serializer = emitter.CreateInstance <TObject>(base.Context); } finally { emitter.FlushTrace(); } } return(serializer); }
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 EmitUnpackMembers(SerializerEmitter emitter, TracingILGenerator unpackerIL, SerializingMember[] entries, LocalBuilder result) { LocalVariableHolder localHolder = new LocalVariableHolder(unpackerIL); unpackerIL.EmitAnyLdarg(1); unpackerIL.EmitGetProperty(_Unpacker.IsArrayHeader); Label target = unpackerIL.DefineLabel("ELSE"); Label label2 = unpackerIL.DefineLabel("END_IF"); unpackerIL.EmitBrfalse(target); EmittingSerializerBuilder <TObject> .EmitUnpackMembersFromArray(emitter, unpackerIL, entries, result, localHolder); unpackerIL.EmitBr(label2); unpackerIL.MarkLabel(target); EmittingSerializerBuilder <TObject> .EmitUnpackMembersFromMap(emitter, unpackerIL, entries, result, localHolder); unpackerIL.MarkLabel(label2); }
protected sealed override void ResetCore(Type targetType, Type baseClass) { // Note: baseClass is always null this class hiearchy. this.Packer = ILConstruct.Argument(1, typeof(Packer), "packer"); this.PackToTarget = ILConstruct.Argument(2, targetType, "objectTree"); this.Unpacker = ILConstruct.Argument(1, typeof(Unpacker), "unpacker"); this.UnpackToTarget = ILConstruct.Argument(2, targetType, "collection"); var traits = targetType.GetCollectionTraits(); if (traits.ElementType != null) { this.CollectionToBeAdded = ILConstruct.Argument(1, targetType, "collection"); this.ItemToAdd = ILConstruct.Argument(2, traits.ElementType, "item"); this.InitialCapacity = ILConstruct.Argument(1, typeof(int), "initialCapacity"); } this._emitter = null; this._enumEmitter = null; }
public static void EmitSerializeValue(SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action <TracingILGenerator> loadValueEmitter, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(packerArgumentIndex >= 0); Contract.Requires(valueType != null); Contract.Requires(loadValueEmitter != null); LocalBuilder serializingValue = localHolder.GetSerializingValue(valueType); loadValueEmitter(il); il.EmitAnyStloc(serializingValue); if ((memberName != null) && (nilImplication == NilImplication.Prohibit)) { Label label; if (!valueType.IsValueType) { il.EmitAnyLdloc(serializingValue); label = il.DefineLabel("END_IF"); il.EmitBrtrue_S(label); il.EmitLdstr(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(label); } else if (Nullable.GetUnderlyingType(valueType) != null) { il.EmitAnyLdloca(serializingValue); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(new Type[] { Nullable.GetUnderlyingType(valueType) }).GetProperty("HasValue")); label = il.DefineLabel("END_IF"); il.EmitBrtrue_S(label); il.EmitLdstr(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(label); } } emitter.RegisterSerializer(valueType)(il, 0); il.EmitAnyLdarg(packerArgumentIndex); il.EmitAnyLdloc(serializingValue); il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(new Type[] { valueType }).GetMethod("PackTo")); }
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 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); } }
private static void CreateTupleUnpack( SerializerEmitter emitter, IList<Type> itemTypes ) { CreateTupleUnpackFrom( emitter, itemTypes ); }
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 CreateMapUnpack( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateMapUnpackFrom( targetType, emitter, traits ); CreateMapUnpackTo( targetType, emitter, traits ); }
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(); } }
/// <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); }
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(); } }
private static void CreateUnpackArrayProceduresCore( Type targetType, SerializerEmitter emitter, CollectionTraits traits ) { CreateArrayUnpackFrom( targetType, emitter, traits ); CreateArrayUnpackTo( targetType, emitter, traits ); }
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(); } }
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(); } }
/// <summary> /// Emits unpacking method with flavor specific getter. /// </summary> /// <param name="emitter">SerializerEmitter which knows the emittion flavor.</param> /// <param name="il">The il generator.</param> /// <param name="result">A variable wich stores unpacked result.</param> /// <param name="unpacker">The local variable which stores current Unpacker.</param> public static void EmitUnpackFrom( SerializerEmitter emitter, TracingILGenerator il, LocalBuilder result, LocalBuilder unpacker ) { var serializerGetter = emitter.RegisterSerializer( result.LocalType ); serializerGetter( il, 0 ); il.EmitAnyLdloc( unpacker ); il.EmitAnyCall( Metadata._UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod( result.LocalType ) ); il.EmitAnyStloc( result ); }
/// <summary> /// Emits deserializing value instructions. /// </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="value">The value local variable which stores unpacked value.</param> /// <param name="targetType">The type of deserialzing type.</param> /// <param name="memberName">The name of the member.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValueWithoutNilImplication( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, string memberName, LocalVariableHolder localHolder ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( unpackerArgumentIndex >= 0 ); Contract.Requires( value != null ); var endOfDeserialization = il.DefineLabel( "END_OF_DESERIALIZATION" ); /* * * 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: */ // Nil implication is not needed. EmitDeserializeValueCore( emitter, il, unpackerArgumentIndex, value, targetType, null, memberName, endOfDeserialization, localHolder ); il.MarkLabel( endOfDeserialization ); }
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 ) ); } } }
/// <summary> /// Emits the serializing value instructions. /// </summary> /// <param name="emitter">The emitter.</param> /// <param name="il">The il generator.</param> /// <param name="packerArgumentIndex">Index of the packer argument.</param> /// <param name="valueType">Type of the current member value.</param> /// <param name="memberName">Name of the current member.</param> /// <param name="nilImplication">The nil implication of the current member.</param> /// <param name="loadValueEmitter">The delegate which emits case specific value loading instructions.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitSerializeValue( SerializerEmitter emitter, TracingILGenerator il, int packerArgumentIndex, Type valueType, string memberName, NilImplication nilImplication, Action<TracingILGenerator> loadValueEmitter, LocalVariableHolder localHolder ) { 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 = localHolder.GetSerializingValue( valueType ); 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" ) ); }
public static void EmitDeserializeCollectionValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder target, MemberInfo member, Type memberType, NilImplication nilImplication, LocalVariableHolder localHolder) { LocalBuilder unpackedData; LocalBuilder unpackedDataValue; Label label2; Label label3; 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); Label label = il.DefineLabel("END_OF_DESERIALIZATION"); EmitGeneralRead(il, unpackerArgumentIndex); switch (nilImplication) { case NilImplication.MemberDefault: il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.Data); unpackedData = localHolder.UnpackedData; il.EmitAnyStloc(unpackedData); il.EmitAnyLdloca(unpackedData); il.EmitGetProperty(_Nullable <MessagePackObject> .Value); unpackedDataValue = localHolder.UnpackedDataValue; il.EmitAnyStloc(unpackedDataValue); il.EmitAnyLdloca(unpackedDataValue); il.EmitGetProperty(_MessagePackObject.IsNil); il.EmitBrtrue(label); goto Label_01B5; case NilImplication.Null: case NilImplication.Prohibit: il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.Data); unpackedData = localHolder.UnpackedData; il.EmitAnyStloc(unpackedData); il.EmitAnyLdloca(unpackedData); il.EmitGetProperty(_Nullable <MessagePackObject> .Value); unpackedDataValue = localHolder.UnpackedDataValue; il.EmitAnyStloc(unpackedDataValue); il.EmitAnyLdloca(unpackedDataValue); il.EmitGetProperty(_MessagePackObject.IsNil); label2 = il.DefineLabel("END_IF0"); il.EmitBrfalse_S(label2); il.EmitLdstr(member.Name); if (nilImplication != NilImplication.Prohibit) { il.EmitAnyCall(SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNullMethod); break; } il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); break; default: goto Label_01B5; } il.EmitThrow(); il.MarkLabel(label2); Label_01B5: label3 = il.DefineLabel("THEN"); Action <TracingILGenerator, int> action = emitter.RegisterSerializer(memberType); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.IsArrayHeader); il.EmitBrtrue_S(label3); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.IsMapHeader); il.EmitBrtrue_S(label3); il.EmitLdstr(member.Name); il.EmitAnyCall(SerializationExceptions.NewStreamDoesNotContainCollectionForMemberMethod); il.EmitThrow(); LocalBuilder subtreeUnpacker = localHolder.SubtreeUnpacker; il.MarkLabel(label3); EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker); action(il, 0); il.EmitAnyLdloc(subtreeUnpacker); il.EmitAnyLdloc(target); EmitLoadValue(il, member); il.EmitAnyCall(typeof(MessagePackSerializer <>).MakeGenericType(new Type[] { memberType }).GetMethod("UnpackTo", new Type[] { typeof(Unpacker), memberType })); EmitUnpackerEndReadSubtree(il, subtreeUnpacker); il.MarkLabel(label); }
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(); } }
/// <summary> /// Emits the deserialize 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="value">The value local variable which stores unpacked value.</param> /// <param name="targetType">The type of deserialzing type.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="memberName">The name of the member.</param> /// <param name="endOfDeserialization">The end of deserialization label for nil implication.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> private static void EmitDeserializeValueCore(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember?member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder) { var directUnpacking = Metadata._Unpacker.GetDirectReadMethod(value.LocalType); if (directUnpacking != null && (member == null || !UnpackHelpers.IsReadOnlyAppendableCollectionMember(member.Value.Member))) { var isSuccess = localHolder.IsDeserializationSucceeded; il.EmitLdc_I4_0(); il.EmitAnyStloc(isSuccess); il.BeginExceptionBlock(); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitAnyLdloca(value); il.EmitAnyCall(directUnpacking); il.EmitAnyStloc(isSuccess); il.BeginCatchBlock(typeof(MessageTypeException)); var ex = localHolder.GetCatchedException(typeof(MessageTypeException)); il.EmitAnyStloc(ex); il.EmitTypeOf(targetType); il.EmitLdstr(memberName); il.EmitAnyLdloc(ex); il.EmitAnyCall(SerializationExceptions.NewFailedToDeserializeMemberMethod); il.EmitThrow(); il.EndExceptionBlock(); var endIf0 = il.DefineLabel("END_IF"); il.EmitAnyLdloc(isSuccess); il.EmitBrtrue_S(endIf0); il.EmitAnyCall(SerializationExceptions.NewUnexpectedEndOfStreamMethod); il.EmitThrow(); il.MarkLabel(endIf0); if (member != null) { // If null, nil implication is NOT needed. EmitNilImplicationForPrimitive(il, member.Value, value, endOfDeserialization); } } else { EmitGeneralRead(il, unpackerArgumentIndex); if (member != null) { // If null, nil implication is NOT needed. EmitNilImplication( il, unpackerArgumentIndex, member.Value.Contract.Name, member.Value.Contract.NilImplication, endOfDeserialization, localHolder ); } var thenIffCollection = il.DefineLabel("THEN_IF_COLLECTION"); var endIfCollection = il.DefineLabel("END_IF_COLLECTION"); /* * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * value = GET_SERIALIZER().UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree() ) * { * value = GET_SERIALIZER().UnpackFrom( subtreeUnpacker ); * } * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.IsMapHeader); il.EmitOr(); il.EmitBrtrue_S(thenIffCollection); EmitUnpackFrom(emitter, il, value, unpackerArgumentIndex); il.EmitBr_S(endIfCollection); var subtreeUnpacker = localHolder.SubtreeUnpacker; il.MarkLabel(thenIffCollection); EmitUnpackerBeginReadSubtree(il, unpackerArgumentIndex, subtreeUnpacker); EmitUnpackFrom(emitter, il, value, subtreeUnpacker); EmitUnpackerEndReadSubtree(il, subtreeUnpacker); il.MarkLabel(endIfCollection); } }
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(); } }
/// <summary> /// Emits the deserialize 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="result">The result local variable which represents the result of deserialization.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValue( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder ) { Contract.Requires( emitter != null ); Contract.Requires( il != null ); Contract.Requires( unpackerArgumentIndex >= 0 ); Contract.Requires( result != null ); var endOfDeserialization = il.DefineLabel( "END_OF_DESERIALIZATION" ); /* * * 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: */ LocalBuilder value; bool useDummyNullableValue = false; if ( member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType( member.Member.GetMemberValueType() ) == null ) { // Use temporary nullable value for nil implication. value = localHolder.GetDeserializedValue( typeof( Nullable<> ).MakeGenericType( member.Member.GetMemberValueType() ) ); useDummyNullableValue = true; } else { value = localHolder.GetDeserializedValue( member.Member.GetMemberValueType() ); } if ( value.LocalType.GetIsValueType() ) { il.EmitAnyLdloca( value ); il.EmitInitobj( value.LocalType ); } else { il.EmitLdnull(); il.EmitAnyStloc( value ); } EmitDeserializeValueCore( emitter, il, unpackerArgumentIndex, value, result.LocalType, member, member.Contract.Name, endOfDeserialization, localHolder ); if ( result.LocalType.IsValueType ) { il.EmitAnyLdloca( result ); } else { il.EmitAnyLdloc( result ); } if ( useDummyNullableValue ) { il.EmitAnyLdloca( value ); il.EmitGetProperty( typeof( Nullable<> ).MakeGenericType( member.Member.GetMemberValueType() ).GetProperty( "Value" ) ); } else { il.EmitAnyLdloc( value ); } EmitStoreValue( il, member.Member ); il.MarkLabel( endOfDeserialization ); }
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 ); } }
/// <summary> /// Emits the deserialize 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="value">The value local variable which stores unpacked value.</param> /// <param name="targetType">The type of deserialzing type.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="memberName">The name of the member.</param> /// <param name="endOfDeserialization">The end of deserialization label for nil implication.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> private static void EmitDeserializeValueCore( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, Type targetType, SerializingMember? member, string memberName, Label endOfDeserialization, LocalVariableHolder localHolder ) { var directUnpacking = Metadata._Unpacker.GetDirectReadMethod( value.LocalType ); if ( directUnpacking != null && ( member == null || !UnpackHelpers.IsReadOnlyAppendableCollectionMember( member.Value.Member ) ) ) { var isSuccess = localHolder.IsDeserializationSucceeded; il.EmitLdc_I4_0(); il.EmitAnyStloc( isSuccess ); il.BeginExceptionBlock(); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitAnyLdloca( value ); il.EmitAnyCall( directUnpacking ); il.EmitAnyStloc( isSuccess ); il.BeginCatchBlock( typeof( MessageTypeException ) ); var ex = localHolder.GetCatchedException( typeof( MessageTypeException ) ); il.EmitAnyStloc( ex ); il.EmitTypeOf( targetType ); il.EmitLdstr( memberName ); il.EmitAnyLdloc( ex ); il.EmitAnyCall( SerializationExceptions.NewFailedToDeserializeMemberMethod ); il.EmitThrow(); il.EndExceptionBlock(); var endIf0 = il.DefineLabel( "END_IF" ); il.EmitAnyLdloc( isSuccess ); il.EmitBrtrue_S( endIf0 ); il.EmitAnyCall( SerializationExceptions.NewUnexpectedEndOfStreamMethod ); il.EmitThrow(); il.MarkLabel( endIf0 ); if ( member != null ) { // If null, nil implication is NOT needed. EmitNilImplicationForPrimitive( il, member.Value, value, endOfDeserialization ); } } else { EmitGeneralRead( il, unpackerArgumentIndex ); if ( member != null ) { // If null, nil implication is NOT needed. EmitNilImplication( il, unpackerArgumentIndex, member.Value.Contract.Name, member.Value.Contract.NilImplication, endOfDeserialization, localHolder ); } var thenIffCollection = il.DefineLabel( "THEN_IF_COLLECTION" ); var endIfCollection = il.DefineLabel( "END_IF_COLLECTION" ); /* * if( !unpacker.IsArrayHeader && !unpacker.IsMapHeader ) * { * value = GET_SERIALIZER().UnpackFrom( unpacker ); * } * else * { * using( var subtreeUnpacker = unpacker.ReadSubtree() ) * { * value = GET_SERIALIZER().UnpackFrom( subtreeUnpacker ); * } * } */ il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsArrayHeader ); il.EmitAnyLdarg( unpackerArgumentIndex ); il.EmitGetProperty( Metadata._Unpacker.IsMapHeader ); il.EmitOr(); il.EmitBrtrue_S( thenIffCollection ); EmitUnpackFrom( emitter, il, value, unpackerArgumentIndex ); il.EmitBr_S( endIfCollection ); var subtreeUnpacker = localHolder.SubtreeUnpacker; il.MarkLabel( thenIffCollection ); EmitUnpackerBeginReadSubtree( il, unpackerArgumentIndex, subtreeUnpacker ); EmitUnpackFrom( emitter, il, value, subtreeUnpacker ); EmitUnpackerEndReadSubtree( il, subtreeUnpacker ); il.MarkLabel( endIfCollection ); } }
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); }
/// <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> /// Emits the deserialize 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="result">The result local variable which represents the result of deserialization.</param> /// <param name="member">The metadata for nil implication. Specify <c>null</c> if nil implication is not needed.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitDeserializeValue(SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder result, SerializingMember member, LocalVariableHolder localHolder) { Contract.Requires(emitter != null); Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); Contract.Requires(result != null); var endOfDeserialization = il.DefineLabel("END_OF_DESERIALIZATION"); /* * * 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: */ LocalBuilder value; bool useDummyNullableValue = false; if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { // Use temporary nullable value for nil implication. value = localHolder.GetDeserializedValue( typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType())); useDummyNullableValue = true; } else { value = localHolder.GetDeserializedValue(member.Member.GetMemberValueType()); } if (value.LocalType.GetIsValueType()) { il.EmitAnyLdloca(value); il.EmitInitobj(value.LocalType); } else { il.EmitLdnull(); il.EmitAnyStloc(value); } EmitDeserializeValueCore(emitter, il, unpackerArgumentIndex, value, result.LocalType, member, member.Contract.Name, endOfDeserialization, localHolder); if (result.LocalType.IsValueType) { il.EmitAnyLdloca(result); } else { il.EmitAnyLdloc(result); } if (useDummyNullableValue) { il.EmitAnyLdloca(value); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(member.Member.GetMemberValueType()).GetProperty("Value")); } else { il.EmitAnyLdloc(value); } EmitStoreValue(il, member.Member); il.MarkLabel(endOfDeserialization); }
public static void EmitDeserializeValue( SerializerEmitter emitter, TracingILGenerator il, int unpackerArgumentIndex, LocalBuilder value, 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( !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 ); il.MarkLabel( endOfDeserialization ); }
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(); } }