xref: /aosp_15_r20/external/protobuf/csharp/src/Google.Protobuf/ByteString.cs (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker #region Copyright notice and license
2*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format
3*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc.  All rights reserved.
4*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/
5*1b3f573fSAndroid Build Coastguard Worker //
6*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
7*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
8*1b3f573fSAndroid Build Coastguard Worker // met:
9*1b3f573fSAndroid Build Coastguard Worker //
10*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions of source code must retain the above copyright
11*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
12*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions in binary form must reproduce the above
13*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
14*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
15*1b3f573fSAndroid Build Coastguard Worker // distribution.
16*1b3f573fSAndroid Build Coastguard Worker //     * Neither the name of Google Inc. nor the names of its
17*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
18*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission.
19*1b3f573fSAndroid Build Coastguard Worker //
20*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*1b3f573fSAndroid Build Coastguard Worker #endregion
32*1b3f573fSAndroid Build Coastguard Worker 
33*1b3f573fSAndroid Build Coastguard Worker using System;
34*1b3f573fSAndroid Build Coastguard Worker using System.Collections;
35*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic;
36*1b3f573fSAndroid Build Coastguard Worker using System.IO;
37*1b3f573fSAndroid Build Coastguard Worker using System.Runtime.InteropServices;
38*1b3f573fSAndroid Build Coastguard Worker using System.Security;
39*1b3f573fSAndroid Build Coastguard Worker using System.Text;
40*1b3f573fSAndroid Build Coastguard Worker #if !NET35
41*1b3f573fSAndroid Build Coastguard Worker using System.Threading;
42*1b3f573fSAndroid Build Coastguard Worker using System.Threading.Tasks;
43*1b3f573fSAndroid Build Coastguard Worker #endif
44*1b3f573fSAndroid Build Coastguard Worker #if NET35
45*1b3f573fSAndroid Build Coastguard Worker using Google.Protobuf.Compatibility;
46*1b3f573fSAndroid Build Coastguard Worker #endif
47*1b3f573fSAndroid Build Coastguard Worker 
48*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf
49*1b3f573fSAndroid Build Coastguard Worker {
50*1b3f573fSAndroid Build Coastguard Worker     /// <summary>
51*1b3f573fSAndroid Build Coastguard Worker     /// Immutable array of bytes.
52*1b3f573fSAndroid Build Coastguard Worker     /// </summary>
53*1b3f573fSAndroid Build Coastguard Worker     [SecuritySafeCritical]
54*1b3f573fSAndroid Build Coastguard Worker     public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
55*1b3f573fSAndroid Build Coastguard Worker     {
56*1b3f573fSAndroid Build Coastguard Worker         private static readonly ByteString empty = new ByteString(new byte[0]);
57*1b3f573fSAndroid Build Coastguard Worker 
58*1b3f573fSAndroid Build Coastguard Worker         private readonly ReadOnlyMemory<byte> bytes;
59*1b3f573fSAndroid Build Coastguard Worker 
60*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
61*1b3f573fSAndroid Build Coastguard Worker         /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
62*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
AttachBytes(ReadOnlyMemory<byte> bytes)63*1b3f573fSAndroid Build Coastguard Worker         internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes)
64*1b3f573fSAndroid Build Coastguard Worker         {
65*1b3f573fSAndroid Build Coastguard Worker             return new ByteString(bytes);
66*1b3f573fSAndroid Build Coastguard Worker         }
67*1b3f573fSAndroid Build Coastguard Worker 
68*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
69*1b3f573fSAndroid Build Coastguard Worker         /// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance.
70*1b3f573fSAndroid Build Coastguard Worker         /// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical
71*1b3f573fSAndroid Build Coastguard Worker         /// in .NET Framework.
72*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
AttachBytes(byte[] bytes)73*1b3f573fSAndroid Build Coastguard Worker         internal static ByteString AttachBytes(byte[] bytes)
74*1b3f573fSAndroid Build Coastguard Worker         {
75*1b3f573fSAndroid Build Coastguard Worker             return AttachBytes(bytes.AsMemory());
76*1b3f573fSAndroid Build Coastguard Worker         }
77*1b3f573fSAndroid Build Coastguard Worker 
78*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
79*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a new ByteString from the given memory. The memory is
80*1b3f573fSAndroid Build Coastguard Worker         /// *not* copied, and must not be modified after this constructor is called.
81*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
ByteString(ReadOnlyMemory<byte> bytes)82*1b3f573fSAndroid Build Coastguard Worker         private ByteString(ReadOnlyMemory<byte> bytes)
83*1b3f573fSAndroid Build Coastguard Worker         {
84*1b3f573fSAndroid Build Coastguard Worker             this.bytes = bytes;
85*1b3f573fSAndroid Build Coastguard Worker         }
86*1b3f573fSAndroid Build Coastguard Worker 
87*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
88*1b3f573fSAndroid Build Coastguard Worker         /// Returns an empty ByteString.
89*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
90*1b3f573fSAndroid Build Coastguard Worker         public static ByteString Empty
91*1b3f573fSAndroid Build Coastguard Worker         {
92*1b3f573fSAndroid Build Coastguard Worker             get { return empty; }
93*1b3f573fSAndroid Build Coastguard Worker         }
94*1b3f573fSAndroid Build Coastguard Worker 
95*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
96*1b3f573fSAndroid Build Coastguard Worker         /// Returns the length of this ByteString in bytes.
97*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
98*1b3f573fSAndroid Build Coastguard Worker         public int Length
99*1b3f573fSAndroid Build Coastguard Worker         {
100*1b3f573fSAndroid Build Coastguard Worker             get { return bytes.Length; }
101*1b3f573fSAndroid Build Coastguard Worker         }
102*1b3f573fSAndroid Build Coastguard Worker 
103*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
104*1b3f573fSAndroid Build Coastguard Worker         /// Returns <c>true</c> if this byte string is empty, <c>false</c> otherwise.
105*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
106*1b3f573fSAndroid Build Coastguard Worker         public bool IsEmpty
107*1b3f573fSAndroid Build Coastguard Worker         {
108*1b3f573fSAndroid Build Coastguard Worker             get { return Length == 0; }
109*1b3f573fSAndroid Build Coastguard Worker         }
110*1b3f573fSAndroid Build Coastguard Worker 
111*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
112*1b3f573fSAndroid Build Coastguard Worker         /// Provides read-only access to the data of this <see cref="ByteString"/>.
113*1b3f573fSAndroid Build Coastguard Worker         /// No data is copied so this is the most efficient way of accessing.
114*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
115*1b3f573fSAndroid Build Coastguard Worker         public ReadOnlySpan<byte> Span
116*1b3f573fSAndroid Build Coastguard Worker         {
117*1b3f573fSAndroid Build Coastguard Worker             get { return bytes.Span; }
118*1b3f573fSAndroid Build Coastguard Worker         }
119*1b3f573fSAndroid Build Coastguard Worker 
120*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
121*1b3f573fSAndroid Build Coastguard Worker         /// Provides read-only access to the data of this <see cref="ByteString"/>.
122*1b3f573fSAndroid Build Coastguard Worker         /// No data is copied so this is the most efficient way of accessing.
123*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
124*1b3f573fSAndroid Build Coastguard Worker         public ReadOnlyMemory<byte> Memory
125*1b3f573fSAndroid Build Coastguard Worker         {
126*1b3f573fSAndroid Build Coastguard Worker             get { return bytes; }
127*1b3f573fSAndroid Build Coastguard Worker         }
128*1b3f573fSAndroid Build Coastguard Worker 
129*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
130*1b3f573fSAndroid Build Coastguard Worker         /// Converts this <see cref="ByteString"/> into a byte array.
131*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
132*1b3f573fSAndroid Build Coastguard Worker         /// <remarks>The data is copied - changes to the returned array will not be reflected in this <c>ByteString</c>.</remarks>
133*1b3f573fSAndroid Build Coastguard Worker         /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
ToByteArray()134*1b3f573fSAndroid Build Coastguard Worker         public byte[] ToByteArray()
135*1b3f573fSAndroid Build Coastguard Worker         {
136*1b3f573fSAndroid Build Coastguard Worker             return bytes.ToArray();
137*1b3f573fSAndroid Build Coastguard Worker         }
138*1b3f573fSAndroid Build Coastguard Worker 
139*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
140*1b3f573fSAndroid Build Coastguard Worker         /// Converts this <see cref="ByteString"/> into a standard base64 representation.
141*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
142*1b3f573fSAndroid Build Coastguard Worker         /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
ToBase64()143*1b3f573fSAndroid Build Coastguard Worker         public string ToBase64()
144*1b3f573fSAndroid Build Coastguard Worker         {
145*1b3f573fSAndroid Build Coastguard Worker             if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
146*1b3f573fSAndroid Build Coastguard Worker             {
147*1b3f573fSAndroid Build Coastguard Worker                 // Fast path. ByteString was created with an array, so pass the underlying array.
148*1b3f573fSAndroid Build Coastguard Worker                 return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);
149*1b3f573fSAndroid Build Coastguard Worker             }
150*1b3f573fSAndroid Build Coastguard Worker             else
151*1b3f573fSAndroid Build Coastguard Worker             {
152*1b3f573fSAndroid Build Coastguard Worker                 // Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.
153*1b3f573fSAndroid Build Coastguard Worker                 return Convert.ToBase64String(bytes.ToArray());
154*1b3f573fSAndroid Build Coastguard Worker             }
155*1b3f573fSAndroid Build Coastguard Worker         }
156*1b3f573fSAndroid Build Coastguard Worker 
157*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
158*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString" /> from the Base64 Encoded String.
159*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
FromBase64(string bytes)160*1b3f573fSAndroid Build Coastguard Worker         public static ByteString FromBase64(string bytes)
161*1b3f573fSAndroid Build Coastguard Worker         {
162*1b3f573fSAndroid Build Coastguard Worker             // By handling the empty string explicitly, we not only optimize but we fix a
163*1b3f573fSAndroid Build Coastguard Worker             // problem on CF 2.0. See issue 61 for details.
164*1b3f573fSAndroid Build Coastguard Worker             return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));
165*1b3f573fSAndroid Build Coastguard Worker         }
166*1b3f573fSAndroid Build Coastguard Worker 
167*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
168*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString"/> from data in the given stream, synchronously.
169*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
170*1b3f573fSAndroid Build Coastguard Worker         /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
171*1b3f573fSAndroid Build Coastguard Worker         /// at the start of the call.</remarks>
172*1b3f573fSAndroid Build Coastguard Worker         /// <param name="stream">The stream to copy into a ByteString.</param>
173*1b3f573fSAndroid Build Coastguard Worker         /// <returns>A ByteString with content read from the given stream.</returns>
FromStream(Stream stream)174*1b3f573fSAndroid Build Coastguard Worker         public static ByteString FromStream(Stream stream)
175*1b3f573fSAndroid Build Coastguard Worker         {
176*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(stream, nameof(stream));
177*1b3f573fSAndroid Build Coastguard Worker             int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
178*1b3f573fSAndroid Build Coastguard Worker             var memoryStream = new MemoryStream(capacity);
179*1b3f573fSAndroid Build Coastguard Worker             stream.CopyTo(memoryStream);
180*1b3f573fSAndroid Build Coastguard Worker #if NETSTANDARD1_1 || NETSTANDARD2_0
181*1b3f573fSAndroid Build Coastguard Worker             byte[] bytes = memoryStream.ToArray();
182*1b3f573fSAndroid Build Coastguard Worker #else
183*1b3f573fSAndroid Build Coastguard Worker             // Avoid an extra copy if we can.
184*1b3f573fSAndroid Build Coastguard Worker             byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
185*1b3f573fSAndroid Build Coastguard Worker #endif
186*1b3f573fSAndroid Build Coastguard Worker             return AttachBytes(bytes);
187*1b3f573fSAndroid Build Coastguard Worker         }
188*1b3f573fSAndroid Build Coastguard Worker 
189*1b3f573fSAndroid Build Coastguard Worker #if !NET35
190*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
191*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
192*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
193*1b3f573fSAndroid Build Coastguard Worker         /// <remarks>If successful, <paramref name="stream"/> will be read completely, from the position
194*1b3f573fSAndroid Build Coastguard Worker         /// at the start of the call.</remarks>
195*1b3f573fSAndroid Build Coastguard Worker         /// <param name="stream">The stream to copy into a ByteString.</param>
196*1b3f573fSAndroid Build Coastguard Worker         /// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
197*1b3f573fSAndroid Build Coastguard Worker         /// <returns>A ByteString with content read from the given stream.</returns>
FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))198*1b3f573fSAndroid Build Coastguard Worker         public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
199*1b3f573fSAndroid Build Coastguard Worker         {
200*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(stream, nameof(stream));
201*1b3f573fSAndroid Build Coastguard Worker             return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
202*1b3f573fSAndroid Build Coastguard Worker         }
203*1b3f573fSAndroid Build Coastguard Worker #endif
204*1b3f573fSAndroid Build Coastguard Worker 
205*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
206*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString" /> from the given array. The contents
207*1b3f573fSAndroid Build Coastguard Worker         /// are copied, so further modifications to the array will not
208*1b3f573fSAndroid Build Coastguard Worker         /// be reflected in the returned ByteString.
209*1b3f573fSAndroid Build Coastguard Worker         /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form
210*1b3f573fSAndroid Build Coastguard Worker         /// which is primarily useful for testing.
211*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyFrom(params byte[] bytes)212*1b3f573fSAndroid Build Coastguard Worker         public static ByteString CopyFrom(params byte[] bytes)
213*1b3f573fSAndroid Build Coastguard Worker         {
214*1b3f573fSAndroid Build Coastguard Worker             return new ByteString((byte[]) bytes.Clone());
215*1b3f573fSAndroid Build Coastguard Worker         }
216*1b3f573fSAndroid Build Coastguard Worker 
217*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
218*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString" /> from a portion of a byte array.
219*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyFrom(byte[] bytes, int offset, int count)220*1b3f573fSAndroid Build Coastguard Worker         public static ByteString CopyFrom(byte[] bytes, int offset, int count)
221*1b3f573fSAndroid Build Coastguard Worker         {
222*1b3f573fSAndroid Build Coastguard Worker             byte[] portion = new byte[count];
223*1b3f573fSAndroid Build Coastguard Worker             ByteArray.Copy(bytes, offset, portion, 0, count);
224*1b3f573fSAndroid Build Coastguard Worker             return new ByteString(portion);
225*1b3f573fSAndroid Build Coastguard Worker         }
226*1b3f573fSAndroid Build Coastguard Worker 
227*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
228*1b3f573fSAndroid Build Coastguard Worker         /// Constructs a <see cref="ByteString" /> from a read only span. The contents
229*1b3f573fSAndroid Build Coastguard Worker         /// are copied, so further modifications to the span will not
230*1b3f573fSAndroid Build Coastguard Worker         /// be reflected in the returned <see cref="ByteString" />.
231*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyFrom(ReadOnlySpan<byte> bytes)232*1b3f573fSAndroid Build Coastguard Worker         public static ByteString CopyFrom(ReadOnlySpan<byte> bytes)
233*1b3f573fSAndroid Build Coastguard Worker         {
234*1b3f573fSAndroid Build Coastguard Worker             return new ByteString(bytes.ToArray());
235*1b3f573fSAndroid Build Coastguard Worker         }
236*1b3f573fSAndroid Build Coastguard Worker 
237*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
238*1b3f573fSAndroid Build Coastguard Worker         /// Creates a new <see cref="ByteString" /> by encoding the specified text with
239*1b3f573fSAndroid Build Coastguard Worker         /// the given encoding.
240*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyFrom(string text, Encoding encoding)241*1b3f573fSAndroid Build Coastguard Worker         public static ByteString CopyFrom(string text, Encoding encoding)
242*1b3f573fSAndroid Build Coastguard Worker         {
243*1b3f573fSAndroid Build Coastguard Worker             return new ByteString(encoding.GetBytes(text));
244*1b3f573fSAndroid Build Coastguard Worker         }
245*1b3f573fSAndroid Build Coastguard Worker 
246*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
247*1b3f573fSAndroid Build Coastguard Worker         /// Creates a new <see cref="ByteString" /> by encoding the specified text in UTF-8.
248*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyFromUtf8(string text)249*1b3f573fSAndroid Build Coastguard Worker         public static ByteString CopyFromUtf8(string text)
250*1b3f573fSAndroid Build Coastguard Worker         {
251*1b3f573fSAndroid Build Coastguard Worker             return CopyFrom(text, Encoding.UTF8);
252*1b3f573fSAndroid Build Coastguard Worker         }
253*1b3f573fSAndroid Build Coastguard Worker 
254*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
255*1b3f573fSAndroid Build Coastguard Worker         /// Returns the byte at the given index.
256*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
257*1b3f573fSAndroid Build Coastguard Worker         public byte this[int index]
258*1b3f573fSAndroid Build Coastguard Worker         {
259*1b3f573fSAndroid Build Coastguard Worker             get { return bytes.Span[index]; }
260*1b3f573fSAndroid Build Coastguard Worker         }
261*1b3f573fSAndroid Build Coastguard Worker 
262*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
263*1b3f573fSAndroid Build Coastguard Worker         /// Converts this <see cref="ByteString"/> into a string by applying the given encoding.
264*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
265*1b3f573fSAndroid Build Coastguard Worker         /// <remarks>
266*1b3f573fSAndroid Build Coastguard Worker         /// This method should only be used to convert binary data which was the result of encoding
267*1b3f573fSAndroid Build Coastguard Worker         /// text with the given encoding.
268*1b3f573fSAndroid Build Coastguard Worker         /// </remarks>
269*1b3f573fSAndroid Build Coastguard Worker         /// <param name="encoding">The encoding to use to decode the binary data into text.</param>
270*1b3f573fSAndroid Build Coastguard Worker         /// <returns>The result of decoding the binary data with the given decoding.</returns>
ToString(Encoding encoding)271*1b3f573fSAndroid Build Coastguard Worker         public string ToString(Encoding encoding)
272*1b3f573fSAndroid Build Coastguard Worker         {
273*1b3f573fSAndroid Build Coastguard Worker             if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
274*1b3f573fSAndroid Build Coastguard Worker             {
275*1b3f573fSAndroid Build Coastguard Worker                 // Fast path. ByteString was created with an array.
276*1b3f573fSAndroid Build Coastguard Worker                 return encoding.GetString(segment.Array, segment.Offset, segment.Count);
277*1b3f573fSAndroid Build Coastguard Worker             }
278*1b3f573fSAndroid Build Coastguard Worker             else
279*1b3f573fSAndroid Build Coastguard Worker             {
280*1b3f573fSAndroid Build Coastguard Worker                 // Slow path. BytesString is not an array. Convert memory and pass result to GetString.
281*1b3f573fSAndroid Build Coastguard Worker                 // TODO: Consider using GetString overload that takes a pointer.
282*1b3f573fSAndroid Build Coastguard Worker                 byte[] array = bytes.ToArray();
283*1b3f573fSAndroid Build Coastguard Worker                 return encoding.GetString(array, 0, array.Length);
284*1b3f573fSAndroid Build Coastguard Worker             }
285*1b3f573fSAndroid Build Coastguard Worker         }
286*1b3f573fSAndroid Build Coastguard Worker 
287*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
288*1b3f573fSAndroid Build Coastguard Worker         /// Converts this <see cref="ByteString"/> into a string by applying the UTF-8 encoding.
289*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
290*1b3f573fSAndroid Build Coastguard Worker         /// <remarks>
291*1b3f573fSAndroid Build Coastguard Worker         /// This method should only be used to convert binary data which was the result of encoding
292*1b3f573fSAndroid Build Coastguard Worker         /// text with UTF-8.
293*1b3f573fSAndroid Build Coastguard Worker         /// </remarks>
294*1b3f573fSAndroid Build Coastguard Worker         /// <returns>The result of decoding the binary data with the given decoding.</returns>
ToStringUtf8()295*1b3f573fSAndroid Build Coastguard Worker         public string ToStringUtf8()
296*1b3f573fSAndroid Build Coastguard Worker         {
297*1b3f573fSAndroid Build Coastguard Worker             return ToString(Encoding.UTF8);
298*1b3f573fSAndroid Build Coastguard Worker         }
299*1b3f573fSAndroid Build Coastguard Worker 
300*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
301*1b3f573fSAndroid Build Coastguard Worker         /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
302*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
303*1b3f573fSAndroid Build Coastguard Worker         /// <returns>An iterator over the bytes in this object.</returns>
304*1b3f573fSAndroid Build Coastguard Worker         [SecuritySafeCritical]
GetEnumerator()305*1b3f573fSAndroid Build Coastguard Worker         public IEnumerator<byte> GetEnumerator()
306*1b3f573fSAndroid Build Coastguard Worker         {
307*1b3f573fSAndroid Build Coastguard Worker             return MemoryMarshal.ToEnumerable(bytes).GetEnumerator();
308*1b3f573fSAndroid Build Coastguard Worker         }
309*1b3f573fSAndroid Build Coastguard Worker 
310*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
311*1b3f573fSAndroid Build Coastguard Worker         /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
312*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
313*1b3f573fSAndroid Build Coastguard Worker         /// <returns>An iterator over the bytes in this object.</returns>
IEnumerable.GetEnumerator()314*1b3f573fSAndroid Build Coastguard Worker         IEnumerator IEnumerable.GetEnumerator()
315*1b3f573fSAndroid Build Coastguard Worker         {
316*1b3f573fSAndroid Build Coastguard Worker             return GetEnumerator();
317*1b3f573fSAndroid Build Coastguard Worker         }
318*1b3f573fSAndroid Build Coastguard Worker 
319*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
320*1b3f573fSAndroid Build Coastguard Worker         /// Creates a CodedInputStream from this ByteString's data.
321*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CreateCodedInput()322*1b3f573fSAndroid Build Coastguard Worker         public CodedInputStream CreateCodedInput()
323*1b3f573fSAndroid Build Coastguard Worker         {
324*1b3f573fSAndroid Build Coastguard Worker             // We trust CodedInputStream not to reveal the provided byte array or modify it
325*1b3f573fSAndroid Build Coastguard Worker             if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length)
326*1b3f573fSAndroid Build Coastguard Worker             {
327*1b3f573fSAndroid Build Coastguard Worker                 // Fast path. ByteString was created with a complete array.
328*1b3f573fSAndroid Build Coastguard Worker                 return new CodedInputStream(segment.Array, segment.Offset, segment.Count);
329*1b3f573fSAndroid Build Coastguard Worker             }
330*1b3f573fSAndroid Build Coastguard Worker             else
331*1b3f573fSAndroid Build Coastguard Worker             {
332*1b3f573fSAndroid Build Coastguard Worker                 // Slow path. BytesString is not an array, or is a slice of an array.
333*1b3f573fSAndroid Build Coastguard Worker                 // Convert memory and pass result to WriteRawBytes.
334*1b3f573fSAndroid Build Coastguard Worker                 return new CodedInputStream(bytes.ToArray());
335*1b3f573fSAndroid Build Coastguard Worker             }
336*1b3f573fSAndroid Build Coastguard Worker         }
337*1b3f573fSAndroid Build Coastguard Worker 
338*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
339*1b3f573fSAndroid Build Coastguard Worker         /// Compares two byte strings for equality.
340*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
341*1b3f573fSAndroid Build Coastguard Worker         /// <param name="lhs">The first byte string to compare.</param>
342*1b3f573fSAndroid Build Coastguard Worker         /// <param name="rhs">The second byte string to compare.</param>
343*1b3f573fSAndroid Build Coastguard Worker         /// <returns><c>true</c> if the byte strings are equal; false otherwise.</returns>
operator ==(ByteString lhs, ByteString rhs)344*1b3f573fSAndroid Build Coastguard Worker         public static bool operator ==(ByteString lhs, ByteString rhs)
345*1b3f573fSAndroid Build Coastguard Worker         {
346*1b3f573fSAndroid Build Coastguard Worker             if (ReferenceEquals(lhs, rhs))
347*1b3f573fSAndroid Build Coastguard Worker             {
348*1b3f573fSAndroid Build Coastguard Worker                 return true;
349*1b3f573fSAndroid Build Coastguard Worker             }
350*1b3f573fSAndroid Build Coastguard Worker             if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
351*1b3f573fSAndroid Build Coastguard Worker             {
352*1b3f573fSAndroid Build Coastguard Worker                 return false;
353*1b3f573fSAndroid Build Coastguard Worker             }
354*1b3f573fSAndroid Build Coastguard Worker 
355*1b3f573fSAndroid Build Coastguard Worker             return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span);
356*1b3f573fSAndroid Build Coastguard Worker         }
357*1b3f573fSAndroid Build Coastguard Worker 
358*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
359*1b3f573fSAndroid Build Coastguard Worker         /// Compares two byte strings for inequality.
360*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
361*1b3f573fSAndroid Build Coastguard Worker         /// <param name="lhs">The first byte string to compare.</param>
362*1b3f573fSAndroid Build Coastguard Worker         /// <param name="rhs">The second byte string to compare.</param>
363*1b3f573fSAndroid Build Coastguard Worker         /// <returns><c>false</c> if the byte strings are equal; true otherwise.</returns>
operator !=(ByteString lhs, ByteString rhs)364*1b3f573fSAndroid Build Coastguard Worker         public static bool operator !=(ByteString lhs, ByteString rhs)
365*1b3f573fSAndroid Build Coastguard Worker         {
366*1b3f573fSAndroid Build Coastguard Worker             return !(lhs == rhs);
367*1b3f573fSAndroid Build Coastguard Worker         }
368*1b3f573fSAndroid Build Coastguard Worker 
369*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
370*1b3f573fSAndroid Build Coastguard Worker         /// Compares this byte string with another object.
371*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
372*1b3f573fSAndroid Build Coastguard Worker         /// <param name="obj">The object to compare this with.</param>
373*1b3f573fSAndroid Build Coastguard Worker         /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
374*1b3f573fSAndroid Build Coastguard Worker         [SecuritySafeCritical]
Equals(object obj)375*1b3f573fSAndroid Build Coastguard Worker         public override bool Equals(object obj)
376*1b3f573fSAndroid Build Coastguard Worker         {
377*1b3f573fSAndroid Build Coastguard Worker             return this == (obj as ByteString);
378*1b3f573fSAndroid Build Coastguard Worker         }
379*1b3f573fSAndroid Build Coastguard Worker 
380*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
381*1b3f573fSAndroid Build Coastguard Worker         /// Returns a hash code for this object. Two equal byte strings
382*1b3f573fSAndroid Build Coastguard Worker         /// will return the same hash code.
383*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
384*1b3f573fSAndroid Build Coastguard Worker         /// <returns>A hash code for this object.</returns>
385*1b3f573fSAndroid Build Coastguard Worker         [SecuritySafeCritical]
GetHashCode()386*1b3f573fSAndroid Build Coastguard Worker         public override int GetHashCode()
387*1b3f573fSAndroid Build Coastguard Worker         {
388*1b3f573fSAndroid Build Coastguard Worker             ReadOnlySpan<byte> b = bytes.Span;
389*1b3f573fSAndroid Build Coastguard Worker 
390*1b3f573fSAndroid Build Coastguard Worker             int ret = 23;
391*1b3f573fSAndroid Build Coastguard Worker             for (int i = 0; i < b.Length; i++)
392*1b3f573fSAndroid Build Coastguard Worker             {
393*1b3f573fSAndroid Build Coastguard Worker                 ret = (ret * 31) + b[i];
394*1b3f573fSAndroid Build Coastguard Worker             }
395*1b3f573fSAndroid Build Coastguard Worker             return ret;
396*1b3f573fSAndroid Build Coastguard Worker         }
397*1b3f573fSAndroid Build Coastguard Worker 
398*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
399*1b3f573fSAndroid Build Coastguard Worker         /// Compares this byte string with another.
400*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
401*1b3f573fSAndroid Build Coastguard Worker         /// <param name="other">The <see cref="ByteString"/> to compare this with.</param>
402*1b3f573fSAndroid Build Coastguard Worker         /// <returns><c>true</c> if <paramref name="other"/> refers to an equal byte string; <c>false</c> otherwise.</returns>
Equals(ByteString other)403*1b3f573fSAndroid Build Coastguard Worker         public bool Equals(ByteString other)
404*1b3f573fSAndroid Build Coastguard Worker         {
405*1b3f573fSAndroid Build Coastguard Worker             return this == other;
406*1b3f573fSAndroid Build Coastguard Worker         }
407*1b3f573fSAndroid Build Coastguard Worker 
408*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
409*1b3f573fSAndroid Build Coastguard Worker         /// Copies the entire byte array to the destination array provided at the offset specified.
410*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
CopyTo(byte[] array, int position)411*1b3f573fSAndroid Build Coastguard Worker         public void CopyTo(byte[] array, int position)
412*1b3f573fSAndroid Build Coastguard Worker         {
413*1b3f573fSAndroid Build Coastguard Worker             bytes.CopyTo(array.AsMemory(position));
414*1b3f573fSAndroid Build Coastguard Worker         }
415*1b3f573fSAndroid Build Coastguard Worker 
416*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
417*1b3f573fSAndroid Build Coastguard Worker         /// Writes the entire byte array to the provided stream
418*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
WriteTo(Stream outputStream)419*1b3f573fSAndroid Build Coastguard Worker         public void WriteTo(Stream outputStream)
420*1b3f573fSAndroid Build Coastguard Worker         {
421*1b3f573fSAndroid Build Coastguard Worker             if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment))
422*1b3f573fSAndroid Build Coastguard Worker             {
423*1b3f573fSAndroid Build Coastguard Worker                 // Fast path. ByteString was created with an array, so pass the underlying array.
424*1b3f573fSAndroid Build Coastguard Worker                 outputStream.Write(segment.Array, segment.Offset, segment.Count);
425*1b3f573fSAndroid Build Coastguard Worker             }
426*1b3f573fSAndroid Build Coastguard Worker             else
427*1b3f573fSAndroid Build Coastguard Worker             {
428*1b3f573fSAndroid Build Coastguard Worker                 // Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.
429*1b3f573fSAndroid Build Coastguard Worker                 var array = bytes.ToArray();
430*1b3f573fSAndroid Build Coastguard Worker                 outputStream.Write(array, 0, array.Length);
431*1b3f573fSAndroid Build Coastguard Worker             }
432*1b3f573fSAndroid Build Coastguard Worker         }
433*1b3f573fSAndroid Build Coastguard Worker     }
434*1b3f573fSAndroid Build Coastguard Worker }