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.IO; 36ffe3c632Sopenharmony_ciusing System.Security; 37ffe3c632Sopenharmony_ciusing System.Text; 38ffe3c632Sopenharmony_ci 39ffe3c632Sopenharmony_cinamespace Google.Protobuf 40ffe3c632Sopenharmony_ci{ 41ffe3c632Sopenharmony_ci /// <summary> 42ffe3c632Sopenharmony_ci /// Encodes and writes protocol message fields. 43ffe3c632Sopenharmony_ci /// </summary> 44ffe3c632Sopenharmony_ci /// <remarks> 45ffe3c632Sopenharmony_ci /// <para> 46ffe3c632Sopenharmony_ci /// This class is generally used by generated code to write appropriate 47ffe3c632Sopenharmony_ci /// primitives to the stream. It effectively encapsulates the lowest 48ffe3c632Sopenharmony_ci /// levels of protocol buffer format. Unlike some other implementations, 49ffe3c632Sopenharmony_ci /// this does not include combined "write tag and value" methods. Generated 50ffe3c632Sopenharmony_ci /// code knows the exact byte representations of the tags they're going to write, 51ffe3c632Sopenharmony_ci /// so there's no need to re-encode them each time. Manually-written code calling 52ffe3c632Sopenharmony_ci /// this class should just call one of the <c>WriteTag</c> overloads before each value. 53ffe3c632Sopenharmony_ci /// </para> 54ffe3c632Sopenharmony_ci /// <para> 55ffe3c632Sopenharmony_ci /// Repeated fields and map fields are not handled by this class; use <c>RepeatedField<T></c> 56ffe3c632Sopenharmony_ci /// and <c>MapField<TKey, TValue></c> to serialize such fields. 57ffe3c632Sopenharmony_ci /// </para> 58ffe3c632Sopenharmony_ci /// </remarks> 59ffe3c632Sopenharmony_ci [SecuritySafeCritical] 60ffe3c632Sopenharmony_ci public sealed partial class CodedOutputStream : IDisposable 61ffe3c632Sopenharmony_ci { 62ffe3c632Sopenharmony_ci /// <summary> 63ffe3c632Sopenharmony_ci /// The buffer size used by CreateInstance(Stream). 64ffe3c632Sopenharmony_ci /// </summary> 65ffe3c632Sopenharmony_ci public static readonly int DefaultBufferSize = 4096; 66ffe3c632Sopenharmony_ci 67ffe3c632Sopenharmony_ci private readonly bool leaveOpen; 68ffe3c632Sopenharmony_ci private readonly byte[] buffer; 69ffe3c632Sopenharmony_ci private WriterInternalState state; 70ffe3c632Sopenharmony_ci 71ffe3c632Sopenharmony_ci private readonly Stream output; 72ffe3c632Sopenharmony_ci 73ffe3c632Sopenharmony_ci #region Construction 74ffe3c632Sopenharmony_ci /// <summary> 75ffe3c632Sopenharmony_ci /// Creates a new CodedOutputStream that writes directly to the given 76ffe3c632Sopenharmony_ci /// byte array. If more bytes are written than fit in the array, 77ffe3c632Sopenharmony_ci /// OutOfSpaceException will be thrown. 78ffe3c632Sopenharmony_ci /// </summary> 79ffe3c632Sopenharmony_ci public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length) 80ffe3c632Sopenharmony_ci { 81ffe3c632Sopenharmony_ci } 82ffe3c632Sopenharmony_ci 83ffe3c632Sopenharmony_ci /// <summary> 84ffe3c632Sopenharmony_ci /// Creates a new CodedOutputStream that writes directly to the given 85ffe3c632Sopenharmony_ci /// byte array slice. If more bytes are written than fit in the array, 86ffe3c632Sopenharmony_ci /// OutOfSpaceException will be thrown. 87ffe3c632Sopenharmony_ci /// </summary> 88ffe3c632Sopenharmony_ci private CodedOutputStream(byte[] buffer, int offset, int length) 89ffe3c632Sopenharmony_ci { 90ffe3c632Sopenharmony_ci this.output = null; 91ffe3c632Sopenharmony_ci this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer)); 92ffe3c632Sopenharmony_ci this.state.position = offset; 93ffe3c632Sopenharmony_ci this.state.limit = offset + length; 94ffe3c632Sopenharmony_ci WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); 95ffe3c632Sopenharmony_ci leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference 96ffe3c632Sopenharmony_ci } 97ffe3c632Sopenharmony_ci 98ffe3c632Sopenharmony_ci private CodedOutputStream(Stream output, byte[] buffer, bool leaveOpen) 99ffe3c632Sopenharmony_ci { 100ffe3c632Sopenharmony_ci this.output = ProtoPreconditions.CheckNotNull(output, nameof(output)); 101ffe3c632Sopenharmony_ci this.buffer = buffer; 102ffe3c632Sopenharmony_ci this.state.position = 0; 103ffe3c632Sopenharmony_ci this.state.limit = buffer.Length; 104ffe3c632Sopenharmony_ci WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); 105ffe3c632Sopenharmony_ci this.leaveOpen = leaveOpen; 106ffe3c632Sopenharmony_ci } 107ffe3c632Sopenharmony_ci 108ffe3c632Sopenharmony_ci /// <summary> 109ffe3c632Sopenharmony_ci /// Creates a new <see cref="CodedOutputStream" /> which write to the given stream, and disposes of that 110ffe3c632Sopenharmony_ci /// stream when the returned <c>CodedOutputStream</c> is disposed. 111ffe3c632Sopenharmony_ci /// </summary> 112ffe3c632Sopenharmony_ci /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param> 113ffe3c632Sopenharmony_ci public CodedOutputStream(Stream output) : this(output, DefaultBufferSize, false) 114ffe3c632Sopenharmony_ci { 115ffe3c632Sopenharmony_ci } 116ffe3c632Sopenharmony_ci 117ffe3c632Sopenharmony_ci /// <summary> 118ffe3c632Sopenharmony_ci /// Creates a new CodedOutputStream which write to the given stream and uses 119ffe3c632Sopenharmony_ci /// the specified buffer size. 120ffe3c632Sopenharmony_ci /// </summary> 121ffe3c632Sopenharmony_ci /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param> 122ffe3c632Sopenharmony_ci /// <param name="bufferSize">The size of buffer to use internally.</param> 123ffe3c632Sopenharmony_ci public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize], false) 124ffe3c632Sopenharmony_ci { 125ffe3c632Sopenharmony_ci } 126ffe3c632Sopenharmony_ci 127ffe3c632Sopenharmony_ci /// <summary> 128ffe3c632Sopenharmony_ci /// Creates a new CodedOutputStream which write to the given stream. 129ffe3c632Sopenharmony_ci /// </summary> 130ffe3c632Sopenharmony_ci /// <param name="output">The stream to write to.</param> 131ffe3c632Sopenharmony_ci /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed; 132ffe3c632Sopenharmony_ci /// if <c>false</c>, the provided stream is disposed as well.</param> 133ffe3c632Sopenharmony_ci public CodedOutputStream(Stream output, bool leaveOpen) : this(output, DefaultBufferSize, leaveOpen) 134ffe3c632Sopenharmony_ci { 135ffe3c632Sopenharmony_ci } 136ffe3c632Sopenharmony_ci 137ffe3c632Sopenharmony_ci /// <summary> 138ffe3c632Sopenharmony_ci /// Creates a new CodedOutputStream which write to the given stream and uses 139ffe3c632Sopenharmony_ci /// the specified buffer size. 140ffe3c632Sopenharmony_ci /// </summary> 141ffe3c632Sopenharmony_ci /// <param name="output">The stream to write to.</param> 142ffe3c632Sopenharmony_ci /// <param name="bufferSize">The size of buffer to use internally.</param> 143ffe3c632Sopenharmony_ci /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed; 144ffe3c632Sopenharmony_ci /// if <c>false</c>, the provided stream is disposed as well.</param> 145ffe3c632Sopenharmony_ci public CodedOutputStream(Stream output, int bufferSize, bool leaveOpen) : this(output, new byte[bufferSize], leaveOpen) 146ffe3c632Sopenharmony_ci { 147ffe3c632Sopenharmony_ci } 148ffe3c632Sopenharmony_ci #endregion 149ffe3c632Sopenharmony_ci 150ffe3c632Sopenharmony_ci /// <summary> 151ffe3c632Sopenharmony_ci /// Returns the current position in the stream, or the position in the output buffer 152ffe3c632Sopenharmony_ci /// </summary> 153ffe3c632Sopenharmony_ci public long Position 154ffe3c632Sopenharmony_ci { 155ffe3c632Sopenharmony_ci get 156ffe3c632Sopenharmony_ci { 157ffe3c632Sopenharmony_ci if (output != null) 158ffe3c632Sopenharmony_ci { 159ffe3c632Sopenharmony_ci return output.Position + state.position; 160ffe3c632Sopenharmony_ci } 161ffe3c632Sopenharmony_ci return state.position; 162ffe3c632Sopenharmony_ci } 163ffe3c632Sopenharmony_ci } 164ffe3c632Sopenharmony_ci 165ffe3c632Sopenharmony_ci #region Writing of values (not including tags) 166ffe3c632Sopenharmony_ci 167ffe3c632Sopenharmony_ci /// <summary> 168ffe3c632Sopenharmony_ci /// Writes a double field value, without a tag, to the stream. 169ffe3c632Sopenharmony_ci /// </summary> 170ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 171ffe3c632Sopenharmony_ci public void WriteDouble(double value) 172ffe3c632Sopenharmony_ci { 173ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 174ffe3c632Sopenharmony_ci WritingPrimitives.WriteDouble(ref span, ref state, value); 175ffe3c632Sopenharmony_ci } 176ffe3c632Sopenharmony_ci 177ffe3c632Sopenharmony_ci /// <summary> 178ffe3c632Sopenharmony_ci /// Writes a float field value, without a tag, to the stream. 179ffe3c632Sopenharmony_ci /// </summary> 180ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 181ffe3c632Sopenharmony_ci public void WriteFloat(float value) 182ffe3c632Sopenharmony_ci { 183ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 184ffe3c632Sopenharmony_ci WritingPrimitives.WriteFloat(ref span, ref state, value); 185ffe3c632Sopenharmony_ci } 186ffe3c632Sopenharmony_ci 187ffe3c632Sopenharmony_ci /// <summary> 188ffe3c632Sopenharmony_ci /// Writes a uint64 field value, without a tag, to the stream. 189ffe3c632Sopenharmony_ci /// </summary> 190ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 191ffe3c632Sopenharmony_ci public void WriteUInt64(ulong value) 192ffe3c632Sopenharmony_ci { 193ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 194ffe3c632Sopenharmony_ci WritingPrimitives.WriteUInt64(ref span, ref state, value); 195ffe3c632Sopenharmony_ci } 196ffe3c632Sopenharmony_ci 197ffe3c632Sopenharmony_ci /// <summary> 198ffe3c632Sopenharmony_ci /// Writes an int64 field value, without a tag, to the stream. 199ffe3c632Sopenharmony_ci /// </summary> 200ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 201ffe3c632Sopenharmony_ci public void WriteInt64(long value) 202ffe3c632Sopenharmony_ci { 203ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 204ffe3c632Sopenharmony_ci WritingPrimitives.WriteInt64(ref span, ref state, value); 205ffe3c632Sopenharmony_ci } 206ffe3c632Sopenharmony_ci 207ffe3c632Sopenharmony_ci /// <summary> 208ffe3c632Sopenharmony_ci /// Writes an int32 field value, without a tag, to the stream. 209ffe3c632Sopenharmony_ci /// </summary> 210ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 211ffe3c632Sopenharmony_ci public void WriteInt32(int value) 212ffe3c632Sopenharmony_ci { 213ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 214ffe3c632Sopenharmony_ci WritingPrimitives.WriteInt32(ref span, ref state, value); 215ffe3c632Sopenharmony_ci } 216ffe3c632Sopenharmony_ci 217ffe3c632Sopenharmony_ci /// <summary> 218ffe3c632Sopenharmony_ci /// Writes a fixed64 field value, without a tag, to the stream. 219ffe3c632Sopenharmony_ci /// </summary> 220ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 221ffe3c632Sopenharmony_ci public void WriteFixed64(ulong value) 222ffe3c632Sopenharmony_ci { 223ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 224ffe3c632Sopenharmony_ci WritingPrimitives.WriteFixed64(ref span, ref state, value); 225ffe3c632Sopenharmony_ci } 226ffe3c632Sopenharmony_ci 227ffe3c632Sopenharmony_ci /// <summary> 228ffe3c632Sopenharmony_ci /// Writes a fixed32 field value, without a tag, to the stream. 229ffe3c632Sopenharmony_ci /// </summary> 230ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 231ffe3c632Sopenharmony_ci public void WriteFixed32(uint value) 232ffe3c632Sopenharmony_ci { 233ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 234ffe3c632Sopenharmony_ci WritingPrimitives.WriteFixed32(ref span, ref state, value); 235ffe3c632Sopenharmony_ci } 236ffe3c632Sopenharmony_ci 237ffe3c632Sopenharmony_ci /// <summary> 238ffe3c632Sopenharmony_ci /// Writes a bool field value, without a tag, to the stream. 239ffe3c632Sopenharmony_ci /// </summary> 240ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 241ffe3c632Sopenharmony_ci public void WriteBool(bool value) 242ffe3c632Sopenharmony_ci { 243ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 244ffe3c632Sopenharmony_ci WritingPrimitives.WriteBool(ref span, ref state, value); 245ffe3c632Sopenharmony_ci } 246ffe3c632Sopenharmony_ci 247ffe3c632Sopenharmony_ci /// <summary> 248ffe3c632Sopenharmony_ci /// Writes a string field value, without a tag, to the stream. 249ffe3c632Sopenharmony_ci /// The data is length-prefixed. 250ffe3c632Sopenharmony_ci /// </summary> 251ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 252ffe3c632Sopenharmony_ci public void WriteString(string value) 253ffe3c632Sopenharmony_ci { 254ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 255ffe3c632Sopenharmony_ci WritingPrimitives.WriteString(ref span, ref state, value); 256ffe3c632Sopenharmony_ci } 257ffe3c632Sopenharmony_ci 258ffe3c632Sopenharmony_ci /// <summary> 259ffe3c632Sopenharmony_ci /// Writes a message, without a tag, to the stream. 260ffe3c632Sopenharmony_ci /// The data is length-prefixed. 261ffe3c632Sopenharmony_ci /// </summary> 262ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 263ffe3c632Sopenharmony_ci public void WriteMessage(IMessage value) 264ffe3c632Sopenharmony_ci { 265ffe3c632Sopenharmony_ci // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), 266ffe3c632Sopenharmony_ci // what we're doing here works fine, but could be more efficient. 267ffe3c632Sopenharmony_ci // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). 268ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 269ffe3c632Sopenharmony_ci WriteContext.Initialize(ref span, ref state, out WriteContext ctx); 270ffe3c632Sopenharmony_ci try 271ffe3c632Sopenharmony_ci { 272ffe3c632Sopenharmony_ci WritingPrimitivesMessages.WriteMessage(ref ctx, value); 273ffe3c632Sopenharmony_ci } 274ffe3c632Sopenharmony_ci finally 275ffe3c632Sopenharmony_ci { 276ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 277ffe3c632Sopenharmony_ci } 278ffe3c632Sopenharmony_ci } 279ffe3c632Sopenharmony_ci 280ffe3c632Sopenharmony_ci /// <summary> 281ffe3c632Sopenharmony_ci /// Writes a message, without a tag, to the stream. 282ffe3c632Sopenharmony_ci /// Only the message data is written, without a length-delimiter. 283ffe3c632Sopenharmony_ci /// </summary> 284ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 285ffe3c632Sopenharmony_ci public void WriteRawMessage(IMessage value) 286ffe3c632Sopenharmony_ci { 287ffe3c632Sopenharmony_ci // TODO(jtattermusch): if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), 288ffe3c632Sopenharmony_ci // what we're doing here works fine, but could be more efficient. 289ffe3c632Sopenharmony_ci // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). 290ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 291ffe3c632Sopenharmony_ci WriteContext.Initialize(ref span, ref state, out WriteContext ctx); 292ffe3c632Sopenharmony_ci try 293ffe3c632Sopenharmony_ci { 294ffe3c632Sopenharmony_ci WritingPrimitivesMessages.WriteRawMessage(ref ctx, value); 295ffe3c632Sopenharmony_ci } 296ffe3c632Sopenharmony_ci finally 297ffe3c632Sopenharmony_ci { 298ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 299ffe3c632Sopenharmony_ci } 300ffe3c632Sopenharmony_ci } 301ffe3c632Sopenharmony_ci 302ffe3c632Sopenharmony_ci /// <summary> 303ffe3c632Sopenharmony_ci /// Writes a group, without a tag, to the stream. 304ffe3c632Sopenharmony_ci /// </summary> 305ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 306ffe3c632Sopenharmony_ci public void WriteGroup(IMessage value) 307ffe3c632Sopenharmony_ci { 308ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 309ffe3c632Sopenharmony_ci WriteContext.Initialize(ref span, ref state, out WriteContext ctx); 310ffe3c632Sopenharmony_ci try 311ffe3c632Sopenharmony_ci { 312ffe3c632Sopenharmony_ci WritingPrimitivesMessages.WriteGroup(ref ctx, value); 313ffe3c632Sopenharmony_ci } 314ffe3c632Sopenharmony_ci finally 315ffe3c632Sopenharmony_ci { 316ffe3c632Sopenharmony_ci ctx.CopyStateTo(this); 317ffe3c632Sopenharmony_ci } 318ffe3c632Sopenharmony_ci } 319ffe3c632Sopenharmony_ci 320ffe3c632Sopenharmony_ci /// <summary> 321ffe3c632Sopenharmony_ci /// Write a byte string, without a tag, to the stream. 322ffe3c632Sopenharmony_ci /// The data is length-prefixed. 323ffe3c632Sopenharmony_ci /// </summary> 324ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 325ffe3c632Sopenharmony_ci public void WriteBytes(ByteString value) 326ffe3c632Sopenharmony_ci { 327ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 328ffe3c632Sopenharmony_ci WritingPrimitives.WriteBytes(ref span, ref state, value); 329ffe3c632Sopenharmony_ci } 330ffe3c632Sopenharmony_ci 331ffe3c632Sopenharmony_ci /// <summary> 332ffe3c632Sopenharmony_ci /// Writes a uint32 value, without a tag, to the stream. 333ffe3c632Sopenharmony_ci /// </summary> 334ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 335ffe3c632Sopenharmony_ci public void WriteUInt32(uint value) 336ffe3c632Sopenharmony_ci { 337ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 338ffe3c632Sopenharmony_ci WritingPrimitives.WriteUInt32(ref span, ref state, value); 339ffe3c632Sopenharmony_ci } 340ffe3c632Sopenharmony_ci 341ffe3c632Sopenharmony_ci /// <summary> 342ffe3c632Sopenharmony_ci /// Writes an enum value, without a tag, to the stream. 343ffe3c632Sopenharmony_ci /// </summary> 344ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 345ffe3c632Sopenharmony_ci public void WriteEnum(int value) 346ffe3c632Sopenharmony_ci { 347ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 348ffe3c632Sopenharmony_ci WritingPrimitives.WriteEnum(ref span, ref state, value); 349ffe3c632Sopenharmony_ci } 350ffe3c632Sopenharmony_ci 351ffe3c632Sopenharmony_ci /// <summary> 352ffe3c632Sopenharmony_ci /// Writes an sfixed32 value, without a tag, to the stream. 353ffe3c632Sopenharmony_ci /// </summary> 354ffe3c632Sopenharmony_ci /// <param name="value">The value to write.</param> 355ffe3c632Sopenharmony_ci public void WriteSFixed32(int value) 356ffe3c632Sopenharmony_ci { 357ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 358ffe3c632Sopenharmony_ci WritingPrimitives.WriteSFixed32(ref span, ref state, value); 359ffe3c632Sopenharmony_ci } 360ffe3c632Sopenharmony_ci 361ffe3c632Sopenharmony_ci /// <summary> 362ffe3c632Sopenharmony_ci /// Writes an sfixed64 value, without a tag, to the stream. 363ffe3c632Sopenharmony_ci /// </summary> 364ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 365ffe3c632Sopenharmony_ci public void WriteSFixed64(long value) 366ffe3c632Sopenharmony_ci { 367ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 368ffe3c632Sopenharmony_ci WritingPrimitives.WriteSFixed64(ref span, ref state, value); 369ffe3c632Sopenharmony_ci } 370ffe3c632Sopenharmony_ci 371ffe3c632Sopenharmony_ci /// <summary> 372ffe3c632Sopenharmony_ci /// Writes an sint32 value, without a tag, to the stream. 373ffe3c632Sopenharmony_ci /// </summary> 374ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 375ffe3c632Sopenharmony_ci public void WriteSInt32(int value) 376ffe3c632Sopenharmony_ci { 377ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 378ffe3c632Sopenharmony_ci WritingPrimitives.WriteSInt32(ref span, ref state, value); 379ffe3c632Sopenharmony_ci } 380ffe3c632Sopenharmony_ci 381ffe3c632Sopenharmony_ci /// <summary> 382ffe3c632Sopenharmony_ci /// Writes an sint64 value, without a tag, to the stream. 383ffe3c632Sopenharmony_ci /// </summary> 384ffe3c632Sopenharmony_ci /// <param name="value">The value to write</param> 385ffe3c632Sopenharmony_ci public void WriteSInt64(long value) 386ffe3c632Sopenharmony_ci { 387ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 388ffe3c632Sopenharmony_ci WritingPrimitives.WriteSInt64(ref span, ref state, value); 389ffe3c632Sopenharmony_ci } 390ffe3c632Sopenharmony_ci 391ffe3c632Sopenharmony_ci /// <summary> 392ffe3c632Sopenharmony_ci /// Writes a length (in bytes) for length-delimited data. 393ffe3c632Sopenharmony_ci /// </summary> 394ffe3c632Sopenharmony_ci /// <remarks> 395ffe3c632Sopenharmony_ci /// This method simply writes a rawint, but exists for clarity in calling code. 396ffe3c632Sopenharmony_ci /// </remarks> 397ffe3c632Sopenharmony_ci /// <param name="length">Length value, in bytes.</param> 398ffe3c632Sopenharmony_ci public void WriteLength(int length) 399ffe3c632Sopenharmony_ci { 400ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 401ffe3c632Sopenharmony_ci WritingPrimitives.WriteLength(ref span, ref state, length); 402ffe3c632Sopenharmony_ci } 403ffe3c632Sopenharmony_ci 404ffe3c632Sopenharmony_ci #endregion 405ffe3c632Sopenharmony_ci 406ffe3c632Sopenharmony_ci #region Raw tag writing 407ffe3c632Sopenharmony_ci /// <summary> 408ffe3c632Sopenharmony_ci /// Encodes and writes a tag. 409ffe3c632Sopenharmony_ci /// </summary> 410ffe3c632Sopenharmony_ci /// <param name="fieldNumber">The number of the field to write the tag for</param> 411ffe3c632Sopenharmony_ci /// <param name="type">The wire format type of the tag to write</param> 412ffe3c632Sopenharmony_ci public void WriteTag(int fieldNumber, WireFormat.WireType type) 413ffe3c632Sopenharmony_ci { 414ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 415ffe3c632Sopenharmony_ci WritingPrimitives.WriteTag(ref span, ref state, fieldNumber, type); 416ffe3c632Sopenharmony_ci } 417ffe3c632Sopenharmony_ci 418ffe3c632Sopenharmony_ci /// <summary> 419ffe3c632Sopenharmony_ci /// Writes an already-encoded tag. 420ffe3c632Sopenharmony_ci /// </summary> 421ffe3c632Sopenharmony_ci /// <param name="tag">The encoded tag</param> 422ffe3c632Sopenharmony_ci public void WriteTag(uint tag) 423ffe3c632Sopenharmony_ci { 424ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 425ffe3c632Sopenharmony_ci WritingPrimitives.WriteTag(ref span, ref state, tag); 426ffe3c632Sopenharmony_ci } 427ffe3c632Sopenharmony_ci 428ffe3c632Sopenharmony_ci /// <summary> 429ffe3c632Sopenharmony_ci /// Writes the given single-byte tag directly to the stream. 430ffe3c632Sopenharmony_ci /// </summary> 431ffe3c632Sopenharmony_ci /// <param name="b1">The encoded tag</param> 432ffe3c632Sopenharmony_ci public void WriteRawTag(byte b1) 433ffe3c632Sopenharmony_ci { 434ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 435ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawTag(ref span, ref state, b1); 436ffe3c632Sopenharmony_ci } 437ffe3c632Sopenharmony_ci 438ffe3c632Sopenharmony_ci /// <summary> 439ffe3c632Sopenharmony_ci /// Writes the given two-byte tag directly to the stream. 440ffe3c632Sopenharmony_ci /// </summary> 441ffe3c632Sopenharmony_ci /// <param name="b1">The first byte of the encoded tag</param> 442ffe3c632Sopenharmony_ci /// <param name="b2">The second byte of the encoded tag</param> 443ffe3c632Sopenharmony_ci public void WriteRawTag(byte b1, byte b2) 444ffe3c632Sopenharmony_ci { 445ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 446ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2); 447ffe3c632Sopenharmony_ci } 448ffe3c632Sopenharmony_ci 449ffe3c632Sopenharmony_ci /// <summary> 450ffe3c632Sopenharmony_ci /// Writes the given three-byte tag directly to the stream. 451ffe3c632Sopenharmony_ci /// </summary> 452ffe3c632Sopenharmony_ci /// <param name="b1">The first byte of the encoded tag</param> 453ffe3c632Sopenharmony_ci /// <param name="b2">The second byte of the encoded tag</param> 454ffe3c632Sopenharmony_ci /// <param name="b3">The third byte of the encoded tag</param> 455ffe3c632Sopenharmony_ci public void WriteRawTag(byte b1, byte b2, byte b3) 456ffe3c632Sopenharmony_ci { 457ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 458ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3); 459ffe3c632Sopenharmony_ci } 460ffe3c632Sopenharmony_ci 461ffe3c632Sopenharmony_ci /// <summary> 462ffe3c632Sopenharmony_ci /// Writes the given four-byte tag directly to the stream. 463ffe3c632Sopenharmony_ci /// </summary> 464ffe3c632Sopenharmony_ci /// <param name="b1">The first byte of the encoded tag</param> 465ffe3c632Sopenharmony_ci /// <param name="b2">The second byte of the encoded tag</param> 466ffe3c632Sopenharmony_ci /// <param name="b3">The third byte of the encoded tag</param> 467ffe3c632Sopenharmony_ci /// <param name="b4">The fourth byte of the encoded tag</param> 468ffe3c632Sopenharmony_ci public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) 469ffe3c632Sopenharmony_ci { 470ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 471ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4); 472ffe3c632Sopenharmony_ci } 473ffe3c632Sopenharmony_ci 474ffe3c632Sopenharmony_ci /// <summary> 475ffe3c632Sopenharmony_ci /// Writes the given five-byte tag directly to the stream. 476ffe3c632Sopenharmony_ci /// </summary> 477ffe3c632Sopenharmony_ci /// <param name="b1">The first byte of the encoded tag</param> 478ffe3c632Sopenharmony_ci /// <param name="b2">The second byte of the encoded tag</param> 479ffe3c632Sopenharmony_ci /// <param name="b3">The third byte of the encoded tag</param> 480ffe3c632Sopenharmony_ci /// <param name="b4">The fourth byte of the encoded tag</param> 481ffe3c632Sopenharmony_ci /// <param name="b5">The fifth byte of the encoded tag</param> 482ffe3c632Sopenharmony_ci public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) 483ffe3c632Sopenharmony_ci { 484ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 485ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4, b5); 486ffe3c632Sopenharmony_ci } 487ffe3c632Sopenharmony_ci #endregion 488ffe3c632Sopenharmony_ci 489ffe3c632Sopenharmony_ci #region Underlying writing primitives 490ffe3c632Sopenharmony_ci 491ffe3c632Sopenharmony_ci /// <summary> 492ffe3c632Sopenharmony_ci /// Writes a 32 bit value as a varint. The fast route is taken when 493ffe3c632Sopenharmony_ci /// there's enough buffer space left to whizz through without checking 494ffe3c632Sopenharmony_ci /// for each byte; otherwise, we resort to calling WriteRawByte each time. 495ffe3c632Sopenharmony_ci /// </summary> 496ffe3c632Sopenharmony_ci internal void WriteRawVarint32(uint value) 497ffe3c632Sopenharmony_ci { 498ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 499ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawVarint32(ref span, ref state, value); 500ffe3c632Sopenharmony_ci } 501ffe3c632Sopenharmony_ci 502ffe3c632Sopenharmony_ci internal void WriteRawVarint64(ulong value) 503ffe3c632Sopenharmony_ci { 504ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 505ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawVarint64(ref span, ref state, value); 506ffe3c632Sopenharmony_ci } 507ffe3c632Sopenharmony_ci 508ffe3c632Sopenharmony_ci internal void WriteRawLittleEndian32(uint value) 509ffe3c632Sopenharmony_ci { 510ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 511ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawLittleEndian32(ref span, ref state, value); 512ffe3c632Sopenharmony_ci } 513ffe3c632Sopenharmony_ci 514ffe3c632Sopenharmony_ci internal void WriteRawLittleEndian64(ulong value) 515ffe3c632Sopenharmony_ci { 516ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 517ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawLittleEndian64(ref span, ref state, value); 518ffe3c632Sopenharmony_ci } 519ffe3c632Sopenharmony_ci 520ffe3c632Sopenharmony_ci /// <summary> 521ffe3c632Sopenharmony_ci /// Writes out an array of bytes. 522ffe3c632Sopenharmony_ci /// </summary> 523ffe3c632Sopenharmony_ci internal void WriteRawBytes(byte[] value) 524ffe3c632Sopenharmony_ci { 525ffe3c632Sopenharmony_ci WriteRawBytes(value, 0, value.Length); 526ffe3c632Sopenharmony_ci } 527ffe3c632Sopenharmony_ci 528ffe3c632Sopenharmony_ci /// <summary> 529ffe3c632Sopenharmony_ci /// Writes out part of an array of bytes. 530ffe3c632Sopenharmony_ci /// </summary> 531ffe3c632Sopenharmony_ci internal void WriteRawBytes(byte[] value, int offset, int length) 532ffe3c632Sopenharmony_ci { 533ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 534ffe3c632Sopenharmony_ci WritingPrimitives.WriteRawBytes(ref span, ref state, value, offset, length); 535ffe3c632Sopenharmony_ci } 536ffe3c632Sopenharmony_ci 537ffe3c632Sopenharmony_ci #endregion 538ffe3c632Sopenharmony_ci 539ffe3c632Sopenharmony_ci /// <summary> 540ffe3c632Sopenharmony_ci /// Indicates that a CodedOutputStream wrapping a flat byte array 541ffe3c632Sopenharmony_ci /// ran out of space. 542ffe3c632Sopenharmony_ci /// </summary> 543ffe3c632Sopenharmony_ci public sealed class OutOfSpaceException : IOException 544ffe3c632Sopenharmony_ci { 545ffe3c632Sopenharmony_ci internal OutOfSpaceException() 546ffe3c632Sopenharmony_ci : base("CodedOutputStream was writing to a flat byte array and ran out of space.") 547ffe3c632Sopenharmony_ci { 548ffe3c632Sopenharmony_ci } 549ffe3c632Sopenharmony_ci } 550ffe3c632Sopenharmony_ci 551ffe3c632Sopenharmony_ci /// <summary> 552ffe3c632Sopenharmony_ci /// Flushes any buffered data and optionally closes the underlying stream, if any. 553ffe3c632Sopenharmony_ci /// </summary> 554ffe3c632Sopenharmony_ci /// <remarks> 555ffe3c632Sopenharmony_ci /// <para> 556ffe3c632Sopenharmony_ci /// By default, any underlying stream is closed by this method. To configure this behaviour, 557ffe3c632Sopenharmony_ci /// use a constructor overload with a <c>leaveOpen</c> parameter. If this instance does not 558ffe3c632Sopenharmony_ci /// have an underlying stream, this method does nothing. 559ffe3c632Sopenharmony_ci /// </para> 560ffe3c632Sopenharmony_ci /// <para> 561ffe3c632Sopenharmony_ci /// For the sake of efficiency, calling this method does not prevent future write calls - but 562ffe3c632Sopenharmony_ci /// if a later write ends up writing to a stream which has been disposed, that is likely to 563ffe3c632Sopenharmony_ci /// fail. It is recommend that you not call any other methods after this. 564ffe3c632Sopenharmony_ci /// </para> 565ffe3c632Sopenharmony_ci /// </remarks> 566ffe3c632Sopenharmony_ci public void Dispose() 567ffe3c632Sopenharmony_ci { 568ffe3c632Sopenharmony_ci Flush(); 569ffe3c632Sopenharmony_ci if (!leaveOpen) 570ffe3c632Sopenharmony_ci { 571ffe3c632Sopenharmony_ci output.Dispose(); 572ffe3c632Sopenharmony_ci } 573ffe3c632Sopenharmony_ci } 574ffe3c632Sopenharmony_ci 575ffe3c632Sopenharmony_ci /// <summary> 576ffe3c632Sopenharmony_ci /// Flushes any buffered data to the underlying stream (if there is one). 577ffe3c632Sopenharmony_ci /// </summary> 578ffe3c632Sopenharmony_ci public void Flush() 579ffe3c632Sopenharmony_ci { 580ffe3c632Sopenharmony_ci var span = new Span<byte>(buffer); 581ffe3c632Sopenharmony_ci WriteBufferHelper.Flush(ref span, ref state); 582ffe3c632Sopenharmony_ci } 583ffe3c632Sopenharmony_ci 584ffe3c632Sopenharmony_ci /// <summary> 585ffe3c632Sopenharmony_ci /// Verifies that SpaceLeft returns zero. It's common to create a byte array 586ffe3c632Sopenharmony_ci /// that is exactly big enough to hold a message, then write to it with 587ffe3c632Sopenharmony_ci /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that 588ffe3c632Sopenharmony_ci /// the message was actually as big as expected, which can help finding bugs. 589ffe3c632Sopenharmony_ci /// </summary> 590ffe3c632Sopenharmony_ci public void CheckNoSpaceLeft() 591ffe3c632Sopenharmony_ci { 592ffe3c632Sopenharmony_ci WriteBufferHelper.CheckNoSpaceLeft(ref state); 593ffe3c632Sopenharmony_ci } 594ffe3c632Sopenharmony_ci 595ffe3c632Sopenharmony_ci /// <summary> 596ffe3c632Sopenharmony_ci /// If writing to a flat array, returns the space left in the array. Otherwise, 597ffe3c632Sopenharmony_ci /// throws an InvalidOperationException. 598ffe3c632Sopenharmony_ci /// </summary> 599ffe3c632Sopenharmony_ci public int SpaceLeft => WriteBufferHelper.GetSpaceLeft(ref state); 600ffe3c632Sopenharmony_ci 601ffe3c632Sopenharmony_ci internal byte[] InternalBuffer => buffer; 602ffe3c632Sopenharmony_ci 603ffe3c632Sopenharmony_ci internal Stream InternalOutputStream => output; 604ffe3c632Sopenharmony_ci 605ffe3c632Sopenharmony_ci internal ref WriterInternalState InternalState => ref state; 606ffe3c632Sopenharmony_ci } 607ffe3c632Sopenharmony_ci} 608