private static void AssertReadFromParseContext(ReadOnlySequence <byte> input, ParseContextAssertAction assertAction, bool assertIsAtEnd) { ParseContext.Initialize(input, out ParseContext parseCtx); assertAction(ref parseCtx); if (assertIsAtEnd) { Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref parseCtx.buffer, ref parseCtx.state)); } }
/// <summary> /// Parses the next tag. /// If the end of logical stream was reached, an invalid tag of 0 is returned. /// </summary> public static uint ParseTag(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { // The "nextTag" logic is there only as an optimization for reading non-packed repeated / map // fields and is strictly speaking not necessary. // TODO(jtattermusch): look into simplifying the ParseTag logic. if (state.hasNextTag) { state.lastTag = state.nextTag; state.hasNextTag = false; return(state.lastTag); } // Optimize for the incredibly common case of having at least two bytes left in the buffer, // and those two bytes being enough to get the tag. This will be true for fields up to 4095. if (state.bufferPos + 2 <= state.bufferSize) { int tmp = buffer[state.bufferPos++]; if (tmp < 128) { state.lastTag = (uint)tmp; } else { int result = tmp & 0x7f; if ((tmp = buffer[state.bufferPos++]) < 128) { result |= tmp << 7; state.lastTag = (uint)result; } else { // Nope, rewind and go the potentially slow route. state.bufferPos -= 2; state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); } } } else { if (SegmentedBufferHelper.IsAtEnd(ref buffer, ref state)) { state.lastTag = 0; return(0); } state.lastTag = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); } if (WireFormat.GetTagFieldNumber(state.lastTag) == 0) { // If we actually read a tag with a field of 0, that's not a valid tag. throw InvalidProtocolBufferException.InvalidTag(); } return(state.lastTag); }
private static void AssertReadFromParseContext(ReadOnlySequence <byte> input, ParseContextAssertAction assertAction, bool assertIsAtEnd) { // Check as ReadOnlySequence<byte> ParseContext.Initialize(input, out ParseContext parseCtx); assertAction(ref parseCtx); if (assertIsAtEnd) { Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref parseCtx.buffer, ref parseCtx.state)); } // Check as ReadOnlySpan<byte> ParseContext.Initialize(input.ToArray().AsSpan(), out ParseContext spanParseContext); assertAction(ref spanParseContext); if (assertIsAtEnd) { Assert.IsTrue(SegmentedBufferHelper.IsAtEnd(ref spanParseContext.buffer, ref spanParseContext.state)); } }