ByteString.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using System.Collections;
  36. using System.Collections.Generic;
  37. using System.Text;
  38. namespace Google.ProtocolBuffers {
  39. /// <summary>
  40. /// Immutable array of bytes.
  41. /// TODO(jonskeet): Implement the common collection interfaces?
  42. /// </summary>
  43. public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString> {
  44. private static readonly ByteString empty = new ByteString(new byte[0]);
  45. private readonly byte[] bytes;
  46. /// <summary>
  47. /// Constructs a new ByteString from the given byte array. The array is
  48. /// *not* copied, and must not be modified after this constructor is called.
  49. /// </summary>
  50. private ByteString(byte[] bytes) {
  51. this.bytes = bytes;
  52. }
  53. /// <summary>
  54. /// Returns an empty ByteString.
  55. /// </summary>
  56. public static ByteString Empty {
  57. get { return empty; }
  58. }
  59. /// <summary>
  60. /// Returns the length of this ByteString in bytes.
  61. /// </summary>
  62. public int Length {
  63. get { return bytes.Length; }
  64. }
  65. public bool IsEmpty {
  66. get { return Length == 0; }
  67. }
  68. public byte[] ToByteArray() {
  69. return (byte[])bytes.Clone();
  70. }
  71. /// <summary>
  72. /// Constructs a ByteString from the Base64 Encoded String.
  73. /// </summary>
  74. public static ByteString FromBase64(string bytes) {
  75. return new ByteString(System.Convert.FromBase64String(bytes));
  76. }
  77. /// <summary>
  78. /// Constructs a ByteString from the given array. The contents
  79. /// are copied, so further modifications to the array will not
  80. /// be reflected in the returned ByteString.
  81. /// </summary>
  82. public static ByteString CopyFrom(byte[] bytes) {
  83. return new ByteString((byte[]) bytes.Clone());
  84. }
  85. /// <summary>
  86. /// Constructs a ByteString from a portion of a byte array.
  87. /// </summary>
  88. public static ByteString CopyFrom(byte[] bytes, int offset, int count) {
  89. byte[] portion = new byte[count];
  90. Array.Copy(bytes, offset, portion, 0, count);
  91. return new ByteString(portion);
  92. }
  93. /// <summary>
  94. /// Creates a new ByteString by encoding the specified text with
  95. /// the given encoding.
  96. /// </summary>
  97. public static ByteString CopyFrom(string text, Encoding encoding) {
  98. return new ByteString(encoding.GetBytes(text));
  99. }
  100. /// <summary>
  101. /// Creates a new ByteString by encoding the specified text in UTF-8.
  102. /// </summary>
  103. public static ByteString CopyFromUtf8(string text) {
  104. return CopyFrom(text, Encoding.UTF8);
  105. }
  106. /// <summary>
  107. /// Retuns the byte at the given index.
  108. /// </summary>
  109. public byte this[int index] {
  110. get { return bytes[index]; }
  111. }
  112. public string ToString(Encoding encoding) {
  113. return encoding.GetString(bytes, 0, bytes.Length);
  114. }
  115. public string ToStringUtf8() {
  116. return ToString(Encoding.UTF8);
  117. }
  118. public IEnumerator<byte> GetEnumerator() {
  119. return ((IEnumerable<byte>) bytes).GetEnumerator();
  120. }
  121. IEnumerator IEnumerable.GetEnumerator() {
  122. return GetEnumerator();
  123. }
  124. /// <summary>
  125. /// Creates a CodedInputStream from this ByteString's data.
  126. /// </summary>
  127. public CodedInputStream CreateCodedInput() {
  128. // We trust CodedInputStream not to reveal the provided byte array or modify it
  129. return CodedInputStream.CreateInstance(bytes);
  130. }
  131. // TODO(jonskeet): CopyTo if it turns out to be required
  132. public override bool Equals(object obj) {
  133. ByteString other = obj as ByteString;
  134. if (obj == null) {
  135. return false;
  136. }
  137. return Equals(other);
  138. }
  139. public override int GetHashCode() {
  140. int ret = 23;
  141. foreach (byte b in bytes) {
  142. ret = (ret << 8) | b;
  143. }
  144. return ret;
  145. }
  146. public bool Equals(ByteString other) {
  147. if (other.bytes.Length != bytes.Length) {
  148. return false;
  149. }
  150. for (int i = 0; i < bytes.Length; i++) {
  151. if (other.bytes[i] != bytes[i]) {
  152. return false;
  153. }
  154. }
  155. return true;
  156. }
  157. /// <summary>
  158. /// Builder for ByteStrings which allows them to be created without extra
  159. /// copying being involved. This has to be a nested type in order to have access
  160. /// to the private ByteString constructor.
  161. /// </summary>
  162. internal sealed class CodedBuilder {
  163. private readonly CodedOutputStream output;
  164. private readonly byte[] buffer;
  165. internal CodedBuilder(int size) {
  166. buffer = new byte[size];
  167. output = CodedOutputStream.CreateInstance(buffer);
  168. }
  169. internal ByteString Build() {
  170. output.CheckNoSpaceLeft();
  171. // We can be confident that the CodedOutputStream will not modify the
  172. // underlying bytes anymore because it already wrote all of them. So,
  173. // no need to make a copy.
  174. return new ByteString(buffer);
  175. }
  176. internal CodedOutputStream CodedOutput {
  177. get {
  178. return output;
  179. }
  180. }
  181. }
  182. }
  183. }