public override void EmitReadRoot(CompilerContext context, Local valueFrom) { // => (T)((IProtoSubTypeSerializer<TBase>)this).ReadSubType(reader, ref state, SubTypeState<TBase>.Create<T>(state.Context, value)); // or // => state.ReadBaseType<TBase, T>(value, this); if (context.IsService) { using var tmp = context.GetLocalWithValue(typeof(T), valueFrom); context.LoadSelfAsService <ISubTypeSerializer <TBase>, TBase>(); context.LoadState(); // sub-state context.LoadSerializationContext(typeof(ISerializationContext)); context.LoadValue(tmp); context.EmitCall(typeof(SubTypeState <TBase>) .GetMethod(nameof(SubTypeState <string> .Create), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(typeof(T))); context.EmitCall(typeof(ISubTypeSerializer <TBase>) .GetMethod(nameof(ISubTypeSerializer <string> .ReadSubType), BindingFlags.Public | BindingFlags.Instance)); if (typeof(T) != typeof(TBase)) { context.Cast(typeof(T)); } } else { context.LoadState(); context.LoadValue(valueFrom); context.LoadSelfAsService <ISubTypeSerializer <TBase>, TBase>(); context.EmitCall(typeof(ProtoReader.State).GetMethod(nameof(ProtoReader.State.ReadBaseType), BindingFlags.Public | BindingFlags.Instance) .MakeGenericMethod(typeof(TBase), typeof(T))); } }
private void WriteFieldHandler(CompilerContext ctx, Type expected, Local loc, CodeLabel handler, CodeLabel @continue, IProtoSerializer serializer) { ctx.MarkLabel(handler); Type expectedType = serializer.ExpectedType; if (expectedType == this.forType) { this.EmitCreateIfNull(ctx, loc); serializer.EmitRead(ctx, loc); } else { RuntimeTypeModel model = (RuntimeTypeModel)ctx.Model; if (((IProtoTypeSerializer)serializer).CanCreateInstance()) { CodeLabel label = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.BranchIfFalse(label, false); ctx.LoadValue(loc); ctx.TryCast(expectedType); ctx.BranchIfTrue(label, false); ctx.LoadReaderWriter(); ctx.LoadValue(loc); ((IProtoTypeSerializer)serializer).EmitCreateInstance(ctx); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("Merge")); ctx.Cast(expected); ctx.StoreValue(loc); ctx.MarkLabel(label); } ctx.LoadValue(loc); ctx.Cast(expectedType); serializer.EmitRead(ctx, null); } if (serializer.ReturnsValue) { ctx.StoreValue(loc); } ctx.Branch(@continue, false); }
void IProtoTypeSerializer.EmitCreateInstance(CompilerContext ctx) { bool flag = true; if (this.factory != null) { EmitInvokeCallback(ctx, this.factory, false, this.constructType, this.forType); } else if (!this.useConstructor) { ctx.LoadValue(this.constructType); ctx.EmitCall(ctx.MapType(typeof(BclHelpers)).GetMethod("GetUninitializedObject")); ctx.Cast(this.forType); } else if (this.constructType.IsClass && this.hasConstructor) { ctx.EmitCtor(this.constructType); } else { ctx.LoadValue(this.ExpectedType); ctx.EmitCall(ctx.MapType(typeof(TypeModel)).GetMethod("ThrowCannotCreateInstance", BindingFlags.Public | BindingFlags.Static)); ctx.LoadNullRef(); flag = false; } if (flag) { ctx.CopyValue(); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("NoteObject", BindingFlags.Public | BindingFlags.Static)); } if (this.baseCtorCallbacks != null) { for (int i = 0; i < this.baseCtorCallbacks.Length; i++) { EmitInvokeCallback(ctx, this.baseCtorCallbacks[i], true, null, this.forType); } } }
private bool EmitDedicatedMethod(CompilerContext ctx, Local valueFrom, bool read) { MethodBuilder dedicatedMethod = ctx.GetDedicatedMethod(this.key, read); if (dedicatedMethod == null) { return(false); } using (Local local = new Local(ctx, ctx.MapType(typeof(SubItemToken)))) { Type type = ctx.MapType((read ? typeof(ProtoReader) : typeof(ProtoWriter))); ctx.LoadValue(valueFrom); if (!read) { if (this.type.IsValueType || !this.recursionCheck) { ctx.LoadNullRef(); } else { ctx.CopyValue(); } } ctx.LoadReaderWriter(); ctx.EmitCall(type.GetMethod("StartSubItem")); ctx.StoreValue(local); ctx.LoadReaderWriter(); ctx.EmitCall(dedicatedMethod); if (read && this.type != dedicatedMethod.ReturnType) { ctx.Cast(this.type); } ctx.LoadValue(local); ctx.LoadReaderWriter(); ctx.EmitCall(type.GetMethod("EndSubItem")); } return(true); }
private static void EmitReadAndAddItem(CompilerContext ctx, Local list, IProtoSerializer tail, MethodInfo add, bool castListForAdd) { ctx.LoadAddress(list, list.Type); if (castListForAdd) { ctx.Cast(add.DeclaringType); } Type expectedType = tail.ExpectedType; bool returnsValue = tail.ReturnsValue; if (!tail.RequiresOldValue) { if (!returnsValue) { throw new InvalidOperationException(); } tail.EmitRead(ctx, null); } else if (expectedType.IsValueType || !returnsValue) { using (Local local = new Local(ctx, expectedType)) { if (!expectedType.IsValueType) { ctx.LoadNullRef(); ctx.StoreValue(local); } else { ctx.LoadAddress(local, expectedType); ctx.EmitCtor(expectedType); } tail.EmitRead(ctx, local); if (!returnsValue) { ctx.LoadValue(local); } } } else { ctx.LoadNullRef(); tail.EmitRead(ctx, null); } Type parameterType = add.GetParameters()[0].ParameterType; if (parameterType != expectedType) { if (parameterType != ctx.MapType(typeof(object))) { if (Helpers.GetUnderlyingType(parameterType) != expectedType) { throw new InvalidOperationException("Conflicting item/add type"); } Type[] typeArray = new Type[] { expectedType }; ctx.EmitCtor(Helpers.GetConstructor(parameterType, typeArray, false)); } else { ctx.CastToObject(expectedType); } } ctx.EmitCall(add); if (add.ReturnType != ctx.MapType(typeof(void))) { ctx.DiscardValue(); } }
void IProtoSerializer.EmitRead(CompilerContext ctx, Local valueFrom) { Type expectedType = this.ExpectedType; using (Local local = ctx.GetLocalWithValue(expectedType, valueFrom)) { using (Local local2 = new Local(ctx, ctx.MapType(typeof(int)))) { if (this.HasCallbacks(TypeModel.CallbackType.BeforeDeserialize)) { if (this.ExpectedType.IsValueType) { this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); } else { CodeLabel label = ctx.DefineLabel(); ctx.LoadValue(local); ctx.BranchIfFalse(label, false); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.BeforeDeserialize); ctx.MarkLabel(label); } } CodeLabel label2 = ctx.DefineLabel(); CodeLabel label3 = ctx.DefineLabel(); ctx.Branch(label2, false); ctx.MarkLabel(label3); BasicList.NodeEnumerator enumerator = BasicList.GetContiguousGroups(this.fieldNumbers, this.serializers).GetEnumerator(); while (enumerator.MoveNext()) { BasicList.Group current = (BasicList.Group)enumerator.Current; CodeLabel label4 = ctx.DefineLabel(); int count = current.Items.Count; if (count == 1) { ctx.LoadValue(local2); ctx.LoadValue(current.First); CodeLabel label5 = ctx.DefineLabel(); ctx.BranchIfEqual(label5, true); ctx.Branch(label4, false); this.WriteFieldHandler(ctx, expectedType, local, label5, label2, (IProtoSerializer)current.Items[0]); } else { ctx.LoadValue(local2); ctx.LoadValue(current.First); ctx.Subtract(); CodeLabel[] jumpTable = new CodeLabel[count]; for (int i = 0; i < count; i++) { jumpTable[i] = ctx.DefineLabel(); } ctx.Switch(jumpTable); ctx.Branch(label4, false); for (int j = 0; j < count; j++) { this.WriteFieldHandler(ctx, expectedType, local, jumpTable[j], label2, (IProtoSerializer)current.Items[j]); } } ctx.MarkLabel(label4); } this.EmitCreateIfNull(ctx, local); ctx.LoadReaderWriter(); if (this.isExtensible) { ctx.LoadValue(local); ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("AppendExtensionData")); } else { ctx.EmitCall(ctx.MapType(typeof(ProtoReader)).GetMethod("SkipField")); } ctx.MarkLabel(label2); ctx.EmitBasicRead("ReadFieldHeader", ctx.MapType(typeof(int))); ctx.CopyValue(); ctx.StoreValue(local2); ctx.LoadValue(0); ctx.BranchIfGreater(label3, false); this.EmitCreateIfNull(ctx, local); this.EmitCallbackIfNeeded(ctx, local, TypeModel.CallbackType.AfterDeserialize); if ((valueFrom != null) && !local.IsSame(valueFrom)) { ctx.LoadValue(local); ctx.Cast(valueFrom.Type); ctx.StoreValue(valueFrom); } } } }
protected override void EmitRead(CompilerContext ctx, Local valueFrom) { MethodInfo methodInfo; MethodInfo methodInfo1; Local localWithValue; if (base.AppendToCollection) { localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom); } else { localWithValue = null; } using (Local local = localWithValue) { using (Local local1 = new Local(ctx, this.builderFactory.ReturnType)) { ctx.EmitCall(this.builderFactory); ctx.StoreValue(local1); if (base.AppendToCollection) { CodeLabel codeLabel = ctx.DefineLabel(); if (!this.ExpectedType.IsValueType) { ctx.LoadValue(local); ctx.BranchIfFalse(codeLabel, false); } PropertyInfo property = Helpers.GetProperty(this.ExpectedType, "Length", false) ?? Helpers.GetProperty(this.ExpectedType, "Count", false) ?? Helpers.GetProperty(ImmutableCollectionDecorator.ResolveIReadOnlyCollection(this.ExpectedType, this.Tail.ExpectedType), "Count", false); ctx.LoadAddress(local, local.Type); ctx.EmitCall(Helpers.GetGetMethod(property, false, false)); ctx.BranchIfFalse(codeLabel, false); Type type = ctx.MapType(typeof(void)); if (this.addRange == null) { MethodInfo enumeratorInfo = base.GetEnumeratorInfo(ctx.Model, out methodInfo, out methodInfo1); Type returnType = enumeratorInfo.ReturnType; using (Local local2 = new Local(ctx, returnType)) { ctx.LoadAddress(local, this.ExpectedType); ctx.EmitCall(enumeratorInfo); ctx.StoreValue(local2); using (IDisposable disposable = ctx.Using(local2)) { CodeLabel codeLabel1 = ctx.DefineLabel(); CodeLabel codeLabel2 = ctx.DefineLabel(); ctx.Branch(codeLabel2, false); ctx.MarkLabel(codeLabel1); ctx.LoadAddress(local1, local1.Type); ctx.LoadAddress(local2, returnType); ctx.EmitCall(methodInfo1); ctx.EmitCall(this.@add); if ([email protected] != null && [email protected] != type) { ctx.DiscardValue(); } ctx.MarkLabel(codeLabel2); ctx.LoadAddress(local2, returnType); ctx.EmitCall(methodInfo); ctx.BranchIfTrue(codeLabel1, false); } } } else { ctx.LoadValue(local1); ctx.LoadValue(local); ctx.EmitCall(this.addRange); if (this.addRange.ReturnType != null && [email protected] != type) { ctx.DiscardValue(); } } ctx.MarkLabel(codeLabel); } ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, false); ctx.LoadAddress(local1, local1.Type); ctx.EmitCall(this.finish); if (this.ExpectedType != this.finish.ReturnType) { ctx.Cast(this.ExpectedType); } } } }