protected override void EmitWrite(UcAsp.RPC.ProtoBuf.Compiler.CompilerContext ctx, UcAsp.RPC.ProtoBuf.Compiler.Local valueFrom) { using (Compiler.Local list = ctx.GetLocalWithValue(ExpectedType, valueFrom)) { MethodInfo moveNext, current, getEnumerator = GetEnumeratorInfo(ctx.Model, 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, ctx.MapType(typeof(SubItemToken))) : null) { if (writePacked) { ctx.LoadValue(fieldNumber); ctx.LoadValue((int)WireType.String); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("WriteFieldHeader")); ctx.LoadValue(list); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("StartSubItem")); ctx.StoreValue(token); ctx.LoadValue(fieldNumber); ctx.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(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 != ctx.MapType(typeof(object)) && current.ReturnType == ctx.MapType(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.LoadReaderWriter(); ctx.EmitCall(ctx.MapType(typeof(ProtoWriter)).GetMethod("EndSubItem")); } } } }