public void EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { ctx.LoadValue(valueFrom); ctx.CastToObject(ExpectedType); ctx.LoadWriter(true); ctx.LoadValue(ctx.MapMetaKeyToCompiledKey(key)); ctx.LoadValue((int)options); ctx.EmitCall(Compiler.WriterUtil.GetStaticMethod <BclHelpers>("WriteNetObject")); }
protected override void EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { using (Compiler.Local valOrNull = ctx.GetLocalWithValue(ExpectedType, valueFrom)) using (Compiler.Local token = new Compiler.Local(ctx, typeof(SubItemToken))) { ctx.LoadNullRef(); ctx.LoadWriter(true); ctx.EmitCall(Compiler.WriterUtil.GetStaticMethod("StartSubItem")); ctx.StoreValue(token); if (Helpers.IsValueType(ExpectedType)) { ctx.LoadAddress(valOrNull, ExpectedType); ctx.LoadValue(ExpectedType.GetProperty("HasValue")); } else { ctx.LoadValue(valOrNull); } Compiler.CodeLabel @end = ctx.DefineLabel(); ctx.BranchIfFalse(@end, false); if (Helpers.IsValueType(ExpectedType)) { ctx.LoadAddress(valOrNull, ExpectedType); ctx.EmitCall(ExpectedType.GetMethod("GetValueOrDefault", Helpers.EmptyTypes)); } else { ctx.LoadValue(valOrNull); } Tail.EmitWrite(ctx, null); ctx.MarkLabel(@end); ctx.LoadValue(token); ctx.LoadWriter(true); ctx.EmitCall(Compiler.WriterUtil.GetStaticMethod("EndSubItem")); } }
void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { if (!EmitDedicatedMethod(ctx, valueFrom, false)) { ctx.LoadValue(valueFrom); if (Helpers.IsValueType(type)) { ctx.CastToObject(type); } ctx.LoadValue(ctx.MapMetaKeyToCompiledKey(key)); // re-map for formality, but would expect identical, else dedicated method ctx.LoadWriter(true); ctx.EmitCall(Helpers.GetStaticMethod(typeof(ProtoWriter), recursionCheck ? "WriteObject" : "WriteRecursionSafeObject", new Type[] { typeof(object), typeof(int), typeof(ProtoWriter), ProtoWriter.ByRefStateType })); } }
void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { ProtoTypeCode typeCode = GetTypeCode(); if (map == null) { ctx.LoadValue(valueFrom); ctx.ConvertToInt32(typeCode, false); ctx.EmitBasicWrite("WriteInt32", null); } else { using (Compiler.Local loc = ctx.GetLocalWithValue(ExpectedType, valueFrom)) { Compiler.CodeLabel @continue = ctx.DefineLabel(); for (int i = 0; i < map.Length; i++) { Compiler.CodeLabel tryNextValue = ctx.DefineLabel(), processThisValue = ctx.DefineLabel(); ctx.LoadValue(loc); WriteEnumValue(ctx, typeCode, map[i].RawValue); ctx.BranchIfEqual(processThisValue, true); ctx.Branch(tryNextValue, true); ctx.MarkLabel(processThisValue); ctx.LoadValue(map[i].WireValue); ctx.EmitBasicWrite("WriteInt32", null); ctx.Branch(@continue, false); ctx.MarkLabel(tryNextValue); } ctx.LoadWriter(false); ctx.LoadValue(loc); ctx.CastToObject(ExpectedType); ctx.EmitCall(typeof(ProtoWriter).GetMethod("ThrowEnumException")); ctx.MarkLabel(@continue); } } }
} // updates field directly #if FEAT_COMPILER void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom) { Type expected = ExpectedType; using (Compiler.Local loc = ctx.GetLocalWithValue(expected, valueFrom)) { // pre-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.BeforeSerialize); Compiler.CodeLabel startFields = ctx.DefineLabel(); // inheritance if (CanHaveInheritance) { for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; Type serType = ser.ExpectedType; if (serType != ExpectedType) { Compiler.CodeLabel ifMatch = ctx.DefineLabel(), nextTest = ctx.DefineLabel(); ctx.LoadValue(loc); ctx.TryCast(serType); ctx.CopyValue(); ctx.BranchIfTrue(ifMatch, true); ctx.DiscardValue(); ctx.Branch(nextTest, true); ctx.MarkLabel(ifMatch); if (Helpers.IsValueType(serType)) { ctx.DiscardValue(); ctx.LoadValue(loc); ctx.CastFromObject(serType); } ser.EmitWrite(ctx, null); ctx.Branch(startFields, false); ctx.MarkLabel(nextTest); } } if (constructType != null && constructType != ExpectedType) { using (Compiler.Local actualType = new Compiler.Local(ctx, typeof(Type))) { // would have jumped to "fields" if an expected sub-type, so two options: // a: *exactly* that type, b: an *unexpected* type ctx.LoadValue(loc); ctx.EmitCall(typeof(object).GetMethod("GetType")); ctx.CopyValue(); ctx.StoreValue(actualType); ctx.LoadValue(ExpectedType); ctx.BranchIfEqual(startFields, true); ctx.LoadValue(actualType); ctx.LoadValue(constructType); ctx.BranchIfEqual(startFields, true); } } else { // would have jumped to "fields" if an expected sub-type, so two options: // a: *exactly* that type, b: an *unexpected* type ctx.LoadValue(loc); ctx.EmitCall(typeof(object).GetMethod("GetType")); ctx.LoadValue(ExpectedType); ctx.BranchIfEqual(startFields, true); } // unexpected, then... note that this *might* be a proxy, which // is handled by ThrowUnexpectedSubtype ctx.LoadValue(ExpectedType); ctx.LoadValue(loc); ctx.EmitCall(typeof(object).GetMethod("GetType")); ctx.EmitCall(typeof(TypeModel).GetMethod("ThrowUnexpectedSubtype", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)); } // fields ctx.MarkLabel(startFields); for (int i = 0; i < serializers.Length; i++) { IProtoSerializer ser = serializers[i]; if (ser.ExpectedType == ExpectedType) { ser.EmitWrite(ctx, loc); } } // extension data if (isExtensible) { ctx.LoadValue(loc); ctx.LoadWriter(true); ctx.EmitCall(Compiler.WriterUtil.GetStaticMethod("AppendExtensionData")); } // post-callbacks EmitCallbackIfNeeded(ctx, loc, TypeModel.CallbackType.AfterSerialize); } }
private bool EmitDedicatedMethod(Compiler.CompilerContext ctx, Compiler.Local valueFrom, bool read) { MethodBuilder method = ctx.GetDedicatedMethod(key, read); if (method == null) { return(false); } using (Compiler.Local val = ctx.GetLocalWithValue(type, valueFrom)) using (Compiler.Local token = new ProtoBuf.Compiler.Local(ctx, typeof(SubItemToken))) { Type rwType = read ? typeof(ProtoReader) : typeof(ProtoWriter); if (read) { ctx.LoadReader(true); } else { // write requires the object for StartSubItem; read doesn't // (if recursion-check is disabled [subtypes] then null is fine too) if (Helpers.IsValueType(type) || !recursionCheck) { ctx.LoadNullRef(); } else { ctx.LoadValue(val); } ctx.LoadWriter(true); } ctx.EmitCall(Helpers.GetStaticMethod(rwType, "StartSubItem", read ? ProtoReader.State.ReaderStateTypeArray : new Type[] { typeof(object), rwType, ProtoWriter.ByRefStateType })); ctx.StoreValue(token); if (read) { ctx.LoadReader(true); ctx.LoadValue(val); } else { ctx.LoadWriter(true); ctx.LoadValue(val); } ctx.EmitCall(method); // handle inheritance (we will be calling the *base* version of things, // but we expect Read to return the "type" type) if (read && type != method.ReturnType) { ctx.Cast(type); } ctx.LoadValue(token); if (read) { ctx.LoadReader(true); ctx.EmitCall(Helpers.GetStaticMethod(rwType, "EndSubItem", new Type[] { typeof(SubItemToken), rwType, ProtoReader.State.ByRefStateType })); } else { ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("EndSubItem")); } } return(true); }