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 object CreateDelegate(Type delegateType, Type targetType, ConstructorInfo constructor, Type[] parameterTypes) { var dynamicMethod = #if !SILVERLIGHT new DynamicMethod("Create" + targetType.Name, targetType, parameterTypes, restrictedSkipVisibility: true); #else new DynamicMethod("Create" + targetType.Name, targetType, parameterTypes); #endif // !SILVERLIGHT var il = new TracingILGenerator(dynamicMethod, NullTextWriter.Instance, isDebuggable: false); if (constructor == null) { // Value type's init. il.DeclareLocal(targetType); il.EmitAnyLdloca(0); il.EmitInitobj(targetType); il.EmitAnyLdloc(0); } else { for (var i = 0; i < parameterTypes.Length; i++) { il.EmitAnyLdarg(i); } il.EmitNewobj(constructor); } il.EmitRet(); return(dynamicMethod.CreateDelegate(delegateType)); }
public static void EmitGetUnpackerItemsCountAsInt32(TracingILGenerator il, int unpackerArgumentIndex, LocalVariableHolder localHolder) { Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); il.EmitAnyLdloca(localHolder.RawItemsCount); il.EmitInitobj(typeof(long)); il.BeginExceptionBlock(); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(_Unpacker.ItemsCount); il.EmitAnyStloc(localHolder.RawItemsCount); il.BeginCatchBlock(typeof(InvalidOperationException)); il.EmitAnyCall(SerializationExceptions.NewIsIncorrectStreamMethod); il.EmitThrow(); il.EndExceptionBlock(); il.EmitAnyLdloc(localHolder.RawItemsCount); il.EmitLdc_I8(0x7fffffffL); Label target = il.DefineLabel(); il.EmitBle_S(target); il.EmitAnyCall(SerializationExceptions.NewIsTooLargeCollectionMethod); il.EmitThrow(); il.MarkLabel(target); il.EmitAnyLdloc(localHolder.RawItemsCount); il.EmitConv_I4(); }
public override void LoadValue(TracingILGenerator il, bool shouldBeAddress) { this.Evaluate(il); il.TraceWriteLine("// Load->: {0}", this); if (this.ContextType.ResolveRuntimeType().GetIsValueType() && shouldBeAddress) { if (this._isLocal) { il.EmitAnyLdloca(this._index); } else { il.EmitAnyLdarga(this._index); } } else { if (this._isLocal) { il.EmitAnyLdloc(this._index); } else { il.EmitAnyLdarg(this._index); } } il.TraceWriteLine("// ->Load: {0}", this); }
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); } }
public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter) { Contract.Requires(il != null); Contract.Requires(target != null); // TODO: For collection, supports .ctor(IEnumerable<> other) if (target.LocalType.IsAbstract || target.LocalType.IsInterface) { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(target.LocalType); } if (target.LocalType.IsArray) { Contract.Assert(initialCountLoadingEmitter != null); initialCountLoadingEmitter(il); il.EmitNewarr(target.LocalType.GetElementType()); il.EmitAnyStloc(target); return; } ConstructorInfo ctor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes); if (ctor != null && initialCountLoadingEmitter != null && typeof(IEnumerable).IsAssignableFrom(target.LocalType)) { if (target.LocalType.IsValueType) { // Same as general method call var capacity = il.DeclareLocal(typeof(int), "capacity"); initialCountLoadingEmitter(il); il.EmitAnyStloc(capacity); il.EmitAnyLdloca(target); il.EmitAnyLdloc(capacity); il.EmitCallConstructor(ctor); } else { initialCountLoadingEmitter(il); il.EmitNewobj(ctor); il.EmitAnyStloc(target); } return; } if (target.LocalType.IsValueType) { // ValueType instance has been initialized by the runtime. return; } ctor = target.LocalType.GetConstructor(Type.EmptyTypes); if (ctor == null) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType); } il.EmitNewobj(ctor); il.EmitAnyStloc(target); }
/// <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 EmitNilImplication(TracingILGenerator il, int unpackerArgumentIndex, string memberName, NilImplication nilImplication, Label endOfDeserialization, LocalVariableHolder localHolder) { LocalBuilder unpackedData; LocalBuilder unpackedDataValue; 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(endOfDeserialization); break; 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); Label target = il.DefineLabel("END_IF0"); il.EmitBrfalse_S(target); il.EmitLdstr(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(target); break; } } }
private static void EmitLoadTarget(Type targetType, TracingILGenerator il, LocalBuilder local) { if (targetType.IsValueType) { il.EmitAnyLdloca(local); } else { il.EmitAnyLdloc(local); } }
private static void EmitCompareNull(TracingILGenerator il, LocalBuilder value, Label targetIfNotNull) { if (value.LocalType == typeof(MessagePackObject)) { il.EmitAnyLdloca(value); il.EmitGetProperty(_MessagePackObject.IsNil); il.EmitBrfalse_S(targetIfNotNull); } else if (value.LocalType.GetIsValueType()) { Contract.Assert(Nullable.GetUnderlyingType(value.LocalType) != null, value.LocalType.FullName); il.EmitAnyLdloca(value); il.EmitGetProperty(value.LocalType.GetProperty("HasValue")); il.EmitBrtrue_S(targetIfNotNull); } else { il.EmitAnyLdloc(value); il.EmitLdnull(); il.EmitBne_Un_S(targetIfNotNull); } }
private static void CreateUnpacking(SerializerEmitter emitter) { TracingILGenerator unpackFromMethodILGenerator = emitter.GetUnpackFromMethodILGenerator(); try { LocalBuilder local = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject?), "mayBeNullData"); LocalBuilder builder2 = unpackFromMethodILGenerator.DeclareLocal(typeof(MessagePackObject), "data"); LocalBuilder builder3 = unpackFromMethodILGenerator.DeclareLocal(typeof(T), "result"); LocalBuilder result = unpackFromMethodILGenerator.DeclareLocal(NullableMessagePackSerializer <T> ._nullableTValueProperty.PropertyType, "value"); Label target = unpackFromMethodILGenerator.DefineLabel("END_IF"); Label label2 = unpackFromMethodILGenerator.DefineLabel("END_METHOD"); unpackFromMethodILGenerator.EmitAnyLdarg(1); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.UnpackerDataProperty); unpackFromMethodILGenerator.EmitAnyStloc(local); unpackFromMethodILGenerator.EmitAnyLdloca(local); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.Nullable_MessagePackObject_ValueProperty); unpackFromMethodILGenerator.EmitAnyStloc(builder2); unpackFromMethodILGenerator.EmitAnyLdloca(builder2); unpackFromMethodILGenerator.EmitGetProperty(NullableMessagePackSerializer.MessagePackObject_IsNilProperty); unpackFromMethodILGenerator.EmitBrfalse_S(target); unpackFromMethodILGenerator.EmitAnyLdloca(builder3); unpackFromMethodILGenerator.EmitInitobj(builder3.LocalType); unpackFromMethodILGenerator.EmitBr_S(label2); unpackFromMethodILGenerator.MarkLabel(target); Emittion.EmitUnpackFrom(emitter, unpackFromMethodILGenerator, result, 1); unpackFromMethodILGenerator.EmitAnyLdloc(result); unpackFromMethodILGenerator.EmitAnyCall(NullableMessagePackSerializer <T> ._nullableTImplicitOperator); unpackFromMethodILGenerator.EmitAnyStloc(builder3); unpackFromMethodILGenerator.MarkLabel(label2); unpackFromMethodILGenerator.EmitAnyLdloc(builder3); unpackFromMethodILGenerator.EmitRet(); } finally { unpackFromMethodILGenerator.FlushTrace(); emitter.FlushTrace(); } }
private static void 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); }
/// <summary> /// Emits gets <see cref="Unpacker.ItemsCount"/> with exception handling. /// Note that final state is the value is pushed top of the evaluation stack. /// </summary> /// <param name="il">IL generator.</param> /// <param name="unpackerArgumentIndex">Argument index of the unpacker.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitGetUnpackerItemsCountAsInt32(TracingILGenerator il, int unpackerArgumentIndex, LocalVariableHolder localHolder) { Contract.Requires(il != null); Contract.Requires(unpackerArgumentIndex >= 0); /* * long rawItemsCount; * try * { * rawItemsCount = unpacker.ItemsCount; * } * catch ( InvalidOperationException ex ) * { * throw SerializationExceptions.NewIsIncorrectStream( ex ); * } * * if( rawItemsCount > Int32.MaxValue ) * { * throw SerializationException.NewIsTooLargeCollection(); * } * * ... unchecked( ( int )rawItemsCount ); */ il.EmitAnyLdloca(localHolder.RawItemsCount); il.EmitInitobj(typeof(long)); il.BeginExceptionBlock(); il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.ItemsCount); il.EmitAnyStloc(localHolder.RawItemsCount); il.BeginCatchBlock(typeof(InvalidOperationException)); il.EmitAnyCall(SerializationExceptions.NewIsIncorrectStreamMethod); il.EmitThrow(); il.EndExceptionBlock(); il.EmitAnyLdloc(localHolder.RawItemsCount); il.EmitLdc_I8(Int32.MaxValue); var endIf = il.DefineLabel(); il.EmitBle_S(endIf); il.EmitAnyCall(SerializationExceptions.NewIsTooLargeCollectionMethod); il.EmitThrow(); il.MarkLabel(endIf); il.EmitAnyLdloc(localHolder.RawItemsCount); il.EmitConv_I4(); }
public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter) { Contract.Requires(il != null); Contract.Requires(target != null); if (target.LocalType.IsArray) { Contract.Assert(initialCountLoadingEmitter != null); initialCountLoadingEmitter(il); il.EmitNewarr(target.LocalType.GetElementType()); il.EmitAnyStloc(target); } else { ConstructorInfo constructor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes); if (((constructor != null) && (initialCountLoadingEmitter != null)) && typeof(IEnumerable).IsAssignableFrom(target.LocalType)) { if (target.LocalType.IsValueType) { LocalBuilder local = il.DeclareLocal(typeof(int), "capacity"); initialCountLoadingEmitter(il); il.EmitAnyStloc(local); il.EmitAnyLdloca(target); il.EmitAnyLdloc(local); il.EmitCallConstructor(constructor); } else { initialCountLoadingEmitter(il); il.EmitNewobj(constructor); il.EmitAnyStloc(target); } } else if (!target.LocalType.IsValueType) { constructor = target.LocalType.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType); } il.EmitNewobj(constructor); il.EmitAnyStloc(target); } } }
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")); }
/// <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); } }
/// <summary> /// Emits the nil implication. /// </summary> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="member">Metadata of the serializing member.</param> /// <param name="endOfDeserialization">The label to the end of deserialization.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitNilImplication( TracingILGenerator il, int unpackerArgumentIndex, SerializingMember member, Label endOfDeserialization, LocalVariableHolder localHolder ) { switch (member.Contract.NilImplication) { case NilImplication.MemberDefault: { // TODO: This should be empty for extra items. /* * if( unpacker.Data.Value.IsNil ) * { * // Skip current. * goto END_OF_DESERIALIZATION; * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.LastReadData); var data = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._MessagePackObject.IsNil); il.EmitBrtrue(endOfDeserialization); break; } case NilImplication.Null: { if (member.Member.GetMemberValueType().GetIsValueType() && Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null) { throw SerializationExceptions.NewValueTypeCannotBeNull( member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType ); } if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } break; } case NilImplication.Prohibit: { if (!member.Member.CanSetValue()) { throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull( member.Contract.Name ); } /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ il.EmitAnyLdarg(unpackerArgumentIndex); il.EmitGetProperty(Metadata._Unpacker.LastReadData); var data = localHolder.UnpackedData; il.EmitAnyStloc(data); il.EmitAnyLdloca(data); il.EmitGetProperty(Metadata._MessagePackObject.IsNil); var endIf0 = il.DefineLabel("END_IF0"); il.EmitBrfalse_S(endIf0); il.EmitLdstr(member.Contract.Name); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(endIf0); break; } } }
public static void EmitForEach(TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action <TracingILGenerator, Action> bodyEmitter) { Contract.Requires(il != null); Contract.Requires(collection != null); Contract.Requires(bodyEmitter != null); LocalBuilder enumerator = il.DeclareLocal(traits.GetEnumeratorMethod.ReturnType, "enumerator"); if (collection.LocalType.IsValueType) { il.EmitAnyLdloca(collection); } else { il.EmitAnyLdloc(collection); } il.EmitAnyCall(traits.GetEnumeratorMethod); il.EmitAnyStloc(enumerator); if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType)) { il.BeginExceptionBlock(); } Label label = il.DefineLabel("START_LOOP"); il.MarkLabel(label); Label target = il.DefineLabel("END_LOOP"); Type returnType = traits.GetEnumeratorMethod.ReturnType; MethodInfo method = returnType.GetMethod("MoveNext", Type.EmptyTypes); PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty("Current"); if (method == null) { method = _IEnumerator.MoveNext; } if (currentProperty == null) { if (returnType == typeof(IDictionaryEnumerator)) { currentProperty = _IDictionaryEnumerator.Current; } else if (returnType.IsInterface) { if (returnType.IsGenericType && (returnType.GetGenericTypeDefinition() == typeof(IEnumerator <>))) { currentProperty = typeof(IEnumerator <>).MakeGenericType(new Type[] { traits.ElementType }).GetProperty("Current"); } else { currentProperty = _IEnumerator.Current; } } } Contract.Assert(currentProperty != null, returnType.ToString()); if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { il.EmitAnyLdloca(enumerator); } else { il.EmitAnyLdloc(enumerator); } il.EmitAnyCall(method); il.EmitBrfalse(target); bodyEmitter(il, delegate { if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { il.EmitAnyLdloca(enumerator); } else { il.EmitAnyLdloc(enumerator); } il.EmitGetProperty(currentProperty); }); il.EmitBr(label); il.MarkLabel(target); if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType)) { il.BeginFinallyBlock(); if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { MethodInfo info2 = traits.GetEnumeratorMethod.ReturnType.GetMethod("Dispose"); if (((info2 != null) && (info2.GetParameters().Length == 0)) && (info2.ReturnType == typeof(void))) { il.EmitAnyLdloca(enumerator); il.EmitAnyCall(info2); } else { il.EmitAnyLdloc(enumerator); il.EmitBox(traits.GetEnumeratorMethod.ReturnType); il.EmitAnyCall(_IDisposable.Dispose); } } else { il.EmitAnyLdloc(enumerator); il.EmitAnyCall(_IDisposable.Dispose); } il.EndExceptionBlock(); } }
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 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 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); }
/// <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 'foreach' statement on the IL stream. /// </summary> /// <param name="il">IL generator to be emitted to.</param> /// <param name="traits"><see cref="CollectionTraits"/> which contains traits of the iterating collection.</param> /// <param name="collection">'collection' argument index.</param> /// <param name="bodyEmitter">Delegate to emit body statement.</param> public static void EmitForEach(TracingILGenerator il, CollectionTraits traits, LocalBuilder collection, Action <TracingILGenerator, Action> bodyEmitter) { Contract.Requires(il != null); Contract.Requires(collection != null); Contract.Requires(bodyEmitter != null); var enumerator = il.DeclareLocal(traits.GetEnumeratorMethod.ReturnType, "enumerator"); // gets enumerator if (collection.LocalType.IsValueType) { il.EmitAnyLdloca(collection); } else { il.EmitAnyLdloc(collection); } il.EmitAnyCall(traits.GetEnumeratorMethod); il.EmitAnyStloc(enumerator); if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType)) { il.BeginExceptionBlock(); } var startLoop = il.DefineLabel("START_LOOP"); il.MarkLabel(startLoop); var endLoop = il.DefineLabel("END_LOOP"); var enumeratorType = traits.GetEnumeratorMethod.ReturnType; MethodInfo moveNextMethod = enumeratorType.GetMethod("MoveNext", Type.EmptyTypes); PropertyInfo currentProperty = traits.GetEnumeratorMethod.ReturnType.GetProperty("Current"); if (moveNextMethod == null) { moveNextMethod = Metadata._IEnumerator.MoveNext; } if (currentProperty == null) { if (enumeratorType == typeof(IDictionaryEnumerator)) { currentProperty = Metadata._IDictionaryEnumerator.Current; } else if (enumeratorType.IsInterface) { if (enumeratorType.IsGenericType && enumeratorType.GetGenericTypeDefinition() == typeof(IEnumerator <>)) { currentProperty = typeof(IEnumerator <>).MakeGenericType(traits.ElementType).GetProperty("Current"); } else { currentProperty = Metadata._IEnumerator.Current; } } } Contract.Assert(currentProperty != null, enumeratorType.ToString()); // iterates if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { il.EmitAnyLdloca(enumerator); } else { il.EmitAnyLdloc(enumerator); } il.EmitAnyCall(moveNextMethod); il.EmitBrfalse(endLoop); bodyEmitter( il, () => { if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { il.EmitAnyLdloca(enumerator); } else { il.EmitAnyLdloc(enumerator); } il.EmitGetProperty(currentProperty); } ); il.EmitBr(startLoop); il.MarkLabel(endLoop); // Dispose if (typeof(IDisposable).IsAssignableFrom(traits.GetEnumeratorMethod.ReturnType)) { il.BeginFinallyBlock(); if (traits.GetEnumeratorMethod.ReturnType.IsValueType) { var disposeMethod = traits.GetEnumeratorMethod.ReturnType.GetMethod("Dispose"); if (disposeMethod != null && disposeMethod.GetParameters().Length == 0 && disposeMethod.ReturnType == typeof(void)) { il.EmitAnyLdloca(enumerator); il.EmitAnyCall(disposeMethod); } else { il.EmitAnyLdloc(enumerator); il.EmitBox(traits.GetEnumeratorMethod.ReturnType); il.EmitAnyCall(Metadata._IDisposable.Dispose); } } else { il.EmitAnyLdloc(enumerator); il.EmitAnyCall(Metadata._IDisposable.Dispose); } il.EndExceptionBlock(); } }
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); }
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); }
/// <summary> /// Emits the nil implication. /// </summary> /// <param name="il">The il generator.</param> /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param> /// <param name="memberName">Name of the deserializing member.</param> /// <param name="nilImplication">The nil implication.</param> /// <param name="endOfDeserialization">The label to the end of deserialization.</param> /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param> public static void EmitNilImplication( TracingILGenerator il, int unpackerArgumentIndex, string memberName, NilImplication nilImplication, Label endOfDeserialization, LocalVariableHolder localHolder ) { switch (nilImplication) { case NilImplication.MemberDefault: { // TODO: This should be empty for extra items. /* * 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.Prohibit: { /* * if( unpacker.Data.Value.IsNil ) * { * throw SerializationEceptions.NewProhibitNullException( "..." ); * } */ 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(memberName); il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod); il.EmitThrow(); il.MarkLabel(endIf0); break; } } }