protected override void EmitWrite(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom)) { MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(out moveNext, out 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.LoadReaderWriter(); ctx.EmitCall(typeof(ProtoWriter).GetMethod("WriteFieldHeader")); ctx.LoadValue(list); ctx.LoadReaderWriter(); ctx.EmitCall(typeof(ProtoWriter).GetMethod("StartSubItem")); ctx.StoreValue(token); ctx.LoadValue(fieldNumber); ctx.LoadReaderWriter(); ctx.EmitCall(typeof(ProtoWriter).GetMethod("SetPackedField")); } ctx.LoadAddress(list, ExpectedType); ctx.EmitCall(getEnumerator); 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); 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); ctx.BranchIfTrue(body, false); } if (writePacked) { ctx.LoadValue(token); ctx.LoadReaderWriter(); ctx.EmitCall(typeof(ProtoWriter).GetMethod("EndSubItem")); } } } }