public static void SkipLastField(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { if (state.lastTag == 0) { throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream"); } switch (WireFormat.GetTagWireType(state.lastTag)) { case WireFormat.WireType.StartGroup: SkipGroup(ref buffer, ref state, state.lastTag); break; case WireFormat.WireType.EndGroup: throw new InvalidProtocolBufferException( "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing"); case WireFormat.WireType.Fixed32: ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state); break; case WireFormat.WireType.Fixed64: ParsingPrimitives.ParseRawLittleEndian64(ref buffer, ref state); break; case WireFormat.WireType.LengthDelimited: var length = ParsingPrimitives.ParseLength(ref buffer, ref state); ParsingPrimitives.SkipRawBytes(ref buffer, ref state, length); break; case WireFormat.WireType.Varint: ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); break; } }
internal static uint?ReadUInt32WrapperSlow(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { int length = ParsingPrimitives.ParseLength(ref buffer, ref state); if (length == 0) { return(0); } int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; uint result = 0; do { // field=1, type=varint = tag of 8 if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 8) { result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); } else { ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); } }while (state.totalBytesRetired + state.bufferPos < finalBufferPos); return(result); }
/// <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); }
internal static uint?ReadUInt32Wrapper(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { // field=1, type=varint = tag of 8 const int expectedTag = 8; // length:1 + tag:1 + value:10(varint64-max) = 12 bytes // Value can be 64 bits for negative integers if (state.bufferPos + 12 <= state.bufferSize) { // The entire wrapper message is already contained in `buffer`. int pos0 = state.bufferPos; int length = buffer[state.bufferPos++]; if (length == 0) { return(0); } // Length will always fit in a single byte. if (length >= 128) { state.bufferPos = pos0; return(ReadUInt32WrapperSlow(ref buffer, ref state)); } int finalBufferPos = state.bufferPos + length; if (buffer[state.bufferPos++] != expectedTag) { state.bufferPos = pos0; return(ReadUInt32WrapperSlow(ref buffer, ref state)); } var result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); // Verify this message only contained a single field. if (state.bufferPos != finalBufferPos) { state.bufferPos = pos0; return(ReadUInt32WrapperSlow(ref buffer, ref state)); } return(result); } else { return(ReadUInt32WrapperSlow(ref buffer, ref state)); } }
public int ReadLength() { return((int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state)); }
public int ReadSInt32() { return(ParsingPrimitives.DecodeZigZag32(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state))); }
public int ReadEnum() { // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. return((int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state)); }
public uint ReadUInt32() { return(ParsingPrimitives.ParseRawVarint32(ref buffer, ref state)); }