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}