| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 | #region Copyright notice and license// Protocol Buffers - Google's data interchange format// Copyright 2008 Google Inc.  All rights reserved.// https://developers.google.com/protocol-buffers///// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.//     * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#endregionusing System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Text;namespace Google.Protobuf{    /// <summary>    /// Immutable array of bytes.    /// TODO(jonskeet): Implement the common collection interfaces?    /// </summary>    public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>    {        private static readonly ByteString empty = new ByteString(new byte[0]);        private readonly byte[] bytes;        /// <summary>        /// Unsafe operations that can cause IO Failure and/or other catestrophic side-effects.        /// </summary>        public static class Unsafe        {            /// <summary>            /// Constructs a new ByteString from the given byte array. The array is            /// *not* copied, and must not be modified after this constructor is called.            /// </summary>            public static ByteString FromBytes(byte[] bytes)            {                return new ByteString(bytes);            }            /// <summary>            /// Provides direct, unrestricted access to the bytes contained in this instance.            /// You must not modify or resize the byte array returned by this method.            /// </summary>            public static byte[] GetBuffer(ByteString bytes)            {                return bytes.bytes;            }        }        /// <summary>        /// Internal use only.  Ensure that the provided array is not mutated and belongs to this instance.        /// </summary>        internal static ByteString AttachBytes(byte[] bytes)        {            return new ByteString(bytes);        }        /// <summary>        /// Constructs a new ByteString from the given byte array. The array is        /// *not* copied, and must not be modified after this constructor is called.        /// </summary>        private ByteString(byte[] bytes)        {            this.bytes = bytes;        }        /// <summary>        /// Returns an empty ByteString.        /// </summary>        public static ByteString Empty        {            get { return empty; }        }        /// <summary>        /// Returns the length of this ByteString in bytes.        /// </summary>        public int Length        {            get { return bytes.Length; }        }        public bool IsEmpty        {            get { return Length == 0; }        }        public byte[] ToByteArray()        {            return (byte[]) bytes.Clone();        }        public string ToBase64()        {            return Convert.ToBase64String(bytes);        }        /// <summary>        /// Constructs a ByteString from the Base64 Encoded String.        /// </summary>        public static ByteString FromBase64(string bytes)        {            // By handling the empty string explicitly, we not only optimize but we fix a            // problem on CF 2.0. See issue 61 for details.            return bytes == "" ? Empty : new ByteString(Convert.FromBase64String(bytes));        }        /// <summary>        /// Constructs a ByteString from the given array. The contents        /// are copied, so further modifications to the array will not        /// be reflected in the returned ByteString.        /// This method can also be invoked in <c>ByteString.CopyFrom(0xaa, 0xbb, ...)</c> form        /// which is primarily useful for testing.        /// </summary>        public static ByteString CopyFrom(params byte[] bytes)        {            return new ByteString((byte[]) bytes.Clone());        }        /// <summary>        /// Constructs a ByteString from a portion of a byte array.        /// </summary>        public static ByteString CopyFrom(byte[] bytes, int offset, int count)        {            byte[] portion = new byte[count];            ByteArray.Copy(bytes, offset, portion, 0, count);            return new ByteString(portion);        }        /// <summary>        /// Creates a new ByteString by encoding the specified text with        /// the given encoding.        /// </summary>        public static ByteString CopyFrom(string text, Encoding encoding)        {            return new ByteString(encoding.GetBytes(text));        }        /// <summary>        /// Creates a new ByteString by encoding the specified text in UTF-8.        /// </summary>        public static ByteString CopyFromUtf8(string text)        {            return CopyFrom(text, Encoding.UTF8);        }        /// <summary>        /// Retuns the byte at the given index.        /// </summary>        public byte this[int index]        {            get { return bytes[index]; }        }        public string ToString(Encoding encoding)        {            return encoding.GetString(bytes, 0, bytes.Length);        }        public string ToStringUtf8()        {            return ToString(Encoding.UTF8);        }        public IEnumerator<byte> GetEnumerator()        {            return ((IEnumerable<byte>) bytes).GetEnumerator();        }        IEnumerator IEnumerable.GetEnumerator()        {            return GetEnumerator();        }        /// <summary>        /// Creates a CodedInputStream from this ByteString's data.        /// </summary>        public CodedInputStream CreateCodedInput()        {            // We trust CodedInputStream not to reveal the provided byte array or modify it            return CodedInputStream.CreateInstance(bytes);        }        public static bool operator ==(ByteString lhs, ByteString rhs)        {            if (ReferenceEquals(lhs, rhs))            {                return true;            }            if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))            {                return false;            }            if (lhs.bytes.Length != rhs.bytes.Length)            {                return false;            }            for (int i = 0; i < lhs.Length; i++)            {                if (rhs.bytes[i] != lhs.bytes[i])                {                    return false;                }            }            return true;        }        public static bool operator !=(ByteString lhs, ByteString rhs)        {            return !(lhs == rhs);        }        // TODO(jonskeet): CopyTo if it turns out to be required        public override bool Equals(object obj)        {            return this == (obj as ByteString);        }        public override int GetHashCode()        {            int ret = 23;            foreach (byte b in bytes)            {                ret = (ret << 8) | b;            }            return ret;        }        public bool Equals(ByteString other)        {            return this == other;        }        /// <summary>        /// Used internally by CodedOutputStream to avoid creating a copy for the write        /// </summary>        internal void WriteRawBytesTo(CodedOutputStream outputStream)        {            outputStream.WriteRawBytes(bytes, 0, bytes.Length);        }        /// <summary>        /// Copies the entire byte array to the destination array provided at the offset specified.        /// </summary>        public void CopyTo(byte[] array, int position)        {            ByteArray.Copy(bytes, 0, array, position, bytes.Length);        }        /// <summary>        /// Writes the entire byte array to the provided stream        /// </summary>        public void WriteTo(Stream outputStream)        {            outputStream.Write(bytes, 0, bytes.Length);        }    }}
 |