1ffe3c632Sopenharmony_ci#region Copyright notice and license 2ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 3ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 4ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 5ffe3c632Sopenharmony_ci// 6ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 7ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 8ffe3c632Sopenharmony_ci// met: 9ffe3c632Sopenharmony_ci// 10ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 11ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 12ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 13ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 14ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 15ffe3c632Sopenharmony_ci// distribution. 16ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 17ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 18ffe3c632Sopenharmony_ci// this software without specific prior written permission. 19ffe3c632Sopenharmony_ci// 20ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31ffe3c632Sopenharmony_ci#endregion 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_ciusing Google.Protobuf.Collections; 34ffe3c632Sopenharmony_ciusing System; 35ffe3c632Sopenharmony_ciusing System.Collections.Generic; 36ffe3c632Sopenharmony_ciusing System.IO; 37ffe3c632Sopenharmony_ciusing System.Runtime.CompilerServices; 38ffe3c632Sopenharmony_ciusing System.Runtime.InteropServices; 39ffe3c632Sopenharmony_ciusing System.Security; 40ffe3c632Sopenharmony_ci 41ffe3c632Sopenharmony_cinamespace Google.Protobuf 42ffe3c632Sopenharmony_ci{ 43ffe3c632Sopenharmony_ci /// <summary> 44ffe3c632Sopenharmony_ci /// Reads and decodes protocol message fields. 45ffe3c632Sopenharmony_ci /// </summary> 46ffe3c632Sopenharmony_ci /// <remarks> 47ffe3c632Sopenharmony_ci /// <para> 48ffe3c632Sopenharmony_ci /// This class is generally used by generated code to read appropriate 49ffe3c632Sopenharmony_ci /// primitives from the stream. It effectively encapsulates the lowest 50ffe3c632Sopenharmony_ci /// levels of protocol buffer format. 51ffe3c632Sopenharmony_ci /// </para> 52ffe3c632Sopenharmony_ci /// <para> 53ffe3c632Sopenharmony_ci /// Repeated fields and map fields are not handled by this class; use <see cref="RepeatedField{T}"/> 54ffe3c632Sopenharmony_ci /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields. 55ffe3c632Sopenharmony_ci /// </para> 56ffe3c632Sopenharmony_ci /// </remarks> 57ffe3c632Sopenharmony_ci [SecuritySafeCritical] 58ffe3c632Sopenharmony_ci public sealed class CodedInputStream : IDisposable 59ffe3c632Sopenharmony_ci { 60ffe3c632Sopenharmony_ci /// <summary> 61ffe3c632Sopenharmony_ci /// Whether to leave the underlying stream open when disposing of this stream. 62ffe3c632Sopenharmony_ci /// This is always true when there's no stream. 63ffe3c632Sopenharmony_ci /// </summary> 64ffe3c632Sopenharmony_ci private readonly bool leaveOpen; 65ffe3c632Sopenharmony_ci 66ffe3c632Sopenharmony_ci /// <summary> 67ffe3c632Sopenharmony_ci /// Buffer of data read from the stream or provided at construction time. 68ffe3c632Sopenharmony_ci /// </summary> 69ffe3c632Sopenharmony_ci private readonly byte[] buffer; 70ffe3c632Sopenharmony_ci 71ffe3c632Sopenharmony_ci /// <summary> 72ffe3c632Sopenharmony_ci /// The stream to read further input from, or null if the byte array buffer was provided 73ffe3c632Sopenharmony_ci /// directly on construction, with no further data available. 74ffe3c632Sopenharmony_ci /// </summary> 75ffe3c632Sopenharmony_ci private readonly Stream input; 76ffe3c632Sopenharmony_ci 77ffe3c632Sopenharmony_ci /// <summary> 78ffe3c632Sopenharmony_ci /// The parser state is kept separately so that other parse implementations can reuse the same 79ffe3c632Sopenharmony_ci /// parsing primitives. 80ffe3c632Sopenharmony_ci /// </summary> 81ffe3c632Sopenharmony_ci private ParserInternalState state; 82ffe3c632Sopenharmony_ci 83ffe3c632Sopenharmony_ci internal const int DefaultRecursionLimit = 100; 84ffe3c632Sopenharmony_ci internal const int DefaultSizeLimit = Int32.MaxValue; 85ffe3c632Sopenharmony_ci internal const int BufferSize = 4096; 86ffe3c632Sopenharmony_ci 87ffe3c632Sopenharmony_ci #region Construction 88ffe3c632Sopenharmony_ci // Note that the checks are performed such that we don't end up checking obviously-valid things 89ffe3c632Sopenharmony_ci // like non-null references for arrays we've just created. 90ffe3c632Sopenharmony_ci 91ffe3c632Sopenharmony_ci /// <summary> 92ffe3c632Sopenharmony_ci /// Creates a new CodedInputStream reading data from the given byte array. 93ffe3c632Sopenharmony_ci /// </summary> 94ffe3c632Sopenharmony_ci public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length, true) 95ffe3c632Sopenharmony_ci { 96ffe3c632Sopenharmony_ci } 97ffe3c632Sopenharmony_ci 98ffe3c632Sopenharmony_ci /// <summary> 99ffe3c632Sopenharmony_ci /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice. 100ffe3c632Sopenharmony_ci /// </summary> 101ffe3c632Sopenharmony_ci public CodedInputStream(byte[] buffer, int offset, int length) 102ffe3c632Sopenharmony_ci : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length, true) 103ffe3c632Sopenharmony_ci { 104ffe3c632Sopenharmony_ci if (offset < 0 || offset > buffer.Length) 105ffe3c632Sopenharmony_ci { 106ffe3c632Sopenharmony_ci throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer"); 107ffe3c632Sopenharmony_ci } 108ffe3c632Sopenharmony_ci if (length < 0 || offset + length > buffer.Length) 109ffe3c632Sopenharmony_ci { 110ffe3c632Sopenharmony_ci throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer"); 111ffe3c632Sopenharmony_ci } 112ffe3c632Sopenharmony_ci } 113ffe3c632Sopenharmony_ci 114ffe3c632Sopenharmony_ci /// <summary> 115ffe3c632Sopenharmony_ci /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream, which will be disposed 116ffe3c632Sopenharmony_ci /// when the returned object is disposed. 117ffe3c632Sopenharmony_ci /// </summary> 118ffe3c632Sopenharmony_ci /// <param name="input">The stream to read from.</param> 119ffe3c632Sopenharmony_ci public CodedInputStream(Stream input) : this(input, false) 120ffe3c632Sopenharmony_ci { 121ffe3c632Sopenharmony_ci } 122ffe3c632Sopenharmony_ci 123ffe3c632Sopenharmony_ci /// <summary> 124ffe3c632Sopenharmony_ci /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream. 125ffe3c632Sopenharmony_ci /// </summary> 126ffe3c632Sopenharmony_ci /// <param name="input">The stream to read from.</param> 127ffe3c632Sopenharmony_ci /// <param name="leaveOpen"><c>true</c> to leave <paramref name="input"/> open when the returned 128ffe3c632Sopenharmony_ci /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the 129ffe3c632Sopenharmony_ci /// returned object is disposed.</param> 130ffe3c632Sopenharmony_ci public CodedInputStream(Stream input, bool leaveOpen) 131ffe3c632Sopenharmony_ci : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0, leaveOpen) 132ffe3c632Sopenharmony_ci { 133ffe3c632Sopenharmony_ci } 134ffe3c632Sopenharmony_ci 135ffe3c632Sopenharmony_ci /// <summary> 136ffe3c632Sopenharmony_ci /// Creates a new CodedInputStream reading data from the given 137ffe3c632Sopenharmony_ci /// stream and buffer, using the default limits. 138ffe3c632Sopenharmony_ci /// </summary> 139ffe3c632Sopenharmony_ci internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, bool leaveOpen) 140ffe3c632Sopenharmony_ci { 141ffe3c632Sopenharmony_ci this.input = input; 142ffe3c632Sopenharmony_ci this.buffer = buffer; 143ffe3c632Sopenharmony_ci this.state.bufferPos = bufferPos; 144ffe3c632Sopenharmony_ci this.state.bufferSize = bufferSize; 145ffe3c632Sopenharmony_ci this.state.sizeLimit = DefaultSizeLimit; 146ffe3c632Sopenharmony_ci this.state.recursionLimit = DefaultRecursionLimit; 147ffe3c632Sopenharmony_ci SegmentedBufferHelper.Initialize(this, out this.state.segmentedBufferHelper); 148ffe3c632Sopenharmony_ci this.leaveOpen = leaveOpen; 149ffe3c632Sopenharmony_ci 150ffe3c632Sopenharmony_ci this.state.currentLimit = int.MaxValue; 151ffe3c632Sopenharmony_ci } 152ffe3c632Sopenharmony_ci 153ffe3c632Sopenharmony_ci /// <summary> 154ffe3c632Sopenharmony_ci /// Creates a new CodedInputStream reading data from the given 155ffe3c632Sopenharmony_ci /// stream and buffer, using the specified limits. 156ffe3c632Sopenharmony_ci /// </summary> 157ffe3c632Sopenharmony_ci /// <remarks> 158ffe3c632Sopenharmony_ci /// This chains to the version with the default limits instead of vice versa to avoid 159ffe3c632Sopenharmony_ci /// having to check that the default values are valid every time. 160ffe3c632Sopenharmony_ci /// </remarks> 161ffe3c632Sopenharmony_ci internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit, bool leaveOpen) 162ffe3c632Sopenharmony_ci : this(input, buffer, bufferPos, bufferSize, leaveOpen) 163ffe3c632Sopenharmony_ci { 164ffe3c632Sopenharmony_ci if (sizeLimit <= 0) 165ffe3c632Sopenharmony_ci { 166ffe3c632Sopenharmony_ci throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive"); 167ffe3c632Sopenharmony_ci } 168ffe3c632Sopenharmony_ci if (recursionLimit <= 0) 169ffe3c632Sopenharmony_ci { 170ffe3c632Sopenharmony_ci throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive"); 171ffe3c632Sopenharmony_ci } 172ffe3c632Sopenharmony_ci this.state.sizeLimit = sizeLimit; 173ffe3c632Sopenharmony_ci this.state.recursionLimit = recursionLimit; 174ffe3c632Sopenharmony_ci } 175ffe3c632Sopenharmony_ci #endregion 176ffe3c632Sopenharmony_ci 177ffe3c632Sopenharmony_ci /// <summary> 178ffe3c632Sopenharmony_ci /// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading 179ffe3c632Sopenharmony_ci /// from an input stream. 180ffe3c632Sopenharmony_ci /// </summary> 181ffe3c632Sopenharmony_ci /// <remarks> 182ffe3c632Sopenharmony_ci /// This method exists separately from the constructor to reduce the number of constructor overloads. 183ffe3c632Sopenharmony_ci /// It is likely to be used considerably less frequently than the constructors, as the default limits 184ffe3c632Sopenharmony_ci /// are suitable for most use cases. 185ffe3c632Sopenharmony_ci /// </remarks> 186ffe3c632Sopenharmony_ci /// <param name="input">The input stream to read from</param> 187ffe3c632Sopenharmony_ci /// <param name="sizeLimit">The total limit of data to read from the stream.</param> 188ffe3c632Sopenharmony_ci /// <param name="recursionLimit">The maximum recursion depth to allow while reading.</param> 189ffe3c632Sopenharmony_ci /// <returns>A <c>CodedInputStream</c> reading from <paramref name="input"/> with the specified size 190ffe3c632Sopenharmony_ci /// and recursion limits.</returns> 191ffe3c632Sopenharmony_ci public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit) 192ffe3c632Sopenharmony_ci { 193ffe3c632Sopenharmony_ci // Note: we may want an overload accepting leaveOpen 194ffe3c632Sopenharmony_ci return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit, false); 195ffe3c632Sopenharmony_ci } 196ffe3c632Sopenharmony_ci 197ffe3c632Sopenharmony_ci /// <summary> 198ffe3c632Sopenharmony_ci /// Returns the current position in the input stream, or the position in the input buffer 199ffe3c632Sopenharmony_ci /// </summary> 200ffe3c632Sopenharmony_ci public long Position 201ffe3c632Sopenharmony_ci { 202ffe3c632Sopenharmony_ci get 203ffe3c632Sopenharmony_ci { 204ffe3c632Sopenharmony_ci if (input != null) 205ffe3c632Sopenharmony_ci { 206ffe3c632Sopenharmony_ci return input.Position - ((state.bufferSize + state.bufferSizeAfterLimit) - state.bufferPos); 207ffe3c632Sopenharmony_ci } 208ffe3c632Sopenharmony_ci return state.bufferPos; 209ffe3c632Sopenharmony_ci } 210ffe3c632Sopenharmony_ci } 211ffe3c632Sopenharmony_ci 212ffe3c632Sopenharmony_ci /// <summary> 213ffe3c632Sopenharmony_ci /// Returns the last tag read, or 0 if no tags have been read or we've read beyond 214ffe3c632Sopenharmony_ci /// the end of the stream. 215ffe3c632Sopenharmony_ci /// </summary> 216ffe3c632Sopenharmony_ci internal uint LastTag { get { return state.lastTag; } } 217ffe3c632Sopenharmony_ci 218ffe3c632Sopenharmony_ci /// <summary> 219ffe3c632Sopenharmony_ci /// Returns the size limit for this stream. 220ffe3c632Sopenharmony_ci /// </summary> 221ffe3c632Sopenharmony_ci /// <remarks> 222ffe3c632Sopenharmony_ci /// This limit is applied when reading from the underlying stream, as a sanity check. It is 223ffe3c632Sopenharmony_ci /// not applied when reading from a byte array data source without an underlying stream. 224ffe3c632Sopenharmony_ci /// The default value is Int32.MaxValue. 225ffe3c632Sopenharmony_ci /// </remarks> 226ffe3c632Sopenharmony_ci /// <value> 227ffe3c632Sopenharmony_ci /// The size limit. 228ffe3c632Sopenharmony_ci /// </value> 229ffe3c632Sopenharmony_ci public int SizeLimit { get { return state.sizeLimit; } } 230ffe3c632Sopenharmony_ci 231ffe3c632Sopenharmony_ci /// <summary> 232ffe3c632Sopenharmony_ci /// Returns the recursion limit for this stream. This limit is applied whilst reading messages, 233ffe3c632Sopenharmony_ci /// to avoid maliciously-recursive data. 234ffe3c632Sopenharmony_ci /// </summary> 235ffe3c632Sopenharmony_ci /// <remarks> 236ffe3c632Sopenharmony_ci /// The default limit is 100. 237ffe3c632Sopenharmony_ci /// </remarks> 238ffe3c632Sopenharmony_ci /// <value> 239ffe3c632Sopenharmony_ci /// The recursion limit for this stream. 240ffe3c632Sopenharmony_ci /// </value> 241ffe3c632Sopenharmony_ci public int RecursionLimit { get { return state.recursionLimit; } } 242ffe3c632Sopenharmony_ci 243ffe3c632Sopenharmony_ci /// <summary> 244ffe3c632Sopenharmony_ci /// Internal-only property; when set to true, unknown fields will be discarded while parsing. 245ffe3c632Sopenharmony_ci /// </summary> 246ffe3c632Sopenharmony_ci internal bool DiscardUnknownFields 247ffe3c632Sopenharmony_ci { 248ffe3c632Sopenharmony_ci get { return state.DiscardUnknownFields; } 249ffe3c632Sopenharmony_ci set { state.DiscardUnknownFields = value; } 250ffe3c632Sopenharmony_ci } 251ffe3c632Sopenharmony_ci 252ffe3c632Sopenharmony_ci /// <summary> 253ffe3c632Sopenharmony_ci /// Internal-only property; provides extension identifiers to compatible messages while parsing. 254ffe3c632Sopenharmony_ci /// </summary> 255ffe3c632Sopenharmony_ci internal ExtensionRegistry ExtensionRegistry 256ffe3c632Sopenharmony_ci { 257ffe3c632Sopenharmony_ci get { return state.ExtensionRegistry; } 258ffe3c632Sopenharmony_ci set { state.ExtensionRegistry = value; } 259ffe3c632Sopenharmony_ci } 260ffe3c632Sopenharmony_ci 261ffe3c632Sopenharmony_ci internal byte[] InternalBuffer => buffer; 262ffe3c632Sopenharmony_ci 263ffe3c632Sopenharmony_ci internal Stream InternalInputStream => input; 264ffe3c632Sopenharmony_ci 265ffe3c632Sopenharmony_ci internal ref ParserInternalState InternalState => ref state; 266ffe3c632Sopenharmony_ci 267ffe3c632Sopenharmony_ci /// <summary> 268ffe3c632Sopenharmony_ci /// Disposes of this instance, potentially closing any underlying stream. 269ffe3c632Sopenharmony_ci /// </summary> 270ffe3c632Sopenharmony_ci /// <remarks> 271ffe3c632Sopenharmony_ci /// As there is no flushing to perform here, disposing of a <see cref="CodedInputStream"/> which 272ffe3c632Sopenharmony_ci /// was constructed with the <c>leaveOpen</c> option parameter set to <c>true</c> (or one which 273ffe3c632Sopenharmony_ci /// was constructed to read from a byte array) has no effect. 274ffe3c632Sopenharmony_ci /// </remarks> 275ffe3c632Sopenharmony_ci public void Dispose() 276ffe3c632Sopenharmony_ci { 277ffe3c632Sopenharmony_ci if (!leaveOpen) 278ffe3c632Sopenharmony_ci { 279ffe3c632Sopenharmony_ci input.Dispose(); 280ffe3c632Sopenharmony_ci } 281ffe3c632Sopenharmony_ci } 282ffe3c632Sopenharmony_ci 283ffe3c632Sopenharmony_ci #region Validation 284ffe3c632Sopenharmony_ci /// <summary> 285ffe3c632Sopenharmony_ci /// Verifies that the last call to ReadTag() returned tag 0 - in other words, 286ffe3c632Sopenharmony_ci /// we've reached the end of the stream when we expected to. 287ffe3c632Sopenharmony_ci /// </summary> 288ffe3c632Sopenharmony_ci /// <exception cref="InvalidProtocolBufferException">The 289ffe3c632Sopenharmony_ci /// tag read was not the one specified</exception> 290ffe3c632Sopenharmony_ci internal void CheckReadEndOfStreamTag() 291ffe3c632Sopenharmony_ci { 292ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref state); 293ffe3c632Sopenharmony_ci } 294ffe3c632Sopenharmony_ci #endregion 295ffe3c632Sopenharmony_ci 296ffe3c632Sopenharmony_ci #region Reading of tags etc 297ffe3c632Sopenharmony_ci 298ffe3c632Sopenharmony_ci /// <summary> 299ffe3c632Sopenharmony_ci /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the 300ffe3c632Sopenharmony_ci /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the 301ffe3c632Sopenharmony_ci /// same value.) 302ffe3c632Sopenharmony_ci /// </summary> 303ffe3c632Sopenharmony_ci public uint PeekTag() 304ffe3c632Sopenharmony_ci { 305ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 306ffe3c632Sopenharmony_ci return ParsingPrimitives.PeekTag(ref span, ref state); 307ffe3c632Sopenharmony_ci } 308ffe3c632Sopenharmony_ci 309ffe3c632Sopenharmony_ci /// <summary> 310ffe3c632Sopenharmony_ci /// Reads a field tag, returning the tag of 0 for "end of stream". 311ffe3c632Sopenharmony_ci /// </summary> 312ffe3c632Sopenharmony_ci /// <remarks> 313ffe3c632Sopenharmony_ci /// If this method returns 0, it doesn't necessarily mean the end of all 314ffe3c632Sopenharmony_ci /// the data in this CodedInputStream; it may be the end of the logical stream 315ffe3c632Sopenharmony_ci /// for an embedded message, for example. 316ffe3c632Sopenharmony_ci /// </remarks> 317ffe3c632Sopenharmony_ci /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns> 318ffe3c632Sopenharmony_ci public uint ReadTag() 319ffe3c632Sopenharmony_ci { 320ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 321ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseTag(ref span, ref state); 322ffe3c632Sopenharmony_ci } 323ffe3c632Sopenharmony_ci 324ffe3c632Sopenharmony_ci /// <summary> 325ffe3c632Sopenharmony_ci /// Skips the data for the field with the tag we've just read. 326ffe3c632Sopenharmony_ci /// This should be called directly after <see cref="ReadTag"/>, when 327ffe3c632Sopenharmony_ci /// the caller wishes to skip an unknown field. 328ffe3c632Sopenharmony_ci /// </summary> 329ffe3c632Sopenharmony_ci /// <remarks> 330ffe3c632Sopenharmony_ci /// This method throws <see cref="InvalidProtocolBufferException"/> if the last-read tag was an end-group tag. 331ffe3c632Sopenharmony_ci /// If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the 332ffe3c632Sopenharmony_ci /// start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly 333ffe3c632Sopenharmony_ci /// resulting in an error if an end-group tag has not been paired with an earlier start-group tag. 334ffe3c632Sopenharmony_ci /// </remarks> 335ffe3c632Sopenharmony_ci /// <exception cref="InvalidProtocolBufferException">The last tag was an end-group tag</exception> 336ffe3c632Sopenharmony_ci /// <exception cref="InvalidOperationException">The last read operation read to the end of the logical stream</exception> 337ffe3c632Sopenharmony_ci public void SkipLastField() 338ffe3c632Sopenharmony_ci { 339ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 340ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.SkipLastField(ref span, ref state); 341ffe3c632Sopenharmony_ci } 342ffe3c632Sopenharmony_ci 343ffe3c632Sopenharmony_ci /// <summary> 344ffe3c632Sopenharmony_ci /// Skip a group. 345ffe3c632Sopenharmony_ci /// </summary> 346ffe3c632Sopenharmony_ci internal void SkipGroup(uint startGroupTag) 347ffe3c632Sopenharmony_ci { 348ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 349ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.SkipGroup(ref span, ref state, startGroupTag); 350ffe3c632Sopenharmony_ci } 351ffe3c632Sopenharmony_ci 352ffe3c632Sopenharmony_ci /// <summary> 353ffe3c632Sopenharmony_ci /// Reads a double field from the stream. 354ffe3c632Sopenharmony_ci /// </summary> 355ffe3c632Sopenharmony_ci public double ReadDouble() 356ffe3c632Sopenharmony_ci { 357ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 358ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseDouble(ref span, ref state); 359ffe3c632Sopenharmony_ci } 360ffe3c632Sopenharmony_ci 361ffe3c632Sopenharmony_ci /// <summary> 362ffe3c632Sopenharmony_ci /// Reads a float field from the stream. 363ffe3c632Sopenharmony_ci /// </summary> 364ffe3c632Sopenharmony_ci public float ReadFloat() 365ffe3c632Sopenharmony_ci { 366ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 367ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseFloat(ref span, ref state); 368ffe3c632Sopenharmony_ci } 369ffe3c632Sopenharmony_ci 370ffe3c632Sopenharmony_ci /// <summary> 371ffe3c632Sopenharmony_ci /// Reads a uint64 field from the stream. 372ffe3c632Sopenharmony_ci /// </summary> 373ffe3c632Sopenharmony_ci public ulong ReadUInt64() 374ffe3c632Sopenharmony_ci { 375ffe3c632Sopenharmony_ci return ReadRawVarint64(); 376ffe3c632Sopenharmony_ci } 377ffe3c632Sopenharmony_ci 378ffe3c632Sopenharmony_ci /// <summary> 379ffe3c632Sopenharmony_ci /// Reads an int64 field from the stream. 380ffe3c632Sopenharmony_ci /// </summary> 381ffe3c632Sopenharmony_ci public long ReadInt64() 382ffe3c632Sopenharmony_ci { 383ffe3c632Sopenharmony_ci return (long) ReadRawVarint64(); 384ffe3c632Sopenharmony_ci } 385ffe3c632Sopenharmony_ci 386ffe3c632Sopenharmony_ci /// <summary> 387ffe3c632Sopenharmony_ci /// Reads an int32 field from the stream. 388ffe3c632Sopenharmony_ci /// </summary> 389ffe3c632Sopenharmony_ci public int ReadInt32() 390ffe3c632Sopenharmony_ci { 391ffe3c632Sopenharmony_ci return (int) ReadRawVarint32(); 392ffe3c632Sopenharmony_ci } 393ffe3c632Sopenharmony_ci 394ffe3c632Sopenharmony_ci /// <summary> 395ffe3c632Sopenharmony_ci /// Reads a fixed64 field from the stream. 396ffe3c632Sopenharmony_ci /// </summary> 397ffe3c632Sopenharmony_ci public ulong ReadFixed64() 398ffe3c632Sopenharmony_ci { 399ffe3c632Sopenharmony_ci return ReadRawLittleEndian64(); 400ffe3c632Sopenharmony_ci } 401ffe3c632Sopenharmony_ci 402ffe3c632Sopenharmony_ci /// <summary> 403ffe3c632Sopenharmony_ci /// Reads a fixed32 field from the stream. 404ffe3c632Sopenharmony_ci /// </summary> 405ffe3c632Sopenharmony_ci public uint ReadFixed32() 406ffe3c632Sopenharmony_ci { 407ffe3c632Sopenharmony_ci return ReadRawLittleEndian32(); 408ffe3c632Sopenharmony_ci } 409ffe3c632Sopenharmony_ci 410ffe3c632Sopenharmony_ci /// <summary> 411ffe3c632Sopenharmony_ci /// Reads a bool field from the stream. 412ffe3c632Sopenharmony_ci /// </summary> 413ffe3c632Sopenharmony_ci public bool ReadBool() 414ffe3c632Sopenharmony_ci { 415ffe3c632Sopenharmony_ci return ReadRawVarint64() != 0; 416ffe3c632Sopenharmony_ci } 417ffe3c632Sopenharmony_ci 418ffe3c632Sopenharmony_ci /// <summary> 419ffe3c632Sopenharmony_ci /// Reads a string field from the stream. 420ffe3c632Sopenharmony_ci /// </summary> 421ffe3c632Sopenharmony_ci public string ReadString() 422ffe3c632Sopenharmony_ci { 423ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 424ffe3c632Sopenharmony_ci return ParsingPrimitives.ReadString(ref span, ref state); 425ffe3c632Sopenharmony_ci } 426ffe3c632Sopenharmony_ci 427ffe3c632Sopenharmony_ci /// <summary> 428ffe3c632Sopenharmony_ci /// Reads an embedded message field value from the stream. 429ffe3c632Sopenharmony_ci /// </summary> 430ffe3c632Sopenharmony_ci public void ReadMessage(IMessage builder) 431ffe3c632Sopenharmony_ci { 432ffe3c632Sopenharmony_ci // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalMergeFrom method), 433ffe3c632Sopenharmony_ci // what we're doing here works fine, but could be more efficient. 434ffe3c632Sopenharmony_ci // What happends is that we first initialize a ParseContext from the current coded input stream only to parse the length of the message, at which point 435ffe3c632Sopenharmony_ci // we will need to switch back again to CodedInputStream-based parsing (which involves copying and storing the state) to be able to 436ffe3c632Sopenharmony_ci // invoke the legacy MergeFrom(CodedInputStream) method. 437ffe3c632Sopenharmony_ci // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). 438ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 439ffe3c632Sopenharmony_ci ParseContext.Initialize(ref span, ref state, out ParseContext ctx); 440ffe3c632Sopenharmony_ci try 441ffe3c632Sopenharmony_ci { 442ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.ReadMessage(ref ctx, builder); 443ffe3c632Sopenharmony_ci } 444ffe3c632Sopenharmony_ci finally 445ffe3c632Sopenharmony_ci { 446ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 447ffe3c632Sopenharmony_ci } 448ffe3c632Sopenharmony_ci } 449ffe3c632Sopenharmony_ci 450ffe3c632Sopenharmony_ci /// <summary> 451ffe3c632Sopenharmony_ci /// Reads an embedded group field from the stream. 452ffe3c632Sopenharmony_ci /// </summary> 453ffe3c632Sopenharmony_ci public void ReadGroup(IMessage builder) 454ffe3c632Sopenharmony_ci { 455ffe3c632Sopenharmony_ci ParseContext.Initialize(this, out ParseContext ctx); 456ffe3c632Sopenharmony_ci try 457ffe3c632Sopenharmony_ci { 458ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.ReadGroup(ref ctx, builder); 459ffe3c632Sopenharmony_ci } 460ffe3c632Sopenharmony_ci finally 461ffe3c632Sopenharmony_ci { 462ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 463ffe3c632Sopenharmony_ci } 464ffe3c632Sopenharmony_ci } 465ffe3c632Sopenharmony_ci 466ffe3c632Sopenharmony_ci /// <summary> 467ffe3c632Sopenharmony_ci /// Reads a bytes field value from the stream. 468ffe3c632Sopenharmony_ci /// </summary> 469ffe3c632Sopenharmony_ci public ByteString ReadBytes() 470ffe3c632Sopenharmony_ci { 471ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 472ffe3c632Sopenharmony_ci return ParsingPrimitives.ReadBytes(ref span, ref state); 473ffe3c632Sopenharmony_ci } 474ffe3c632Sopenharmony_ci 475ffe3c632Sopenharmony_ci /// <summary> 476ffe3c632Sopenharmony_ci /// Reads a uint32 field value from the stream. 477ffe3c632Sopenharmony_ci /// </summary> 478ffe3c632Sopenharmony_ci public uint ReadUInt32() 479ffe3c632Sopenharmony_ci { 480ffe3c632Sopenharmony_ci return ReadRawVarint32(); 481ffe3c632Sopenharmony_ci } 482ffe3c632Sopenharmony_ci 483ffe3c632Sopenharmony_ci /// <summary> 484ffe3c632Sopenharmony_ci /// Reads an enum field value from the stream. 485ffe3c632Sopenharmony_ci /// </summary> 486ffe3c632Sopenharmony_ci public int ReadEnum() 487ffe3c632Sopenharmony_ci { 488ffe3c632Sopenharmony_ci // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. 489ffe3c632Sopenharmony_ci return (int) ReadRawVarint32(); 490ffe3c632Sopenharmony_ci } 491ffe3c632Sopenharmony_ci 492ffe3c632Sopenharmony_ci /// <summary> 493ffe3c632Sopenharmony_ci /// Reads an sfixed32 field value from the stream. 494ffe3c632Sopenharmony_ci /// </summary> 495ffe3c632Sopenharmony_ci public int ReadSFixed32() 496ffe3c632Sopenharmony_ci { 497ffe3c632Sopenharmony_ci return (int) ReadRawLittleEndian32(); 498ffe3c632Sopenharmony_ci } 499ffe3c632Sopenharmony_ci 500ffe3c632Sopenharmony_ci /// <summary> 501ffe3c632Sopenharmony_ci /// Reads an sfixed64 field value from the stream. 502ffe3c632Sopenharmony_ci /// </summary> 503ffe3c632Sopenharmony_ci public long ReadSFixed64() 504ffe3c632Sopenharmony_ci { 505ffe3c632Sopenharmony_ci return (long) ReadRawLittleEndian64(); 506ffe3c632Sopenharmony_ci } 507ffe3c632Sopenharmony_ci 508ffe3c632Sopenharmony_ci /// <summary> 509ffe3c632Sopenharmony_ci /// Reads an sint32 field value from the stream. 510ffe3c632Sopenharmony_ci /// </summary> 511ffe3c632Sopenharmony_ci public int ReadSInt32() 512ffe3c632Sopenharmony_ci { 513ffe3c632Sopenharmony_ci return ParsingPrimitives.DecodeZigZag32(ReadRawVarint32()); 514ffe3c632Sopenharmony_ci } 515ffe3c632Sopenharmony_ci 516ffe3c632Sopenharmony_ci /// <summary> 517ffe3c632Sopenharmony_ci /// Reads an sint64 field value from the stream. 518ffe3c632Sopenharmony_ci /// </summary> 519ffe3c632Sopenharmony_ci public long ReadSInt64() 520ffe3c632Sopenharmony_ci { 521ffe3c632Sopenharmony_ci return ParsingPrimitives.DecodeZigZag64(ReadRawVarint64()); 522ffe3c632Sopenharmony_ci } 523ffe3c632Sopenharmony_ci 524ffe3c632Sopenharmony_ci /// <summary> 525ffe3c632Sopenharmony_ci /// Reads a length for length-delimited data. 526ffe3c632Sopenharmony_ci /// </summary> 527ffe3c632Sopenharmony_ci /// <remarks> 528ffe3c632Sopenharmony_ci /// This is internally just reading a varint, but this method exists 529ffe3c632Sopenharmony_ci /// to make the calling code clearer. 530ffe3c632Sopenharmony_ci /// </remarks> 531ffe3c632Sopenharmony_ci public int ReadLength() 532ffe3c632Sopenharmony_ci { 533ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 534ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseLength(ref span, ref state); 535ffe3c632Sopenharmony_ci } 536ffe3c632Sopenharmony_ci 537ffe3c632Sopenharmony_ci /// <summary> 538ffe3c632Sopenharmony_ci /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>, 539ffe3c632Sopenharmony_ci /// the tag is consumed and the method returns <c>true</c>; otherwise, the 540ffe3c632Sopenharmony_ci /// stream is left in the original position and the method returns <c>false</c>. 541ffe3c632Sopenharmony_ci /// </summary> 542ffe3c632Sopenharmony_ci public bool MaybeConsumeTag(uint tag) 543ffe3c632Sopenharmony_ci { 544ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 545ffe3c632Sopenharmony_ci return ParsingPrimitives.MaybeConsumeTag(ref span, ref state, tag); 546ffe3c632Sopenharmony_ci } 547ffe3c632Sopenharmony_ci 548ffe3c632Sopenharmony_ci#endregion 549ffe3c632Sopenharmony_ci 550ffe3c632Sopenharmony_ci #region Underlying reading primitives 551ffe3c632Sopenharmony_ci 552ffe3c632Sopenharmony_ci /// <summary> 553ffe3c632Sopenharmony_ci /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits. 554ffe3c632Sopenharmony_ci /// This method is optimised for the case where we've got lots of data in the buffer. 555ffe3c632Sopenharmony_ci /// That means we can check the size just once, then just read directly from the buffer 556ffe3c632Sopenharmony_ci /// without constant rechecking of the buffer length. 557ffe3c632Sopenharmony_ci /// </summary> 558ffe3c632Sopenharmony_ci internal uint ReadRawVarint32() 559ffe3c632Sopenharmony_ci { 560ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 561ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseRawVarint32(ref span, ref state); 562ffe3c632Sopenharmony_ci } 563ffe3c632Sopenharmony_ci 564ffe3c632Sopenharmony_ci /// <summary> 565ffe3c632Sopenharmony_ci /// Reads a varint from the input one byte at a time, so that it does not 566ffe3c632Sopenharmony_ci /// read any bytes after the end of the varint. If you simply wrapped the 567ffe3c632Sopenharmony_ci /// stream in a CodedInputStream and used ReadRawVarint32(Stream) 568ffe3c632Sopenharmony_ci /// then you would probably end up reading past the end of the varint since 569ffe3c632Sopenharmony_ci /// CodedInputStream buffers its input. 570ffe3c632Sopenharmony_ci /// </summary> 571ffe3c632Sopenharmony_ci /// <param name="input"></param> 572ffe3c632Sopenharmony_ci /// <returns></returns> 573ffe3c632Sopenharmony_ci internal static uint ReadRawVarint32(Stream input) 574ffe3c632Sopenharmony_ci { 575ffe3c632Sopenharmony_ci return ParsingPrimitives.ReadRawVarint32(input); 576ffe3c632Sopenharmony_ci } 577ffe3c632Sopenharmony_ci 578ffe3c632Sopenharmony_ci /// <summary> 579ffe3c632Sopenharmony_ci /// Reads a raw varint from the stream. 580ffe3c632Sopenharmony_ci /// </summary> 581ffe3c632Sopenharmony_ci internal ulong ReadRawVarint64() 582ffe3c632Sopenharmony_ci { 583ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 584ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseRawVarint64(ref span, ref state); 585ffe3c632Sopenharmony_ci } 586ffe3c632Sopenharmony_ci 587ffe3c632Sopenharmony_ci /// <summary> 588ffe3c632Sopenharmony_ci /// Reads a 32-bit little-endian integer from the stream. 589ffe3c632Sopenharmony_ci /// </summary> 590ffe3c632Sopenharmony_ci internal uint ReadRawLittleEndian32() 591ffe3c632Sopenharmony_ci { 592ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 593ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseRawLittleEndian32(ref span, ref state); 594ffe3c632Sopenharmony_ci } 595ffe3c632Sopenharmony_ci 596ffe3c632Sopenharmony_ci /// <summary> 597ffe3c632Sopenharmony_ci /// Reads a 64-bit little-endian integer from the stream. 598ffe3c632Sopenharmony_ci /// </summary> 599ffe3c632Sopenharmony_ci internal ulong ReadRawLittleEndian64() 600ffe3c632Sopenharmony_ci { 601ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 602ffe3c632Sopenharmony_ci return ParsingPrimitives.ParseRawLittleEndian64(ref span, ref state); 603ffe3c632Sopenharmony_ci } 604ffe3c632Sopenharmony_ci #endregion 605ffe3c632Sopenharmony_ci 606ffe3c632Sopenharmony_ci #region Internal reading and buffer management 607ffe3c632Sopenharmony_ci 608ffe3c632Sopenharmony_ci /// <summary> 609ffe3c632Sopenharmony_ci /// Sets currentLimit to (current position) + byteLimit. This is called 610ffe3c632Sopenharmony_ci /// when descending into a length-delimited embedded message. The previous 611ffe3c632Sopenharmony_ci /// limit is returned. 612ffe3c632Sopenharmony_ci /// </summary> 613ffe3c632Sopenharmony_ci /// <returns>The old limit.</returns> 614ffe3c632Sopenharmony_ci internal int PushLimit(int byteLimit) 615ffe3c632Sopenharmony_ci { 616ffe3c632Sopenharmony_ci return SegmentedBufferHelper.PushLimit(ref state, byteLimit); 617ffe3c632Sopenharmony_ci } 618ffe3c632Sopenharmony_ci 619ffe3c632Sopenharmony_ci /// <summary> 620ffe3c632Sopenharmony_ci /// Discards the current limit, returning the previous limit. 621ffe3c632Sopenharmony_ci /// </summary> 622ffe3c632Sopenharmony_ci internal void PopLimit(int oldLimit) 623ffe3c632Sopenharmony_ci { 624ffe3c632Sopenharmony_ci SegmentedBufferHelper.PopLimit(ref state, oldLimit); 625ffe3c632Sopenharmony_ci } 626ffe3c632Sopenharmony_ci 627ffe3c632Sopenharmony_ci /// <summary> 628ffe3c632Sopenharmony_ci /// Returns whether or not all the data before the limit has been read. 629ffe3c632Sopenharmony_ci /// </summary> 630ffe3c632Sopenharmony_ci /// <returns></returns> 631ffe3c632Sopenharmony_ci internal bool ReachedLimit 632ffe3c632Sopenharmony_ci { 633ffe3c632Sopenharmony_ci get 634ffe3c632Sopenharmony_ci { 635ffe3c632Sopenharmony_ci return SegmentedBufferHelper.IsReachedLimit(ref state); 636ffe3c632Sopenharmony_ci } 637ffe3c632Sopenharmony_ci } 638ffe3c632Sopenharmony_ci 639ffe3c632Sopenharmony_ci /// <summary> 640ffe3c632Sopenharmony_ci /// Returns true if the stream has reached the end of the input. This is the 641ffe3c632Sopenharmony_ci /// case if either the end of the underlying input source has been reached or 642ffe3c632Sopenharmony_ci /// the stream has reached a limit created using PushLimit. 643ffe3c632Sopenharmony_ci /// </summary> 644ffe3c632Sopenharmony_ci public bool IsAtEnd 645ffe3c632Sopenharmony_ci { 646ffe3c632Sopenharmony_ci get 647ffe3c632Sopenharmony_ci { 648ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 649ffe3c632Sopenharmony_ci return SegmentedBufferHelper.IsAtEnd(ref span, ref state); 650ffe3c632Sopenharmony_ci } 651ffe3c632Sopenharmony_ci } 652ffe3c632Sopenharmony_ci 653ffe3c632Sopenharmony_ci /// <summary> 654ffe3c632Sopenharmony_ci /// Called when buffer is empty to read more bytes from the 655ffe3c632Sopenharmony_ci /// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that 656ffe3c632Sopenharmony_ci /// either there will be at least one byte in the buffer when it returns 657ffe3c632Sopenharmony_ci /// or it will throw an exception. If <paramref name="mustSucceed"/> is false, 658ffe3c632Sopenharmony_ci /// RefillBuffer() returns false if no more bytes were available. 659ffe3c632Sopenharmony_ci /// </summary> 660ffe3c632Sopenharmony_ci /// <param name="mustSucceed"></param> 661ffe3c632Sopenharmony_ci /// <returns></returns> 662ffe3c632Sopenharmony_ci private bool RefillBuffer(bool mustSucceed) 663ffe3c632Sopenharmony_ci { 664ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 665ffe3c632Sopenharmony_ci return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed); 666ffe3c632Sopenharmony_ci } 667ffe3c632Sopenharmony_ci 668ffe3c632Sopenharmony_ci /// <summary> 669ffe3c632Sopenharmony_ci /// Reads a fixed size of bytes from the input. 670ffe3c632Sopenharmony_ci /// </summary> 671ffe3c632Sopenharmony_ci /// <exception cref="InvalidProtocolBufferException"> 672ffe3c632Sopenharmony_ci /// the end of the stream or the current limit was reached 673ffe3c632Sopenharmony_ci /// </exception> 674ffe3c632Sopenharmony_ci internal byte[] ReadRawBytes(int size) 675ffe3c632Sopenharmony_ci { 676ffe3c632Sopenharmony_ci var span = new ReadOnlySpan<byte>(buffer); 677ffe3c632Sopenharmony_ci return ParsingPrimitives.ReadRawBytes(ref span, ref state, size); 678ffe3c632Sopenharmony_ci } 679ffe3c632Sopenharmony_ci 680ffe3c632Sopenharmony_ci /// <summary> 681ffe3c632Sopenharmony_ci /// Reads a top-level message or a nested message after the limits for this message have been pushed. 682ffe3c632Sopenharmony_ci /// (parser will proceed until the end of the current limit) 683ffe3c632Sopenharmony_ci /// NOTE: this method needs to be public because it's invoked by the generated code - e.g. msg.MergeFrom(CodedInputStream input) method 684ffe3c632Sopenharmony_ci /// </summary> 685ffe3c632Sopenharmony_ci public void ReadRawMessage(IMessage message) 686ffe3c632Sopenharmony_ci { 687ffe3c632Sopenharmony_ci ParseContext.Initialize(this, out ParseContext ctx); 688ffe3c632Sopenharmony_ci try 689ffe3c632Sopenharmony_ci { 690ffe3c632Sopenharmony_ci ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); 691ffe3c632Sopenharmony_ci } 692ffe3c632Sopenharmony_ci finally 693ffe3c632Sopenharmony_ci { 694ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 695ffe3c632Sopenharmony_ci } 696ffe3c632Sopenharmony_ci } 697ffe3c632Sopenharmony_ci#endregion 698ffe3c632Sopenharmony_ci } 699ffe3c632Sopenharmony_ci} 700