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