public void EmitRead(SerializerCodeGen g, EmitReadMetaDelegate readNextMeta, Action prepareInstance, Action <Local> add) { if (readNextMeta == null) { readNextMeta = (s, f) => f(); } using (g.ctx.StartDebugBlockAuto(this)) { WireType packedWireType = _packedWireTypeForRead; bool packedAllowedStatic = (!_protoCompatibility || packedWireType != WireType.None); using (var packed = packedAllowedStatic ? g.ctx.Local(typeof(bool)) : null) using (var token = g.ctx.Local(typeof(SubItemToken))) using (var fieldNumber = _protoCompatibility ? g.ctx.Local(typeof(int)):null) using (var loop = g.ctx.Local(typeof(bool))) { if (!fieldNumber.IsNullRef()) { g.Assign(fieldNumber, g.ReaderFunc.FieldNumber()); } if (packedAllowedStatic) { g.Assign(packed, g.ReaderFunc.WireType() == WireType.String); } bool subItemNeededStatic = !_protoCompatibility; if (subItemNeededStatic || packedAllowedStatic) { if (!subItemNeededStatic) { g.If(packed); } g.Assign(token, g.ReaderFunc.StartSubItem()); if (!subItemNeededStatic) { g.End(); } } g.ctx.MarkDebug("ProtoCompatibility: " + _protoCompatibility); if (_protoCompatibility) { // this is not an error that we don't wait for the first item // if field is present there is at least one element prepareInstance?.Invoke(); if (packedAllowedStatic) { g.If(packed); { g.While(g.ReaderFunc.HasSubValue_bool(packedWireType)); { EmitReadElementContent(g, add); } g.End(); } g.Else(); } g.DoWhile(); { EmitReadElementContent(g, add); } g.EndDoWhile(g.ReaderFunc.TryReadFieldHeader_bool(fieldNumber)); if (packedAllowedStatic) { g.End(); } } else { var breakLabel = g.DefineLabel(); g.DoWhile(); { g.Assign(loop, false); readNextMeta( () => { using (g.ctx.StartDebugBlockAuto(this, "readNextMeta.OnSuccess")) { g.Assign(loop, true); } }, () => { using (g.ctx.StartDebugBlockAuto(this, "readNextMeta.OnFail")) { g.If(!g.ReaderFunc.TryReadFieldHeader_bool(FieldItem)); { g.If(g.ReaderFunc.ReadFieldHeader_int() == 0); { g.Goto(breakLabel); } g.End(); g.Reader.SkipField(); g.Assign(loop, true); } g.End(); } }); } g.EndDoWhile(loop); g.MarkLabel(breakLabel); prepareInstance?.Invoke(); g.If(g.ReaderFunc.FieldNumber() == FieldItem); { g.If(packed); { using (var packedWireTypeDynamic = g.ctx.Local(typeof(WireType))) { g.Assign(packedWireTypeDynamic, g.ReaderFunc.WireType()); g.DoWhile(); { EmitReadElementContent(g, add); } g.EndDoWhile(g.ReaderFunc.HasSubValue_bool(packedWireTypeDynamic)); } } g.Else(); { g.DoWhile(); { EmitReadElementContent(g, add); } g.EndDoWhile(g.ReaderFunc.TryReadFieldHeader_bool(FieldItem)); } g.End(); } g.End(); } if (subItemNeededStatic || packedAllowedStatic) { if (!subItemNeededStatic) { g.If(packed); } g.Reader.EndSubItem(token); if (!subItemNeededStatic) { g.End(); } } } } }