internal static void EmitReadList(ProtoBuf.Compiler.CompilerContext ctx, Compiler.Local list, IProtoSerializer tail, MethodInfo add, WireType packedWireType, bool castListForAdd) { using (Compiler.Local fieldNumber = new Compiler.Local(ctx, typeof(int))) { Compiler.CodeLabel readPacked = packedWireType == WireType.None ? new Compiler.CodeLabel() : ctx.DefineLabel(); if (packedWireType != WireType.None) { ctx.LoadReader(false); ctx.LoadValue(typeof(ProtoReader).GetProperty("WireType")); ctx.LoadValue((int)WireType.String); ctx.BranchIfEqual(readPacked, false); } ctx.LoadReader(false); ctx.LoadValue(typeof(ProtoReader).GetProperty("FieldNumber")); ctx.StoreValue(fieldNumber); Compiler.CodeLabel @continue = ctx.DefineLabel(); ctx.MarkLabel(@continue); EmitReadAndAddItem(ctx, list, tail, add, castListForAdd); ctx.LoadReader(true); ctx.LoadValue(fieldNumber); ctx.EmitCall(typeof(ProtoReader).GetMethod("TryReadFieldHeader", new[] { ProtoReader.State.ByRefStateType, typeof(int) })); ctx.BranchIfTrue(@continue, false); if (packedWireType != WireType.None) { Compiler.CodeLabel allDone = ctx.DefineLabel(); ctx.Branch(allDone, false); ctx.MarkLabel(readPacked); ctx.LoadReader(true); ctx.EmitCall(typeof(ProtoReader).GetMethod("StartSubItem", ProtoReader.State.ReaderStateTypeArray)); Compiler.CodeLabel testForData = ctx.DefineLabel(), noMoreData = ctx.DefineLabel(); ctx.MarkLabel(testForData); ctx.LoadValue((int)packedWireType); ctx.LoadReader(false); ctx.EmitCall(typeof(ProtoReader).GetMethod("HasSubValue")); ctx.BranchIfFalse(noMoreData, false); EmitReadAndAddItem(ctx, list, tail, add, castListForAdd); ctx.Branch(testForData, false); ctx.MarkLabel(noMoreData); ctx.LoadReader(true); ctx.EmitCall(typeof(ProtoReader).GetMethod("EndSubItem", new[] { typeof(SubItemToken), typeof(ProtoReader), ProtoReader.State.ByRefStateType })); ctx.MarkLabel(allDone); } } }
protected override void EmitRead(ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.Local valueFrom) { if (strict || NeedsHint) { ctx.LoadReader(strict); ctx.LoadValue((int)wireType); if (strict) { ctx.EmitCall(typeof(ProtoReader).GetMethod("Assert", new[] { ProtoReader.State.ByRefStateType, typeof(WireType) })); } else { ctx.EmitCall(typeof(ProtoReader).GetMethod("Hint")); } } Tail.EmitRead(ctx, valueFrom); }