|  | #region Copyright notice and license | 
|  | // Protocol Buffers - Google's data interchange format | 
|  | // Copyright 2008 Google Inc.  All rights reserved. | 
|  | // | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file or at | 
|  | // https://developers.google.com/open-source/licenses/bsd | 
|  | #endregion | 
|  |  | 
|  | using System; | 
|  | using System.IO; | 
|  | using System.Security; | 
|  |  | 
|  | namespace Google.Protobuf | 
|  | { | 
|  | /// <summary> | 
|  | /// Encodes and writes protocol message fields. | 
|  | /// </summary> | 
|  | /// <remarks> | 
|  | /// <para> | 
|  | /// This class is generally used by generated code to write appropriate | 
|  | /// primitives to the stream. It effectively encapsulates the lowest | 
|  | /// levels of protocol buffer format. Unlike some other implementations, | 
|  | /// this does not include combined "write tag and value" methods. Generated | 
|  | /// code knows the exact byte representations of the tags they're going to write, | 
|  | /// so there's no need to re-encode them each time. Manually-written code calling | 
|  | /// this class should just call one of the <c>WriteTag</c> overloads before each value. | 
|  | /// </para> | 
|  | /// <para> | 
|  | /// Repeated fields and map fields are not handled by this class; use <c>RepeatedField<T></c> | 
|  | /// and <c>MapField<TKey, TValue></c> to serialize such fields. | 
|  | /// </para> | 
|  | /// </remarks> | 
|  | [SecuritySafeCritical] | 
|  | public sealed partial class CodedOutputStream : IDisposable | 
|  | { | 
|  | /// <summary> | 
|  | /// The buffer size used by CreateInstance(Stream). | 
|  | /// </summary> | 
|  | public static readonly int DefaultBufferSize = 4096; | 
|  |  | 
|  | private readonly bool leaveOpen; | 
|  | private readonly byte[] buffer; | 
|  | private WriterInternalState state; | 
|  |  | 
|  | private readonly Stream output; | 
|  |  | 
|  | #region Construction | 
|  | /// <summary> | 
|  | /// Creates a new CodedOutputStream that writes directly to the given | 
|  | /// byte array. If more bytes are written than fit in the array, | 
|  | /// OutOfSpaceException will be thrown. | 
|  | /// </summary> | 
|  | public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length) | 
|  | { | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Creates a new CodedOutputStream that writes directly to the given | 
|  | /// byte array slice. If more bytes are written than fit in the array, | 
|  | /// OutOfSpaceException will be thrown. | 
|  | /// </summary> | 
|  | private CodedOutputStream(byte[] buffer, int offset, int length) | 
|  | { | 
|  | this.output = null; | 
|  | this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer)); | 
|  | this.state.position = offset; | 
|  | this.state.limit = offset + length; | 
|  | WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); | 
|  | leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference | 
|  | } | 
|  |  | 
|  | private CodedOutputStream(Stream output, byte[] buffer, bool leaveOpen) | 
|  | { | 
|  | this.output = ProtoPreconditions.CheckNotNull(output, nameof(output)); | 
|  | this.buffer = buffer; | 
|  | this.state.position = 0; | 
|  | this.state.limit = buffer.Length; | 
|  | WriteBufferHelper.Initialize(this, out this.state.writeBufferHelper); | 
|  | this.leaveOpen = leaveOpen; | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Creates a new <see cref="CodedOutputStream" /> which write to the given stream, and disposes of that | 
|  | /// stream when the returned <c>CodedOutputStream</c> is disposed. | 
|  | /// </summary> | 
|  | /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param> | 
|  | public CodedOutputStream(Stream output) : this(output, DefaultBufferSize, false) | 
|  | { | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Creates a new CodedOutputStream which write to the given stream and uses | 
|  | /// the specified buffer size. | 
|  | /// </summary> | 
|  | /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param> | 
|  | /// <param name="bufferSize">The size of buffer to use internally.</param> | 
|  | public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize], false) | 
|  | { | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Creates a new CodedOutputStream which write to the given stream. | 
|  | /// </summary> | 
|  | /// <param name="output">The stream to write to.</param> | 
|  | /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed; | 
|  | /// if <c>false</c>, the provided stream is disposed as well.</param> | 
|  | public CodedOutputStream(Stream output, bool leaveOpen) : this(output, DefaultBufferSize, leaveOpen) | 
|  | { | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Creates a new CodedOutputStream which write to the given stream and uses | 
|  | /// the specified buffer size. | 
|  | /// </summary> | 
|  | /// <param name="output">The stream to write to.</param> | 
|  | /// <param name="bufferSize">The size of buffer to use internally.</param> | 
|  | /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed; | 
|  | /// if <c>false</c>, the provided stream is disposed as well.</param> | 
|  | public CodedOutputStream(Stream output, int bufferSize, bool leaveOpen) : this(output, new byte[bufferSize], leaveOpen) | 
|  | { | 
|  | } | 
|  | #endregion | 
|  |  | 
|  | /// <summary> | 
|  | /// Returns the current position in the stream, or the position in the output buffer | 
|  | /// </summary> | 
|  | public long Position | 
|  | { | 
|  | get | 
|  | { | 
|  | if (output != null) | 
|  | { | 
|  | return output.Position + state.position; | 
|  | } | 
|  | return state.position; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Configures whether or not serialization is deterministic. | 
|  | /// </summary> | 
|  | /// <remarks> | 
|  | /// Deterministic serialization guarantees that for a given binary, equal messages (defined by the | 
|  | /// equals methods in protos) will always be serialized to the same bytes. This implies: | 
|  | /// <list type="bullet"> | 
|  | /// <item><description>Repeated serialization of a message will return the same bytes.</description></item> | 
|  | /// <item><description>Different processes of the same binary (which may be executing on different machines) | 
|  | /// will serialize equal messages to the same bytes.</description></item> | 
|  | /// </list> | 
|  | /// Note the deterministic serialization is NOT canonical across languages; it is also unstable | 
|  | /// across different builds with schema changes due to unknown fields. Users who need canonical | 
|  | /// serialization, e.g. persistent storage in a canonical form, fingerprinting, etc, should define | 
|  | /// their own canonicalization specification and implement the serializer using reflection APIs | 
|  | /// rather than relying on this API. | 
|  | /// Once set, the serializer will: (Note this is an implementation detail and may subject to | 
|  | /// change in the future) | 
|  | /// <list type="bullet"> | 
|  | /// <item><description>Sort map entries by keys in lexicographical order or numerical order. Note: For string | 
|  | /// keys, the order is based on comparing the UTF-16 code unit value of each character in the strings. | 
|  | /// The order may be different from the deterministic serialization in other languages where | 
|  | /// maps are sorted on the lexicographical order of the UTF8 encoded keys.</description></item> | 
|  | /// </list> | 
|  | /// </remarks> | 
|  | public bool Deterministic { get; set; } | 
|  |  | 
|  | #region Writing of values (not including tags) | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a double field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteDouble(double value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteDouble(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a float field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteFloat(float value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteFloat(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a uint64 field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteUInt64(ulong value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteUInt64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an int64 field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteInt64(long value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteInt64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an int32 field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteInt32(int value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteInt32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a fixed64 field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteFixed64(ulong value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteFixed64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a fixed32 field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteFixed32(uint value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteFixed32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a bool field value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteBool(bool value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteBool(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a string field value, without a tag, to the stream. | 
|  | /// The data is length-prefixed. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteString(string value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteString(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a message, without a tag, to the stream. | 
|  | /// The data is length-prefixed. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteMessage(IMessage value) | 
|  | { | 
|  | // TODO: if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), | 
|  | // what we're doing here works fine, but could be more efficient. | 
|  | // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). | 
|  | var span = new Span<byte>(buffer); | 
|  | WriteContext.Initialize(ref span, ref state, out WriteContext ctx); | 
|  | try | 
|  | { | 
|  | WritingPrimitivesMessages.WriteMessage(ref ctx, value); | 
|  | } | 
|  | finally | 
|  | { | 
|  | ctx.CopyStateTo(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a message, without a tag, to the stream. | 
|  | /// Only the message data is written, without a length-delimiter. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteRawMessage(IMessage value) | 
|  | { | 
|  | // TODO: if the message doesn't implement IBufferMessage (and thus does not provide the InternalWriteTo method), | 
|  | // what we're doing here works fine, but could be more efficient. | 
|  | // For now, this inefficiency is fine, considering this is only a backward-compatibility scenario (and regenerating the code fixes it). | 
|  | var span = new Span<byte>(buffer); | 
|  | WriteContext.Initialize(ref span, ref state, out WriteContext ctx); | 
|  | try | 
|  | { | 
|  | WritingPrimitivesMessages.WriteRawMessage(ref ctx, value); | 
|  | } | 
|  | finally | 
|  | { | 
|  | ctx.CopyStateTo(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a group, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteGroup(IMessage value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WriteContext.Initialize(ref span, ref state, out WriteContext ctx); | 
|  | try | 
|  | { | 
|  | WritingPrimitivesMessages.WriteGroup(ref ctx, value); | 
|  | } | 
|  | finally | 
|  | { | 
|  | ctx.CopyStateTo(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Write a byte string, without a tag, to the stream. | 
|  | /// The data is length-prefixed. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteBytes(ByteString value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteBytes(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a uint32 value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteUInt32(uint value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteUInt32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an enum value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteEnum(int value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteEnum(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an sfixed32 value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write.</param> | 
|  | public void WriteSFixed32(int value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteSFixed32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an sfixed64 value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteSFixed64(long value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteSFixed64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an sint32 value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteSInt32(int value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteSInt32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an sint64 value, without a tag, to the stream. | 
|  | /// </summary> | 
|  | /// <param name="value">The value to write</param> | 
|  | public void WriteSInt64(long value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteSInt64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a length (in bytes) for length-delimited data. | 
|  | /// </summary> | 
|  | /// <remarks> | 
|  | /// This method simply writes a rawint, but exists for clarity in calling code. | 
|  | /// </remarks> | 
|  | /// <param name="length">Length value, in bytes.</param> | 
|  | public void WriteLength(int length) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteLength(ref span, ref state, length); | 
|  | } | 
|  |  | 
|  | #endregion | 
|  |  | 
|  | #region Raw tag writing | 
|  | /// <summary> | 
|  | /// Encodes and writes a tag. | 
|  | /// </summary> | 
|  | /// <param name="fieldNumber">The number of the field to write the tag for</param> | 
|  | /// <param name="type">The wire format type of the tag to write</param> | 
|  | public void WriteTag(int fieldNumber, WireFormat.WireType type) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteTag(ref span, ref state, fieldNumber, type); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes an already-encoded tag. | 
|  | /// </summary> | 
|  | /// <param name="tag">The encoded tag</param> | 
|  | public void WriteTag(uint tag) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteTag(ref span, ref state, tag); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes the given single-byte tag directly to the stream. | 
|  | /// </summary> | 
|  | /// <param name="b1">The encoded tag</param> | 
|  | public void WriteRawTag(byte b1) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawTag(ref span, ref state, b1); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes the given two-byte tag directly to the stream. | 
|  | /// </summary> | 
|  | /// <param name="b1">The first byte of the encoded tag</param> | 
|  | /// <param name="b2">The second byte of the encoded tag</param> | 
|  | public void WriteRawTag(byte b1, byte b2) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes the given three-byte tag directly to the stream. | 
|  | /// </summary> | 
|  | /// <param name="b1">The first byte of the encoded tag</param> | 
|  | /// <param name="b2">The second byte of the encoded tag</param> | 
|  | /// <param name="b3">The third byte of the encoded tag</param> | 
|  | public void WriteRawTag(byte b1, byte b2, byte b3) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes the given four-byte tag directly to the stream. | 
|  | /// </summary> | 
|  | /// <param name="b1">The first byte of the encoded tag</param> | 
|  | /// <param name="b2">The second byte of the encoded tag</param> | 
|  | /// <param name="b3">The third byte of the encoded tag</param> | 
|  | /// <param name="b4">The fourth byte of the encoded tag</param> | 
|  | public void WriteRawTag(byte b1, byte b2, byte b3, byte b4) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes the given five-byte tag directly to the stream. | 
|  | /// </summary> | 
|  | /// <param name="b1">The first byte of the encoded tag</param> | 
|  | /// <param name="b2">The second byte of the encoded tag</param> | 
|  | /// <param name="b3">The third byte of the encoded tag</param> | 
|  | /// <param name="b4">The fourth byte of the encoded tag</param> | 
|  | /// <param name="b5">The fifth byte of the encoded tag</param> | 
|  | public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawTag(ref span, ref state, b1, b2, b3, b4, b5); | 
|  | } | 
|  | #endregion | 
|  |  | 
|  | #region Underlying writing primitives | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes a 32 bit value as a varint. The fast route is taken when | 
|  | /// there's enough buffer space left to whizz through without checking | 
|  | /// for each byte; otherwise, we resort to calling WriteRawByte each time. | 
|  | /// </summary> | 
|  | internal void WriteRawVarint32(uint value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawVarint32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | internal void WriteRawVarint64(ulong value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawVarint64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | internal void WriteRawLittleEndian32(uint value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawLittleEndian32(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | internal void WriteRawLittleEndian64(ulong value) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawLittleEndian64(ref span, ref state, value); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes out an array of bytes. | 
|  | /// </summary> | 
|  | internal void WriteRawBytes(byte[] value) | 
|  | { | 
|  | WriteRawBytes(value, 0, value.Length); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Writes out part of an array of bytes. | 
|  | /// </summary> | 
|  | internal void WriteRawBytes(byte[] value, int offset, int length) | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WritingPrimitives.WriteRawBytes(ref span, ref state, value, offset, length); | 
|  | } | 
|  |  | 
|  | #endregion | 
|  |  | 
|  | /// <summary> | 
|  | /// Indicates that a CodedOutputStream wrapping a flat byte array | 
|  | /// ran out of space. | 
|  | /// </summary> | 
|  | public sealed class OutOfSpaceException : IOException | 
|  | { | 
|  | internal OutOfSpaceException() | 
|  | : base("CodedOutputStream was writing to a flat byte array and ran out of space.") | 
|  | { | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Flushes any buffered data and optionally closes the underlying stream, if any. | 
|  | /// </summary> | 
|  | /// <remarks> | 
|  | /// <para> | 
|  | /// By default, any underlying stream is closed by this method. To configure this behaviour, | 
|  | /// use a constructor overload with a <c>leaveOpen</c> parameter. If this instance does not | 
|  | /// have an underlying stream, this method does nothing. | 
|  | /// </para> | 
|  | /// <para> | 
|  | /// For the sake of efficiency, calling this method does not prevent future write calls - but | 
|  | /// if a later write ends up writing to a stream which has been disposed, that is likely to | 
|  | /// fail. It is recommend that you not call any other methods after this. | 
|  | /// </para> | 
|  | /// </remarks> | 
|  | public void Dispose() | 
|  | { | 
|  | Flush(); | 
|  | if (!leaveOpen) | 
|  | { | 
|  | output.Dispose(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Flushes any buffered data to the underlying stream (if there is one). | 
|  | /// </summary> | 
|  | public void Flush() | 
|  | { | 
|  | var span = new Span<byte>(buffer); | 
|  | WriteBufferHelper.Flush(ref span, ref state); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// Verifies that SpaceLeft returns zero. It's common to create a byte array | 
|  | /// that is exactly big enough to hold a message, then write to it with | 
|  | /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that | 
|  | /// the message was actually as big as expected, which can help finding bugs. | 
|  | /// </summary> | 
|  | public void CheckNoSpaceLeft() | 
|  | { | 
|  | WriteBufferHelper.CheckNoSpaceLeft(ref state); | 
|  | } | 
|  |  | 
|  | /// <summary> | 
|  | /// If writing to a flat array, returns the space left in the array. Otherwise, | 
|  | /// throws an InvalidOperationException. | 
|  | /// </summary> | 
|  | public int SpaceLeft => WriteBufferHelper.GetSpaceLeft(ref state); | 
|  |  | 
|  | internal byte[] InternalBuffer => buffer; | 
|  |  | 
|  | internal Stream InternalOutputStream => output; | 
|  |  | 
|  | internal ref WriterInternalState InternalState => ref state; | 
|  | } | 
|  | } |