protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { // int i and T[] arr using (Compiler.Local arr = ctx.GetLocalWithValue(ExpectedType, valueFrom)) using (Compiler.Local i = new ProtoBuf.Compiler.Local(ctx, typeof(int))) { bool writePacked = (options & OPTIONS_WritePacked) != 0; bool fixedLengthPacked = writePacked && CanUsePackedPrefix(); using (Compiler.Local token = (writePacked && !fixedLengthPacked) ? new Compiler.Local(ctx, typeof(SubItemToken)) : null) { Type mappedWriter = typeof(ProtoWriter); if (writePacked) { ctx.LoadValue(fieldNumber); ctx.LoadValue((int)WireType.String); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("WriteFieldHeader")); if (fixedLengthPacked) { // write directly - no need for buffering ctx.LoadLength(arr, false); ctx.LoadValue((int)packedWireType); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("WritePackedPrefix")); } else { ctx.LoadValue(arr); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("StartSubItem")); ctx.StoreValue(token); } ctx.LoadValue(fieldNumber); ctx.LoadWriter(false); ctx.EmitCall(mappedWriter.GetMethod("SetPackedField")); } EmitWriteArrayLoop(ctx, i, arr); if (writePacked) { if (fixedLengthPacked) { ctx.LoadValue(fieldNumber); ctx.LoadWriter(false); ctx.EmitCall(mappedWriter.GetMethod("ClearPackedField")); } else { ctx.LoadValue(token); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("EndSubItem")); } } } } }
protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom)) { MethodInfo getEnumerator = GetEnumeratorInfo(out MethodInfo moveNext, out MethodInfo current); Helpers.DebugAssert(moveNext != null); Helpers.DebugAssert(current != null); Helpers.DebugAssert(getEnumerator != null); Type enumeratorType = getEnumerator.ReturnType; bool writePacked = WritePacked; using (Compiler.Local iter = new Compiler.Local(ctx, enumeratorType)) using (Compiler.Local token = writePacked ? new Compiler.Local(ctx, typeof(SubItemToken)) : null) { if (writePacked) { ctx.LoadValue(fieldNumber); ctx.LoadValue((int)WireType.String); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("WriteFieldHeader")); ctx.LoadValue(list); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("StartSubItem")); ctx.StoreValue(token); ctx.LoadValue(fieldNumber); ctx.LoadWriter(false); ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField")); } ctx.LoadAddress(list, ExpectedType); ctx.EmitCall(getEnumerator, ExpectedType); ctx.StoreValue(iter); using (ctx.Using(iter)) { Compiler.CodeLabel body = ctx.DefineLabel(), next = ctx.DefineLabel(); ctx.Branch(next, false); ctx.MarkLabel(body); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(current, enumeratorType); Type itemType = Tail.ExpectedType; if (itemType != typeof(object) && current.ReturnType == typeof(object)) { ctx.CastFromObject(itemType); } Tail.EmitWrite(ctx, null); ctx.MarkLabel(@next); ctx.LoadAddress(iter, enumeratorType); ctx.EmitCall(moveNext, enumeratorType); ctx.BranchIfTrue(body, false); } if (writePacked) { ctx.LoadValue(token); ctx.LoadWriter(true); ctx.EmitCall(ProtoWriter.GetStaticMethod("EndSubItem")); } } } }