1*1b3f573fSAndroid Build Coastguard Worker #region Copyright notice and license 2*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format 3*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc. All rights reserved. 4*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/ 5*1b3f573fSAndroid Build Coastguard Worker // 6*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without 7*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are 8*1b3f573fSAndroid Build Coastguard Worker // met: 9*1b3f573fSAndroid Build Coastguard Worker // 10*1b3f573fSAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright 11*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer. 12*1b3f573fSAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above 13*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer 14*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the 15*1b3f573fSAndroid Build Coastguard Worker // distribution. 16*1b3f573fSAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its 17*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from 18*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission. 19*1b3f573fSAndroid Build Coastguard Worker // 20*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31*1b3f573fSAndroid Build Coastguard Worker #endregion 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker using System; 34*1b3f573fSAndroid Build Coastguard Worker using System.Buffers; 35*1b3f573fSAndroid Build Coastguard Worker using System.Buffers.Binary; 36*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic; 37*1b3f573fSAndroid Build Coastguard Worker using System.IO; 38*1b3f573fSAndroid Build Coastguard Worker using System.Runtime.CompilerServices; 39*1b3f573fSAndroid Build Coastguard Worker using System.Runtime.InteropServices; 40*1b3f573fSAndroid Build Coastguard Worker using System.Security; 41*1b3f573fSAndroid Build Coastguard Worker using System.Text; 42*1b3f573fSAndroid Build Coastguard Worker using Google.Protobuf.Collections; 43*1b3f573fSAndroid Build Coastguard Worker 44*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf 45*1b3f573fSAndroid Build Coastguard Worker { 46*1b3f573fSAndroid Build Coastguard Worker /// <summary> 47*1b3f573fSAndroid Build Coastguard Worker /// Fast parsing primitives for wrapper types 48*1b3f573fSAndroid Build Coastguard Worker /// </summary> 49*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] 50*1b3f573fSAndroid Build Coastguard Worker internal static class ParsingPrimitivesWrappers 51*1b3f573fSAndroid Build Coastguard Worker { ReadFloatWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)52*1b3f573fSAndroid Build Coastguard Worker internal static float? ReadFloatWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 53*1b3f573fSAndroid Build Coastguard Worker { 54*1b3f573fSAndroid Build Coastguard Worker // length:1 + tag:1 + value:4 = 6 bytes 55*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos + 6 <= state.bufferSize) 56*1b3f573fSAndroid Build Coastguard Worker { 57*1b3f573fSAndroid Build Coastguard Worker // The entire wrapper message is already contained in `buffer`. 58*1b3f573fSAndroid Build Coastguard Worker int length = buffer[state.bufferPos]; 59*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 60*1b3f573fSAndroid Build Coastguard Worker { 61*1b3f573fSAndroid Build Coastguard Worker state.bufferPos++; 62*1b3f573fSAndroid Build Coastguard Worker return 0F; 63*1b3f573fSAndroid Build Coastguard Worker } 64*1b3f573fSAndroid Build Coastguard Worker // tag:1 + value:4 = length of 5 bytes 65*1b3f573fSAndroid Build Coastguard Worker // field=1, type=32-bit = tag of 13 66*1b3f573fSAndroid Build Coastguard Worker if (length != 5 || buffer[state.bufferPos + 1] != 13) 67*1b3f573fSAndroid Build Coastguard Worker { 68*1b3f573fSAndroid Build Coastguard Worker return ReadFloatWrapperSlow(ref buffer, ref state); 69*1b3f573fSAndroid Build Coastguard Worker } 70*1b3f573fSAndroid Build Coastguard Worker state.bufferPos += 2; 71*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitives.ParseFloat(ref buffer, ref state); 72*1b3f573fSAndroid Build Coastguard Worker } 73*1b3f573fSAndroid Build Coastguard Worker else 74*1b3f573fSAndroid Build Coastguard Worker { 75*1b3f573fSAndroid Build Coastguard Worker return ReadFloatWrapperSlow(ref buffer, ref state); 76*1b3f573fSAndroid Build Coastguard Worker } 77*1b3f573fSAndroid Build Coastguard Worker } 78*1b3f573fSAndroid Build Coastguard Worker ReadFloatWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)79*1b3f573fSAndroid Build Coastguard Worker internal static float? ReadFloatWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 80*1b3f573fSAndroid Build Coastguard Worker { 81*1b3f573fSAndroid Build Coastguard Worker int length = ParsingPrimitives.ParseLength(ref buffer, ref state); 82*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 83*1b3f573fSAndroid Build Coastguard Worker { 84*1b3f573fSAndroid Build Coastguard Worker return 0F; 85*1b3f573fSAndroid Build Coastguard Worker } 86*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; 87*1b3f573fSAndroid Build Coastguard Worker float result = 0F; 88*1b3f573fSAndroid Build Coastguard Worker do 89*1b3f573fSAndroid Build Coastguard Worker { 90*1b3f573fSAndroid Build Coastguard Worker // field=1, type=32-bit = tag of 13 91*1b3f573fSAndroid Build Coastguard Worker if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 13) 92*1b3f573fSAndroid Build Coastguard Worker { 93*1b3f573fSAndroid Build Coastguard Worker result = ParsingPrimitives.ParseFloat(ref buffer, ref state); 94*1b3f573fSAndroid Build Coastguard Worker } 95*1b3f573fSAndroid Build Coastguard Worker else 96*1b3f573fSAndroid Build Coastguard Worker { 97*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); 98*1b3f573fSAndroid Build Coastguard Worker } 99*1b3f573fSAndroid Build Coastguard Worker } 100*1b3f573fSAndroid Build Coastguard Worker while (state.totalBytesRetired + state.bufferPos < finalBufferPos); 101*1b3f573fSAndroid Build Coastguard Worker return result; 102*1b3f573fSAndroid Build Coastguard Worker } 103*1b3f573fSAndroid Build Coastguard Worker ReadDoubleWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)104*1b3f573fSAndroid Build Coastguard Worker internal static double? ReadDoubleWrapperLittleEndian(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 105*1b3f573fSAndroid Build Coastguard Worker { 106*1b3f573fSAndroid Build Coastguard Worker // length:1 + tag:1 + value:8 = 10 bytes 107*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos + 10 <= state.bufferSize) 108*1b3f573fSAndroid Build Coastguard Worker { 109*1b3f573fSAndroid Build Coastguard Worker // The entire wrapper message is already contained in `buffer`. 110*1b3f573fSAndroid Build Coastguard Worker int length = buffer[state.bufferPos]; 111*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 112*1b3f573fSAndroid Build Coastguard Worker { 113*1b3f573fSAndroid Build Coastguard Worker state.bufferPos++; 114*1b3f573fSAndroid Build Coastguard Worker return 0D; 115*1b3f573fSAndroid Build Coastguard Worker } 116*1b3f573fSAndroid Build Coastguard Worker // tag:1 + value:8 = length of 9 bytes 117*1b3f573fSAndroid Build Coastguard Worker // field=1, type=64-bit = tag of 9 118*1b3f573fSAndroid Build Coastguard Worker if (length != 9 || buffer[state.bufferPos + 1] != 9) 119*1b3f573fSAndroid Build Coastguard Worker { 120*1b3f573fSAndroid Build Coastguard Worker return ReadDoubleWrapperSlow(ref buffer, ref state); 121*1b3f573fSAndroid Build Coastguard Worker } 122*1b3f573fSAndroid Build Coastguard Worker state.bufferPos += 2; 123*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitives.ParseDouble(ref buffer, ref state); 124*1b3f573fSAndroid Build Coastguard Worker } 125*1b3f573fSAndroid Build Coastguard Worker else 126*1b3f573fSAndroid Build Coastguard Worker { 127*1b3f573fSAndroid Build Coastguard Worker return ReadDoubleWrapperSlow(ref buffer, ref state); 128*1b3f573fSAndroid Build Coastguard Worker } 129*1b3f573fSAndroid Build Coastguard Worker } 130*1b3f573fSAndroid Build Coastguard Worker ReadDoubleWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)131*1b3f573fSAndroid Build Coastguard Worker internal static double? ReadDoubleWrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 132*1b3f573fSAndroid Build Coastguard Worker { 133*1b3f573fSAndroid Build Coastguard Worker int length = ParsingPrimitives.ParseLength(ref buffer, ref state); 134*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 135*1b3f573fSAndroid Build Coastguard Worker { 136*1b3f573fSAndroid Build Coastguard Worker return 0D; 137*1b3f573fSAndroid Build Coastguard Worker } 138*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; 139*1b3f573fSAndroid Build Coastguard Worker double result = 0D; 140*1b3f573fSAndroid Build Coastguard Worker do 141*1b3f573fSAndroid Build Coastguard Worker { 142*1b3f573fSAndroid Build Coastguard Worker // field=1, type=64-bit = tag of 9 143*1b3f573fSAndroid Build Coastguard Worker if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 9) 144*1b3f573fSAndroid Build Coastguard Worker { 145*1b3f573fSAndroid Build Coastguard Worker result = ParsingPrimitives.ParseDouble(ref buffer, ref state); 146*1b3f573fSAndroid Build Coastguard Worker } 147*1b3f573fSAndroid Build Coastguard Worker else 148*1b3f573fSAndroid Build Coastguard Worker { 149*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); 150*1b3f573fSAndroid Build Coastguard Worker } 151*1b3f573fSAndroid Build Coastguard Worker } 152*1b3f573fSAndroid Build Coastguard Worker while (state.totalBytesRetired + state.bufferPos < finalBufferPos); 153*1b3f573fSAndroid Build Coastguard Worker return result; 154*1b3f573fSAndroid Build Coastguard Worker } 155*1b3f573fSAndroid Build Coastguard Worker ReadBoolWrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)156*1b3f573fSAndroid Build Coastguard Worker internal static bool? ReadBoolWrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 157*1b3f573fSAndroid Build Coastguard Worker { 158*1b3f573fSAndroid Build Coastguard Worker return ReadUInt64Wrapper(ref buffer, ref state) != 0; 159*1b3f573fSAndroid Build Coastguard Worker } 160*1b3f573fSAndroid Build Coastguard Worker ReadUInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)161*1b3f573fSAndroid Build Coastguard Worker internal static uint? ReadUInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 162*1b3f573fSAndroid Build Coastguard Worker { 163*1b3f573fSAndroid Build Coastguard Worker // field=1, type=varint = tag of 8 164*1b3f573fSAndroid Build Coastguard Worker const int expectedTag = 8; 165*1b3f573fSAndroid Build Coastguard Worker // length:1 + tag:1 + value:10(varint64-max) = 12 bytes 166*1b3f573fSAndroid Build Coastguard Worker // Value can be 64 bits for negative integers 167*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos + 12 <= state.bufferSize) 168*1b3f573fSAndroid Build Coastguard Worker { 169*1b3f573fSAndroid Build Coastguard Worker // The entire wrapper message is already contained in `buffer`. 170*1b3f573fSAndroid Build Coastguard Worker int pos0 = state.bufferPos; 171*1b3f573fSAndroid Build Coastguard Worker int length = buffer[state.bufferPos++]; 172*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 173*1b3f573fSAndroid Build Coastguard Worker { 174*1b3f573fSAndroid Build Coastguard Worker return 0; 175*1b3f573fSAndroid Build Coastguard Worker } 176*1b3f573fSAndroid Build Coastguard Worker // Length will always fit in a single byte. 177*1b3f573fSAndroid Build Coastguard Worker if (length >= 128) 178*1b3f573fSAndroid Build Coastguard Worker { 179*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 180*1b3f573fSAndroid Build Coastguard Worker return ReadUInt32WrapperSlow(ref buffer, ref state); 181*1b3f573fSAndroid Build Coastguard Worker } 182*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.bufferPos + length; 183*1b3f573fSAndroid Build Coastguard Worker if (buffer[state.bufferPos++] != expectedTag) 184*1b3f573fSAndroid Build Coastguard Worker { 185*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 186*1b3f573fSAndroid Build Coastguard Worker return ReadUInt32WrapperSlow(ref buffer, ref state); 187*1b3f573fSAndroid Build Coastguard Worker } 188*1b3f573fSAndroid Build Coastguard Worker var result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); 189*1b3f573fSAndroid Build Coastguard Worker // Verify this message only contained a single field. 190*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos != finalBufferPos) 191*1b3f573fSAndroid Build Coastguard Worker { 192*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 193*1b3f573fSAndroid Build Coastguard Worker return ReadUInt32WrapperSlow(ref buffer, ref state); 194*1b3f573fSAndroid Build Coastguard Worker } 195*1b3f573fSAndroid Build Coastguard Worker return result; 196*1b3f573fSAndroid Build Coastguard Worker } 197*1b3f573fSAndroid Build Coastguard Worker else 198*1b3f573fSAndroid Build Coastguard Worker { 199*1b3f573fSAndroid Build Coastguard Worker return ReadUInt32WrapperSlow(ref buffer, ref state); 200*1b3f573fSAndroid Build Coastguard Worker } 201*1b3f573fSAndroid Build Coastguard Worker } 202*1b3f573fSAndroid Build Coastguard Worker ReadUInt32WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)203*1b3f573fSAndroid Build Coastguard Worker internal static uint? ReadUInt32WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 204*1b3f573fSAndroid Build Coastguard Worker { 205*1b3f573fSAndroid Build Coastguard Worker int length = ParsingPrimitives.ParseLength(ref buffer, ref state); 206*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 207*1b3f573fSAndroid Build Coastguard Worker { 208*1b3f573fSAndroid Build Coastguard Worker return 0; 209*1b3f573fSAndroid Build Coastguard Worker } 210*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; 211*1b3f573fSAndroid Build Coastguard Worker uint result = 0; 212*1b3f573fSAndroid Build Coastguard Worker do 213*1b3f573fSAndroid Build Coastguard Worker { 214*1b3f573fSAndroid Build Coastguard Worker // field=1, type=varint = tag of 8 215*1b3f573fSAndroid Build Coastguard Worker if (ParsingPrimitives.ParseTag(ref buffer, ref state) == 8) 216*1b3f573fSAndroid Build Coastguard Worker { 217*1b3f573fSAndroid Build Coastguard Worker result = ParsingPrimitives.ParseRawVarint32(ref buffer, ref state); 218*1b3f573fSAndroid Build Coastguard Worker } 219*1b3f573fSAndroid Build Coastguard Worker else 220*1b3f573fSAndroid Build Coastguard Worker { 221*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); 222*1b3f573fSAndroid Build Coastguard Worker } 223*1b3f573fSAndroid Build Coastguard Worker } 224*1b3f573fSAndroid Build Coastguard Worker while (state.totalBytesRetired + state.bufferPos < finalBufferPos); 225*1b3f573fSAndroid Build Coastguard Worker return result; 226*1b3f573fSAndroid Build Coastguard Worker } 227*1b3f573fSAndroid Build Coastguard Worker ReadInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)228*1b3f573fSAndroid Build Coastguard Worker internal static int? ReadInt32Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 229*1b3f573fSAndroid Build Coastguard Worker { 230*1b3f573fSAndroid Build Coastguard Worker return (int?)ReadUInt32Wrapper(ref buffer, ref state); 231*1b3f573fSAndroid Build Coastguard Worker } 232*1b3f573fSAndroid Build Coastguard Worker ReadUInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)233*1b3f573fSAndroid Build Coastguard Worker internal static ulong? ReadUInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 234*1b3f573fSAndroid Build Coastguard Worker { 235*1b3f573fSAndroid Build Coastguard Worker // field=1, type=varint = tag of 8 236*1b3f573fSAndroid Build Coastguard Worker const int expectedTag = 8; 237*1b3f573fSAndroid Build Coastguard Worker // length:1 + tag:1 + value:10(varint64-max) = 12 bytes 238*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos + 12 <= state.bufferSize) 239*1b3f573fSAndroid Build Coastguard Worker { 240*1b3f573fSAndroid Build Coastguard Worker // The entire wrapper message is already contained in `buffer`. 241*1b3f573fSAndroid Build Coastguard Worker int pos0 = state.bufferPos; 242*1b3f573fSAndroid Build Coastguard Worker int length = buffer[state.bufferPos++]; 243*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 244*1b3f573fSAndroid Build Coastguard Worker { 245*1b3f573fSAndroid Build Coastguard Worker return 0L; 246*1b3f573fSAndroid Build Coastguard Worker } 247*1b3f573fSAndroid Build Coastguard Worker // Length will always fit in a single byte. 248*1b3f573fSAndroid Build Coastguard Worker if (length >= 128) 249*1b3f573fSAndroid Build Coastguard Worker { 250*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 251*1b3f573fSAndroid Build Coastguard Worker return ReadUInt64WrapperSlow(ref buffer, ref state); 252*1b3f573fSAndroid Build Coastguard Worker } 253*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.bufferPos + length; 254*1b3f573fSAndroid Build Coastguard Worker if (buffer[state.bufferPos++] != expectedTag) 255*1b3f573fSAndroid Build Coastguard Worker { 256*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 257*1b3f573fSAndroid Build Coastguard Worker return ReadUInt64WrapperSlow(ref buffer, ref state); 258*1b3f573fSAndroid Build Coastguard Worker } 259*1b3f573fSAndroid Build Coastguard Worker var result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); 260*1b3f573fSAndroid Build Coastguard Worker // Verify this message only contained a single field. 261*1b3f573fSAndroid Build Coastguard Worker if (state.bufferPos != finalBufferPos) 262*1b3f573fSAndroid Build Coastguard Worker { 263*1b3f573fSAndroid Build Coastguard Worker state.bufferPos = pos0; 264*1b3f573fSAndroid Build Coastguard Worker return ReadUInt64WrapperSlow(ref buffer, ref state); 265*1b3f573fSAndroid Build Coastguard Worker } 266*1b3f573fSAndroid Build Coastguard Worker return result; 267*1b3f573fSAndroid Build Coastguard Worker } 268*1b3f573fSAndroid Build Coastguard Worker else 269*1b3f573fSAndroid Build Coastguard Worker { 270*1b3f573fSAndroid Build Coastguard Worker return ReadUInt64WrapperSlow(ref buffer, ref state); 271*1b3f573fSAndroid Build Coastguard Worker } 272*1b3f573fSAndroid Build Coastguard Worker } 273*1b3f573fSAndroid Build Coastguard Worker ReadUInt64WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)274*1b3f573fSAndroid Build Coastguard Worker internal static ulong? ReadUInt64WrapperSlow(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 275*1b3f573fSAndroid Build Coastguard Worker { 276*1b3f573fSAndroid Build Coastguard Worker // field=1, type=varint = tag of 8 277*1b3f573fSAndroid Build Coastguard Worker const int expectedTag = 8; 278*1b3f573fSAndroid Build Coastguard Worker int length = ParsingPrimitives.ParseLength(ref buffer, ref state); 279*1b3f573fSAndroid Build Coastguard Worker if (length == 0) 280*1b3f573fSAndroid Build Coastguard Worker { 281*1b3f573fSAndroid Build Coastguard Worker return 0L; 282*1b3f573fSAndroid Build Coastguard Worker } 283*1b3f573fSAndroid Build Coastguard Worker int finalBufferPos = state.totalBytesRetired + state.bufferPos + length; 284*1b3f573fSAndroid Build Coastguard Worker ulong result = 0L; 285*1b3f573fSAndroid Build Coastguard Worker do 286*1b3f573fSAndroid Build Coastguard Worker { 287*1b3f573fSAndroid Build Coastguard Worker if (ParsingPrimitives.ParseTag(ref buffer, ref state) == expectedTag) 288*1b3f573fSAndroid Build Coastguard Worker { 289*1b3f573fSAndroid Build Coastguard Worker result = ParsingPrimitives.ParseRawVarint64(ref buffer, ref state); 290*1b3f573fSAndroid Build Coastguard Worker } 291*1b3f573fSAndroid Build Coastguard Worker else 292*1b3f573fSAndroid Build Coastguard Worker { 293*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.SkipLastField(ref buffer, ref state); 294*1b3f573fSAndroid Build Coastguard Worker } 295*1b3f573fSAndroid Build Coastguard Worker } 296*1b3f573fSAndroid Build Coastguard Worker while (state.totalBytesRetired + state.bufferPos < finalBufferPos); 297*1b3f573fSAndroid Build Coastguard Worker return result; 298*1b3f573fSAndroid Build Coastguard Worker } 299*1b3f573fSAndroid Build Coastguard Worker ReadInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)300*1b3f573fSAndroid Build Coastguard Worker internal static long? ReadInt64Wrapper(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) 301*1b3f573fSAndroid Build Coastguard Worker { 302*1b3f573fSAndroid Build Coastguard Worker return (long?)ReadUInt64Wrapper(ref buffer, ref state); 303*1b3f573fSAndroid Build Coastguard Worker } 304*1b3f573fSAndroid Build Coastguard Worker ReadFloatWrapperLittleEndian(ref ParseContext ctx)305*1b3f573fSAndroid Build Coastguard Worker internal static float? ReadFloatWrapperLittleEndian(ref ParseContext ctx) 306*1b3f573fSAndroid Build Coastguard Worker { 307*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadFloatWrapperLittleEndian(ref ctx.buffer, ref ctx.state); 308*1b3f573fSAndroid Build Coastguard Worker } 309*1b3f573fSAndroid Build Coastguard Worker ReadFloatWrapperSlow(ref ParseContext ctx)310*1b3f573fSAndroid Build Coastguard Worker internal static float? ReadFloatWrapperSlow(ref ParseContext ctx) 311*1b3f573fSAndroid Build Coastguard Worker { 312*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadFloatWrapperSlow(ref ctx.buffer, ref ctx.state); 313*1b3f573fSAndroid Build Coastguard Worker } 314*1b3f573fSAndroid Build Coastguard Worker ReadDoubleWrapperLittleEndian(ref ParseContext ctx)315*1b3f573fSAndroid Build Coastguard Worker internal static double? ReadDoubleWrapperLittleEndian(ref ParseContext ctx) 316*1b3f573fSAndroid Build Coastguard Worker { 317*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadDoubleWrapperLittleEndian(ref ctx.buffer, ref ctx.state); 318*1b3f573fSAndroid Build Coastguard Worker } 319*1b3f573fSAndroid Build Coastguard Worker ReadDoubleWrapperSlow(ref ParseContext ctx)320*1b3f573fSAndroid Build Coastguard Worker internal static double? ReadDoubleWrapperSlow(ref ParseContext ctx) 321*1b3f573fSAndroid Build Coastguard Worker { 322*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadDoubleWrapperSlow(ref ctx.buffer, ref ctx.state); 323*1b3f573fSAndroid Build Coastguard Worker } 324*1b3f573fSAndroid Build Coastguard Worker ReadBoolWrapper(ref ParseContext ctx)325*1b3f573fSAndroid Build Coastguard Worker internal static bool? ReadBoolWrapper(ref ParseContext ctx) 326*1b3f573fSAndroid Build Coastguard Worker { 327*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadBoolWrapper(ref ctx.buffer, ref ctx.state); 328*1b3f573fSAndroid Build Coastguard Worker } 329*1b3f573fSAndroid Build Coastguard Worker ReadUInt32Wrapper(ref ParseContext ctx)330*1b3f573fSAndroid Build Coastguard Worker internal static uint? ReadUInt32Wrapper(ref ParseContext ctx) 331*1b3f573fSAndroid Build Coastguard Worker { 332*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadUInt32Wrapper(ref ctx.buffer, ref ctx.state); 333*1b3f573fSAndroid Build Coastguard Worker } 334*1b3f573fSAndroid Build Coastguard Worker ReadInt32Wrapper(ref ParseContext ctx)335*1b3f573fSAndroid Build Coastguard Worker internal static int? ReadInt32Wrapper(ref ParseContext ctx) 336*1b3f573fSAndroid Build Coastguard Worker { 337*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadInt32Wrapper(ref ctx.buffer, ref ctx.state); 338*1b3f573fSAndroid Build Coastguard Worker } 339*1b3f573fSAndroid Build Coastguard Worker ReadUInt64Wrapper(ref ParseContext ctx)340*1b3f573fSAndroid Build Coastguard Worker internal static ulong? ReadUInt64Wrapper(ref ParseContext ctx) 341*1b3f573fSAndroid Build Coastguard Worker { 342*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadUInt64Wrapper(ref ctx.buffer, ref ctx.state); 343*1b3f573fSAndroid Build Coastguard Worker } 344*1b3f573fSAndroid Build Coastguard Worker ReadUInt64WrapperSlow(ref ParseContext ctx)345*1b3f573fSAndroid Build Coastguard Worker internal static ulong? ReadUInt64WrapperSlow(ref ParseContext ctx) 346*1b3f573fSAndroid Build Coastguard Worker { 347*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadUInt64WrapperSlow(ref ctx.buffer, ref ctx.state); 348*1b3f573fSAndroid Build Coastguard Worker } 349*1b3f573fSAndroid Build Coastguard Worker ReadInt64Wrapper(ref ParseContext ctx)350*1b3f573fSAndroid Build Coastguard Worker internal static long? ReadInt64Wrapper(ref ParseContext ctx) 351*1b3f573fSAndroid Build Coastguard Worker { 352*1b3f573fSAndroid Build Coastguard Worker return ParsingPrimitivesWrappers.ReadInt64Wrapper(ref ctx.buffer, ref ctx.state); 353*1b3f573fSAndroid Build Coastguard Worker } 354*1b3f573fSAndroid Build Coastguard Worker } 355*1b3f573fSAndroid Build Coastguard Worker }