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 System;
34ffe3c632Sopenharmony_ciusing System.Collections;
35ffe3c632Sopenharmony_ciusing System.Collections.Generic;
36ffe3c632Sopenharmony_ciusing System.IO;
37ffe3c632Sopenharmony_ciusing System.Security;
38ffe3c632Sopenharmony_ciusing System.Text;
39ffe3c632Sopenharmony_ci#if !NET35
40ffe3c632Sopenharmony_ciusing System.Threading;
41ffe3c632Sopenharmony_ciusing System.Threading.Tasks;
42ffe3c632Sopenharmony_ci#endif
43ffe3c632Sopenharmony_ci#if NET35
44ffe3c632Sopenharmony_ciusing Google.Protobuf.Compatibility;
45ffe3c632Sopenharmony_ci#endif
46ffe3c632Sopenharmony_ci
47ffe3c632Sopenharmony_cinamespace Google.Protobuf
48ffe3c632Sopenharmony_ci{
49ffe3c632Sopenharmony_ci    /// <summary>
50ffe3c632Sopenharmony_ci    /// Immutable array of bytes.
51ffe3c632Sopenharmony_ci    /// </summary>
52ffe3c632Sopenharmony_ci    public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
53ffe3c632Sopenharmony_ci    {
54ffe3c632Sopenharmony_ci        private static readonly ByteString empty = new ByteString(new byte[0]);
55ffe3c632Sopenharmony_ci
56ffe3c632Sopenharmony_ci        private readonly byte[] bytes;
57ffe3c632Sopenharmony_ci
58ffe3c632Sopenharmony_ci        /// <summary>
59ffe3c632Sopenharmony_ci        /// Unsafe operations that can cause IO Failure and/or other catastrophic side-effects.
60ffe3c632Sopenharmony_ci        /// </summary>
61ffe3c632Sopenharmony_ci        internal static class Unsafe
62ffe3c632Sopenharmony_ci        {
63ffe3c632Sopenharmony_ci            /// <summary>
64ffe3c632Sopenharmony_ci            /// Constructs a new ByteString from the given byte array. The array is
65ffe3c632Sopenharmony_ci            /// *not* copied, and must not be modified after this constructor is called.
66ffe3c632Sopenharmony_ci            /// </summary>
67ffe3c632Sopenharmony_ci            internal static ByteString FromBytes(byte[] bytes)
68ffe3c632Sopenharmony_ci            {
69ffe3c632Sopenharmony_ci                return new ByteString(bytes);
70ffe3c632Sopenharmony_ci            }
71ffe3c632Sopenharmony_ci        }
72ffe3c632Sopenharmony_ci
73ffe3c632Sopenharmony_ci        /// <summary>
74ffe3c632Sopenharmony_ci        /// Internal use only.  Ensure that the provided array is not mutated and belongs to this instance.
75ffe3c632Sopenharmony_ci        /// </summary>
76ffe3c632Sopenharmony_ci        internal static ByteString AttachBytes(byte[] bytes)
77ffe3c632Sopenharmony_ci        {
78ffe3c632Sopenharmony_ci            return new ByteString(bytes);
79ffe3c632Sopenharmony_ci        }
80ffe3c632Sopenharmony_ci
81ffe3c632Sopenharmony_ci        /// <summary>
82ffe3c632Sopenharmony_ci        /// Constructs a new ByteString from the given byte array. The array is
83ffe3c632Sopenharmony_ci        /// *not* copied, and must not be modified after this constructor is called.
84ffe3c632Sopenharmony_ci        /// </summary>
85ffe3c632Sopenharmony_ci        private ByteString(byte[] bytes)
86ffe3c632Sopenharmony_ci        {
87ffe3c632Sopenharmony_ci            this.bytes = bytes;
88ffe3c632Sopenharmony_ci        }
89ffe3c632Sopenharmony_ci
90ffe3c632Sopenharmony_ci        /// <summary>
91ffe3c632Sopenharmony_ci        /// Returns an empty ByteString.
92ffe3c632Sopenharmony_ci        /// </summary>
93ffe3c632Sopenharmony_ci        public static ByteString Empty
94ffe3c632Sopenharmony_ci        {
95ffe3c632Sopenharmony_ci            get { return empty; }
96ffe3c632Sopenharmony_ci        }
97ffe3c632Sopenharmony_ci
98ffe3c632Sopenharmony_ci        /// <summary>
99ffe3c632Sopenharmony_ci        /// Returns the length of this ByteString in bytes.
100ffe3c632Sopenharmony_ci        /// </summary>
101ffe3c632Sopenharmony_ci        public int Length
102ffe3c632Sopenharmony_ci        {
103ffe3c632Sopenharmony_ci            get { return bytes.Length; }
104ffe3c632Sopenharmony_ci        }
105ffe3c632Sopenharmony_ci
106ffe3c632Sopenharmony_ci        /// <summary>
107ffe3c632Sopenharmony_ci        /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
108ffe3c632Sopenharmony_ci        /// </summary>
109ffe3c632Sopenharmony_ci        public bool IsEmpty
110ffe3c632Sopenharmony_ci        {
111ffe3c632Sopenharmony_ci            get { return Length == 0; }
112ffe3c632Sopenharmony_ci        }
113ffe3c632Sopenharmony_ci
114ffe3c632Sopenharmony_ci#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
115ffe3c632Sopenharmony_ci        /// <summary>
116ffe3c632Sopenharmony_ci        /// Provides read-only access to the data of this <see cref="ByteString"/>.
117ffe3c632Sopenharmony_ci        /// No data is copied so this is the most efficient way of accessing.
118ffe3c632Sopenharmony_ci        /// </summary>
119ffe3c632Sopenharmony_ci        public ReadOnlySpan<byte> Span
120ffe3c632Sopenharmony_ci        {
121ffe3c632Sopenharmony_ci            [SecuritySafeCritical]
122ffe3c632Sopenharmony_ci            get
123ffe3c632Sopenharmony_ci            {
124ffe3c632Sopenharmony_ci                return new ReadOnlySpan<byte>(bytes);
125ffe3c632Sopenharmony_ci            }
126ffe3c632Sopenharmony_ci        }
127ffe3c632Sopenharmony_ci
128ffe3c632Sopenharmony_ci        /// <summary>
129ffe3c632Sopenharmony_ci        /// Provides read-only access to the data of this <see cref="ByteString"/>.
130ffe3c632Sopenharmony_ci        /// No data is copied so this is the most efficient way of accessing.
131ffe3c632Sopenharmony_ci        /// </summary>
132ffe3c632Sopenharmony_ci        public ReadOnlyMemory<byte> Memory
133ffe3c632Sopenharmony_ci        {
134ffe3c632Sopenharmony_ci            [SecuritySafeCritical]
135ffe3c632Sopenharmony_ci            get
136ffe3c632Sopenharmony_ci            {
137ffe3c632Sopenharmony_ci                return new ReadOnlyMemory<byte>(bytes);
138ffe3c632Sopenharmony_ci            }
139ffe3c632Sopenharmony_ci        }
140ffe3c632Sopenharmony_ci#endif
141ffe3c632Sopenharmony_ci
142ffe3c632Sopenharmony_ci        /// <summary>
143ffe3c632Sopenharmony_ci        /// Converts this <see cref="ByteString"/> into a byte array.
144ffe3c632Sopenharmony_ci        /// </summary>
145ffe3c632Sopenharmony_ci        /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
146ffe3c632Sopenharmony_ci        /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
147ffe3c632Sopenharmony_ci        public byte[] ToByteArray()
148ffe3c632Sopenharmony_ci        {
149ffe3c632Sopenharmony_ci            return (byte[]) bytes.Clone();
150ffe3c632Sopenharmony_ci        }
151ffe3c632Sopenharmony_ci
152ffe3c632Sopenharmony_ci        /// <summary>
153ffe3c632Sopenharmony_ci        /// Converts this <see cref="ByteString"/> into a standard base64 representation.
154ffe3c632Sopenharmony_ci        /// </summary>
155ffe3c632Sopenharmony_ci        /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
156ffe3c632Sopenharmony_ci        public string ToBase64()
157ffe3c632Sopenharmony_ci        {
158ffe3c632Sopenharmony_ci            return Convert.ToBase64String(bytes);
159ffe3c632Sopenharmony_ci        }
160ffe3c632Sopenharmony_ci
161ffe3c632Sopenharmony_ci        /// <summary>
162ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
163ffe3c632Sopenharmony_ci        /// </summary>
164ffe3c632Sopenharmony_ci        public static ByteString FromBase64(string bytes)
165ffe3c632Sopenharmony_ci        {
166ffe3c632Sopenharmony_ci            // By handling the empty string explicitly, we not only optimize but we fix a
167ffe3c632Sopenharmony_ci            // problem on CF 2.0. See issue 61 for details.
168ffe3c632Sopenharmony_ci            return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
169ffe3c632Sopenharmony_ci        }
170ffe3c632Sopenharmony_ci
171ffe3c632Sopenharmony_ci        /// <summary>
172ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously.
173ffe3c632Sopenharmony_ci        /// </summary>
174ffe3c632Sopenharmony_ci        /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
175ffe3c632Sopenharmony_ci        /// at the start of the call.</remarks>
176ffe3c632Sopenharmony_ci        /// <param name="stream">The stream to copy into a ByteString.</param>
177ffe3c632Sopenharmony_ci        /// <returns>A ByteString with content read from the given stream.</returns>
178ffe3c632Sopenharmony_ci        public static ByteString FromStream(Stream stream)
179ffe3c632Sopenharmony_ci        {
180ffe3c632Sopenharmony_ci            ProtoPreconditions.CheckNotNull(stream, nameof(stream));
181ffe3c632Sopenharmony_ci            int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
182ffe3c632Sopenharmony_ci            var memoryStream = new MemoryStream(capacity);
183ffe3c632Sopenharmony_ci            stream.CopyTo(memoryStream);
184ffe3c632Sopenharmony_ci#if NETSTANDARD1_1 || NETSTANDARD2_0
185ffe3c632Sopenharmony_ci            byte[] bytes = memoryStream.ToArray();
186ffe3c632Sopenharmony_ci#else
187ffe3c632Sopenharmony_ci            // Avoid an extra copy if we can.
188ffe3c632Sopenharmony_ci            byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
189ffe3c632Sopenharmony_ci#endif
190ffe3c632Sopenharmony_ci            return AttachBytes(bytes);
191ffe3c632Sopenharmony_ci        }
192ffe3c632Sopenharmony_ci
193ffe3c632Sopenharmony_ci#if !NET35
194ffe3c632Sopenharmony_ci        /// <summary>
195ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
196ffe3c632Sopenharmony_ci        /// </summary>
197ffe3c632Sopenharmony_ci        /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
198ffe3c632Sopenharmony_ci        /// at the start of the call.</remarks>
199ffe3c632Sopenharmony_ci        /// <param name="stream">The stream to copy into a ByteString.</param>
200ffe3c632Sopenharmony_ci        /// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
201ffe3c632Sopenharmony_ci        /// <returns>A ByteString with content read from the given stream.</returns>
202ffe3c632Sopenharmony_ci        public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
203ffe3c632Sopenharmony_ci        {
204ffe3c632Sopenharmony_ci            ProtoPreconditions.CheckNotNull(stream, nameof(stream));
205ffe3c632Sopenharmony_ci            int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
206ffe3c632Sopenharmony_ci            var memoryStream = new MemoryStream(capacity);
207ffe3c632Sopenharmony_ci            // We have to specify the buffer size here, as there's no overload accepting the cancellation token
208ffe3c632Sopenharmony_ci            // alone. But it's documented to use 81920 by default if not specified.
209ffe3c632Sopenharmony_ci            await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
210ffe3c632Sopenharmony_ci#if NETSTANDARD1_1 || NETSTANDARD2_0
211ffe3c632Sopenharmony_ci            byte[] bytes = memoryStream.ToArray();
212ffe3c632Sopenharmony_ci#else
213ffe3c632Sopenharmony_ci            // Avoid an extra copy if we can.
214ffe3c632Sopenharmony_ci            byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
215ffe3c632Sopenharmony_ci#endif
216ffe3c632Sopenharmony_ci            return AttachBytes(bytes);
217ffe3c632Sopenharmony_ci        }
218ffe3c632Sopenharmony_ci#endif
219ffe3c632Sopenharmony_ci
220ffe3c632Sopenharmony_ci        /// <summary>
221ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString" /> from the given array. The contents
222ffe3c632Sopenharmony_ci        /// are copied, so further modifications to the array will not
223ffe3c632Sopenharmony_ci        /// be reflected in the returned ByteString.
224ffe3c632Sopenharmony_ci        /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
225ffe3c632Sopenharmony_ci        /// which is primarily useful for testing.
226ffe3c632Sopenharmony_ci        /// </summary>
227ffe3c632Sopenharmony_ci        public static ByteString CopyFrom(params byte[] bytes)
228ffe3c632Sopenharmony_ci        {
229ffe3c632Sopenharmony_ci            return new ByteString((byte[]) bytes.Clone());
230ffe3c632Sopenharmony_ci        }
231ffe3c632Sopenharmony_ci
232ffe3c632Sopenharmony_ci        /// <summary>
233ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
234ffe3c632Sopenharmony_ci        /// </summary>
235ffe3c632Sopenharmony_ci        public static ByteString CopyFrom(byte[] bytes, int offset, int count)
236ffe3c632Sopenharmony_ci        {
237ffe3c632Sopenharmony_ci            byte[] portion = new byte[count];
238ffe3c632Sopenharmony_ci            ByteArray.Copy(bytes, offset, portion, 0, count);
239ffe3c632Sopenharmony_ci            return new ByteString(portion);
240ffe3c632Sopenharmony_ci        }
241ffe3c632Sopenharmony_ci
242ffe3c632Sopenharmony_ci#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
243ffe3c632Sopenharmony_ci        /// <summary>
244ffe3c632Sopenharmony_ci        /// Constructs a <see cref="ByteString" /> from a read only span. The contents
245ffe3c632Sopenharmony_ci        /// are copied, so further modifications to the span will not
246ffe3c632Sopenharmony_ci        /// be reflected in the returned <see cref="ByteString" />.
247ffe3c632Sopenharmony_ci        /// </summary>
248ffe3c632Sopenharmony_ci        public static ByteString CopyFrom(ReadOnlySpan<byte> bytes)
249ffe3c632Sopenharmony_ci        {
250ffe3c632Sopenharmony_ci            return new ByteString(bytes.ToArray());
251ffe3c632Sopenharmony_ci        }
252ffe3c632Sopenharmony_ci#endif
253ffe3c632Sopenharmony_ci
254ffe3c632Sopenharmony_ci        /// <summary>
255ffe3c632Sopenharmony_ci        /// Creates a new <see cref="ByteString" /> by encoding the specified text with
256ffe3c632Sopenharmony_ci        /// the given encoding.
257ffe3c632Sopenharmony_ci        /// </summary>
258ffe3c632Sopenharmony_ci        public static ByteString CopyFrom(string text, Encoding encoding)
259ffe3c632Sopenharmony_ci        {
260ffe3c632Sopenharmony_ci            return new ByteString(encoding.GetBytes(text));
261ffe3c632Sopenharmony_ci        }
262ffe3c632Sopenharmony_ci
263ffe3c632Sopenharmony_ci        /// <summary>
264ffe3c632Sopenharmony_ci        /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
265ffe3c632Sopenharmony_ci        /// </summary>
266ffe3c632Sopenharmony_ci        public static ByteString CopyFromUtf8(string text)
267ffe3c632Sopenharmony_ci        {
268ffe3c632Sopenharmony_ci            return CopyFrom(text, Encoding.UTF8);
269ffe3c632Sopenharmony_ci        }
270ffe3c632Sopenharmony_ci
271ffe3c632Sopenharmony_ci        /// <summary>
272ffe3c632Sopenharmony_ci        /// Retuns the byte at the given index.
273ffe3c632Sopenharmony_ci        /// </summary>
274ffe3c632Sopenharmony_ci        public byte this[int index]
275ffe3c632Sopenharmony_ci        {
276ffe3c632Sopenharmony_ci            get { return bytes[index]; }
277ffe3c632Sopenharmony_ci        }
278ffe3c632Sopenharmony_ci
279ffe3c632Sopenharmony_ci        /// <summary>
280ffe3c632Sopenharmony_ci        /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
281ffe3c632Sopenharmony_ci        /// </summary>
282ffe3c632Sopenharmony_ci        /// <remarks>
283ffe3c632Sopenharmony_ci        /// This method should only be used to convert binary data which was the result of encoding
284ffe3c632Sopenharmony_ci        /// text with the given encoding.
285ffe3c632Sopenharmony_ci        /// </remarks>
286ffe3c632Sopenharmony_ci        /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
287ffe3c632Sopenharmony_ci        /// <returns>The result of decoding the binary data with the given decoding.</returns>
288ffe3c632Sopenharmony_ci        public string ToString(Encoding encoding)
289ffe3c632Sopenharmony_ci        {
290ffe3c632Sopenharmony_ci            return encoding.GetString(bytes, 0, bytes.Length);
291ffe3c632Sopenharmony_ci        }
292ffe3c632Sopenharmony_ci
293ffe3c632Sopenharmony_ci        /// <summary>
294ffe3c632Sopenharmony_ci        /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
295ffe3c632Sopenharmony_ci        /// </summary>
296ffe3c632Sopenharmony_ci        /// <remarks>
297ffe3c632Sopenharmony_ci        /// This method should only be used to convert binary data which was the result of encoding
298ffe3c632Sopenharmony_ci        /// text with UTF-8.
299ffe3c632Sopenharmony_ci        /// </remarks>
300ffe3c632Sopenharmony_ci        /// <returns>The result of decoding the binary data with the given decoding.</returns>
301ffe3c632Sopenharmony_ci        public string ToStringUtf8()
302ffe3c632Sopenharmony_ci        {
303ffe3c632Sopenharmony_ci            return ToString(Encoding.UTF8);
304ffe3c632Sopenharmony_ci        }
305ffe3c632Sopenharmony_ci
306ffe3c632Sopenharmony_ci        /// <summary>
307ffe3c632Sopenharmony_ci        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
308ffe3c632Sopenharmony_ci        /// </summary>
309ffe3c632Sopenharmony_ci        /// <returns>An iterator over the bytes in this object.</returns>
310ffe3c632Sopenharmony_ci        public IEnumerator<byte> GetEnumerator()
311ffe3c632Sopenharmony_ci        {
312ffe3c632Sopenharmony_ci            return ((IEnumerable<byte>) bytes).GetEnumerator();
313ffe3c632Sopenharmony_ci        }
314ffe3c632Sopenharmony_ci
315ffe3c632Sopenharmony_ci        /// <summary>
316ffe3c632Sopenharmony_ci        /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
317ffe3c632Sopenharmony_ci        /// </summary>
318ffe3c632Sopenharmony_ci        /// <returns>An iterator over the bytes in this object.</returns>
319ffe3c632Sopenharmony_ci        IEnumerator IEnumerable.GetEnumerator()
320ffe3c632Sopenharmony_ci        {
321ffe3c632Sopenharmony_ci            return GetEnumerator();
322ffe3c632Sopenharmony_ci        }
323ffe3c632Sopenharmony_ci
324ffe3c632Sopenharmony_ci        /// <summary>
325ffe3c632Sopenharmony_ci        /// Creates a CodedInputStream from this ByteString's data.
326ffe3c632Sopenharmony_ci        /// </summary>
327ffe3c632Sopenharmony_ci        public CodedInputStream CreateCodedInput()
328ffe3c632Sopenharmony_ci        {
329ffe3c632Sopenharmony_ci            // We trust CodedInputStream not to reveal the provided byte array or modify it
330ffe3c632Sopenharmony_ci            return new CodedInputStream(bytes);
331ffe3c632Sopenharmony_ci        }
332ffe3c632Sopenharmony_ci
333ffe3c632Sopenharmony_ci        /// <summary>
334ffe3c632Sopenharmony_ci        /// Compares two byte strings for equality.
335ffe3c632Sopenharmony_ci        /// </summary>
336ffe3c632Sopenharmony_ci        /// <param name="lhs">The first byte string to compare.</param>
337ffe3c632Sopenharmony_ci        /// <param name="rhs">The second byte string to compare.</param>
338ffe3c632Sopenharmony_ci        /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
339ffe3c632Sopenharmony_ci        public static bool operator ==(ByteString lhs, ByteString rhs)
340ffe3c632Sopenharmony_ci        {
341ffe3c632Sopenharmony_ci            if (ReferenceEquals(lhs, rhs))
342ffe3c632Sopenharmony_ci            {
343ffe3c632Sopenharmony_ci                return true;
344ffe3c632Sopenharmony_ci            }
345ffe3c632Sopenharmony_ci            if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
346ffe3c632Sopenharmony_ci            {
347ffe3c632Sopenharmony_ci                return false;
348ffe3c632Sopenharmony_ci            }
349ffe3c632Sopenharmony_ci            if (lhs.bytes.Length != rhs.bytes.Length)
350ffe3c632Sopenharmony_ci            {
351ffe3c632Sopenharmony_ci                return false;
352ffe3c632Sopenharmony_ci            }
353ffe3c632Sopenharmony_ci            for (int i = 0; i < lhs.Length; i++)
354ffe3c632Sopenharmony_ci            {
355ffe3c632Sopenharmony_ci                if (rhs.bytes[i] != lhs.bytes[i])
356ffe3c632Sopenharmony_ci                {
357ffe3c632Sopenharmony_ci                    return false;
358ffe3c632Sopenharmony_ci                }
359ffe3c632Sopenharmony_ci            }
360ffe3c632Sopenharmony_ci            return true;
361ffe3c632Sopenharmony_ci        }
362ffe3c632Sopenharmony_ci
363ffe3c632Sopenharmony_ci        /// <summary>
364ffe3c632Sopenharmony_ci        /// Compares two byte strings for inequality.
365ffe3c632Sopenharmony_ci        /// </summary>
366ffe3c632Sopenharmony_ci        /// <param name="lhs">The first byte string to compare.</param>
367ffe3c632Sopenharmony_ci        /// <param name="rhs">The second byte string to compare.</param>
368ffe3c632Sopenharmony_ci        /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
369ffe3c632Sopenharmony_ci        public static bool operator !=(ByteString lhs, ByteString rhs)
370ffe3c632Sopenharmony_ci        {
371ffe3c632Sopenharmony_ci            return !(lhs == rhs);
372ffe3c632Sopenharmony_ci        }
373ffe3c632Sopenharmony_ci
374ffe3c632Sopenharmony_ci        /// <summary>
375ffe3c632Sopenharmony_ci        /// Compares this byte string with another object.
376ffe3c632Sopenharmony_ci        /// </summary>
377ffe3c632Sopenharmony_ci        /// <param name="obj">The object to compare this with.</param>
378ffe3c632Sopenharmony_ci        /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
379ffe3c632Sopenharmony_ci        public override bool Equals(object obj)
380ffe3c632Sopenharmony_ci        {
381ffe3c632Sopenharmony_ci            return this == (obj as ByteString);
382ffe3c632Sopenharmony_ci        }
383ffe3c632Sopenharmony_ci
384ffe3c632Sopenharmony_ci        /// <summary>
385ffe3c632Sopenharmony_ci        /// Returns a hash code for this object. Two equal byte strings
386ffe3c632Sopenharmony_ci        /// will return the same hash code.
387ffe3c632Sopenharmony_ci        /// </summary>
388ffe3c632Sopenharmony_ci        /// <returns>A hash code for this object.</returns>
389ffe3c632Sopenharmony_ci        public override int GetHashCode()
390ffe3c632Sopenharmony_ci        {
391ffe3c632Sopenharmony_ci            int ret = 23;
392ffe3c632Sopenharmony_ci            foreach (byte b in bytes)
393ffe3c632Sopenharmony_ci            {
394ffe3c632Sopenharmony_ci                ret = (ret * 31) + b;
395ffe3c632Sopenharmony_ci            }
396ffe3c632Sopenharmony_ci            return ret;
397ffe3c632Sopenharmony_ci        }
398ffe3c632Sopenharmony_ci
399ffe3c632Sopenharmony_ci        /// <summary>
400ffe3c632Sopenharmony_ci        /// Compares this byte string with another.
401ffe3c632Sopenharmony_ci        /// </summary>
402ffe3c632Sopenharmony_ci        /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
403ffe3c632Sopenharmony_ci        /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
404ffe3c632Sopenharmony_ci        public bool Equals(ByteString other)
405ffe3c632Sopenharmony_ci        {
406ffe3c632Sopenharmony_ci            return this == other;
407ffe3c632Sopenharmony_ci        }
408ffe3c632Sopenharmony_ci
409ffe3c632Sopenharmony_ci        /// <summary>
410ffe3c632Sopenharmony_ci        /// Used internally by CodedOutputStream to avoid creating a copy for the write
411ffe3c632Sopenharmony_ci        /// </summary>
412ffe3c632Sopenharmony_ci        internal void WriteRawBytesTo(CodedOutputStream outputStream)
413ffe3c632Sopenharmony_ci        {
414ffe3c632Sopenharmony_ci            outputStream.WriteRawBytes(bytes, 0, bytes.Length);
415ffe3c632Sopenharmony_ci        }
416ffe3c632Sopenharmony_ci
417ffe3c632Sopenharmony_ci        /// <summary>
418ffe3c632Sopenharmony_ci        /// Copies the entire byte array to the destination array provided at the offset specified.
419ffe3c632Sopenharmony_ci        /// </summary>
420ffe3c632Sopenharmony_ci        public void CopyTo(byte[] array, int position)
421ffe3c632Sopenharmony_ci        {
422ffe3c632Sopenharmony_ci            ByteArray.Copy(bytes, 0, array, position, bytes.Length);
423ffe3c632Sopenharmony_ci        }
424ffe3c632Sopenharmony_ci
425ffe3c632Sopenharmony_ci        /// <summary>
426ffe3c632Sopenharmony_ci        /// Writes the entire byte array to the provided stream
427ffe3c632Sopenharmony_ci        /// </summary>
428ffe3c632Sopenharmony_ci        public void WriteTo(Stream outputStream)
429ffe3c632Sopenharmony_ci        {
430ffe3c632Sopenharmony_ci            outputStream.Write(bytes, 0, bytes.Length);
431ffe3c632Sopenharmony_ci        }
432ffe3c632Sopenharmony_ci    }
433ffe3c632Sopenharmony_ci}