blob: bb133a77415d651b5ff9be388d1a177d2391bff4 [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
csharptest74c5e0c2011-07-14 13:06:22 -050038using System.Collections;
csharptestc671a4b2011-06-08 11:51:24 -050039using System.Collections.Generic;
csharptest71f662c2011-05-20 15:15:34 -050040using System.IO;
41using System.Text;
csharptestced18e12011-06-09 19:47:56 -050042using Google.ProtocolBuffers.Collections;
csharptest71f662c2011-05-20 15:15:34 -050043using Google.ProtocolBuffers.Descriptors;
44
45namespace Google.ProtocolBuffers
46{
47 /// <summary>
48 /// Encodes and writes protocol message fields.
49 /// </summary>
50 /// <remarks>
51 /// This class contains two kinds of methods: methods that write specific
52 /// protocol message constructs and field types (e.g. WriteTag and
53 /// WriteInt32) and methods that write low-level values (e.g.
54 /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
55 /// messages, you should use the former methods, but if you are writing some
56 /// other format of your own design, use the latter. The names of the former
57 /// methods are taken from the protocol buffer type names, not .NET types.
58 /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
59 /// </remarks>
csharptest819b7152011-09-08 20:28:22 -050060 public sealed partial class CodedOutputStream : ICodedOutputStream, IDisposable
csharptest71f662c2011-05-20 15:15:34 -050061 {
62 /// <summary>
63 /// The buffer size used by CreateInstance(Stream).
64 /// </summary>
65 public static readonly int DefaultBufferSize = 4096;
66
67 private readonly byte[] buffer;
68 private readonly int limit;
69 private int position;
70 private readonly Stream output;
71
72 #region Construction
73
74 private CodedOutputStream(byte[] buffer, int offset, int length)
75 {
76 this.output = null;
77 this.buffer = buffer;
78 this.position = offset;
79 this.limit = offset + length;
80 }
81
82 private CodedOutputStream(Stream output, byte[] buffer)
83 {
84 this.output = output;
85 this.buffer = buffer;
86 this.position = 0;
87 this.limit = buffer.Length;
88 }
89
90 /// <summary>
91 /// Creates a new CodedOutputStream which write to the given stream.
92 /// </summary>
93 public static CodedOutputStream CreateInstance(Stream output)
94 {
95 return CreateInstance(output, DefaultBufferSize);
96 }
97
98 /// <summary>
99 /// Creates a new CodedOutputStream which write to the given stream and uses
100 /// the specified buffer size.
101 /// </summary>
102 public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
103 {
104 return new CodedOutputStream(output, new byte[bufferSize]);
105 }
106
107 /// <summary>
108 /// Creates a new CodedOutputStream that writes directly to the given
109 /// byte array. If more bytes are written than fit in the array,
110 /// OutOfSpaceException will be thrown.
111 /// </summary>
112 public static CodedOutputStream CreateInstance(byte[] flatArray)
113 {
114 return CreateInstance(flatArray, 0, flatArray.Length);
115 }
116
117 /// <summary>
118 /// Creates a new CodedOutputStream that writes directly to the given
119 /// byte array slice. If more bytes are written than fit in the array,
120 /// OutOfSpaceException will be thrown.
121 /// </summary>
122 public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
123 {
124 return new CodedOutputStream(flatArray, offset, length);
125 }
126
127 #endregion
csharptest819b7152011-09-08 20:28:22 -0500128
129 public void Dispose()
130 {
131 if (output != null)
132 {
133 if (position > 0)
134 Flush();
135 output.Dispose();
136 }
137 }
csharptest71f662c2011-05-20 15:15:34 -0500138
csharptest2b868842011-06-10 14:41:47 -0500139 #region Writing of unknown fields
140
141 [Obsolete]
142 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
143 {
144 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
145 value.WriteTo(this);
146 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
147 }
148
149 public void WriteUnknownBytes(int fieldNumber, ByteString value)
150 {
151 WriteBytes(fieldNumber, null /*not used*/, value);
152 }
153
154 [CLSCompliant(false)]
155 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
156 {
csharptest74c5e0c2011-07-14 13:06:22 -0500157 if (wireType == WireFormat.WireType.Varint)
158 {
csharptest2b868842011-06-10 14:41:47 -0500159 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500160 }
csharptest2b868842011-06-10 14:41:47 -0500161 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500162 {
163 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
164 }
csharptest2b868842011-06-10 14:41:47 -0500165 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500166 {
csharptest2b868842011-06-10 14:41:47 -0500167 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500168 }
csharptest2b868842011-06-10 14:41:47 -0500169 else
csharptest74c5e0c2011-07-14 13:06:22 -0500170 {
csharptest2b868842011-06-10 14:41:47 -0500171 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500172 }
csharptest2b868842011-06-10 14:41:47 -0500173 }
174
175 #endregion
176
csharptestb00ea132011-06-10 01:09:57 -0500177 #region Writing of tags and fields
178
179 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
180 {
181 switch (fieldType)
182 {
183 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500184 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500185 break;
186 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500187 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500188 break;
189 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500190 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500191 break;
192 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500193 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500194 break;
195 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500196 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500197 break;
198 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500199 if (value is Enum)
200 {
201 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
202 }
csharptestb00ea132011-06-10 01:09:57 -0500203 else
csharptest74c5e0c2011-07-14 13:06:22 -0500204 {
205 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
206 }
csharptestb00ea132011-06-10 01:09:57 -0500207 break;
208 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500209 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500210 break;
211 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500212 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500213 break;
214 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500215 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500216 break;
217 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500218 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500219 break;
220 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500221 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500222 break;
223 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500224 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500225 break;
226 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500227 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500228 break;
229 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500230 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500231 break;
232 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500233 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500234 break;
235 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500236 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500237 break;
238 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500239 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500240 break;
241 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500242 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500243 break;
244 }
245 }
csharptest71f662c2011-05-20 15:15:34 -0500246
247 /// <summary>
248 /// Writes a double field value, including tag, to the stream.
249 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500250 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500251 {
252 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
253 WriteDoubleNoTag(value);
254 }
255
256 /// <summary>
257 /// Writes a float field value, including tag, to the stream.
258 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500259 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500260 {
261 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
262 WriteFloatNoTag(value);
263 }
264
265 /// <summary>
266 /// Writes a uint64 field value, including tag, to the stream.
267 /// </summary>
268 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500269 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500270 {
271 WriteTag(fieldNumber, WireFormat.WireType.Varint);
272 WriteRawVarint64(value);
273 }
274
275 /// <summary>
276 /// Writes an int64 field value, including tag, to the stream.
277 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500278 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500279 {
280 WriteTag(fieldNumber, WireFormat.WireType.Varint);
281 WriteRawVarint64((ulong) value);
282 }
283
284 /// <summary>
285 /// Writes an int32 field value, including tag, to the stream.
286 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500287 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500288 {
289 WriteTag(fieldNumber, WireFormat.WireType.Varint);
290 if (value >= 0)
291 {
292 WriteRawVarint32((uint) value);
293 }
294 else
295 {
296 // Must sign-extend.
297 WriteRawVarint64((ulong) value);
298 }
299 }
300
301 /// <summary>
302 /// Writes a fixed64 field value, including tag, to the stream.
303 /// </summary>
304 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500305 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500306 {
307 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
308 WriteRawLittleEndian64(value);
309 }
310
311 /// <summary>
312 /// Writes a fixed32 field value, including tag, to the stream.
313 /// </summary>
314 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500315 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500316 {
317 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
318 WriteRawLittleEndian32(value);
319 }
320
321 /// <summary>
322 /// Writes a bool field value, including tag, to the stream.
323 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500324 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500325 {
326 WriteTag(fieldNumber, WireFormat.WireType.Varint);
327 WriteRawByte(value ? (byte) 1 : (byte) 0);
328 }
329
330 /// <summary>
331 /// Writes a string field value, including tag, to the stream.
332 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500333 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500334 {
335 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
336 // Optimise the case where we have enough space to write
337 // the string directly to the buffer, which should be common.
338 int length = Encoding.UTF8.GetByteCount(value);
339 WriteRawVarint32((uint) length);
340 if (limit - position >= length)
341 {
342 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
343 position += length;
344 }
345 else
346 {
347 byte[] bytes = Encoding.UTF8.GetBytes(value);
348 WriteRawBytes(bytes);
349 }
350 }
351
352 /// <summary>
353 /// Writes a group field value, including tag, to the stream.
354 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500355 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500356 {
357 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
358 value.WriteTo(this);
359 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
360 }
361
csharptest90922db2011-06-03 11:57:47 -0500362 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500363 {
364 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
365 WriteRawVarint32((uint) value.SerializedSize);
366 value.WriteTo(this);
367 }
368
csharptest90922db2011-06-03 11:57:47 -0500369 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500370 {
csharptest71f662c2011-05-20 15:15:34 -0500371 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500372 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500373 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500374 }
375
376 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500377 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500378 {
379 WriteTag(fieldNumber, WireFormat.WireType.Varint);
380 WriteRawVarint32(value);
381 }
382
csharptest304ff3a2011-08-05 16:51:49 -0500383 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500384 {
385 WriteTag(fieldNumber, WireFormat.WireType.Varint);
386 WriteRawVarint32((uint) value);
387 }
388
csharptest90922db2011-06-03 11:57:47 -0500389 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500390 {
391 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
392 WriteRawLittleEndian32((uint) value);
393 }
394
csharptest90922db2011-06-03 11:57:47 -0500395 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500396 {
397 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
398 WriteRawLittleEndian64((ulong) value);
399 }
400
csharptest90922db2011-06-03 11:57:47 -0500401 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500402 {
403 WriteTag(fieldNumber, WireFormat.WireType.Varint);
404 WriteRawVarint32(EncodeZigZag32(value));
405 }
406
csharptest90922db2011-06-03 11:57:47 -0500407 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500408 {
409 WriteTag(fieldNumber, WireFormat.WireType.Varint);
410 WriteRawVarint64(EncodeZigZag64(value));
411 }
412
csharptest90922db2011-06-03 11:57:47 -0500413 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500414 {
415 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500416 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
417 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500418 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
419 }
420
csharptestffafdaa2011-06-03 12:58:14 -0500421 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500422 {
423 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500424 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
425 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500426 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
427 }
csharptest90922db2011-06-03 11:57:47 -0500428
csharptestb00ea132011-06-10 01:09:57 -0500429 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500430
csharptestb00ea132011-06-10 01:09:57 -0500431 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500432
433 public void WriteFieldNoTag(FieldType fieldType, object value)
434 {
435 switch (fieldType)
436 {
csharptestc671a4b2011-06-08 11:51:24 -0500437 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500438 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500439 break;
csharptestc671a4b2011-06-08 11:51:24 -0500440 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500441 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500442 break;
csharptestc671a4b2011-06-08 11:51:24 -0500443 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500444 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500445 break;
csharptestc671a4b2011-06-08 11:51:24 -0500446 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500447 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500448 break;
449 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500450 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500451 break;
452 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500453 if (value is Enum)
454 {
455 WriteEnumNoTag((int) value);
456 }
csharptestc671a4b2011-06-08 11:51:24 -0500457 else
csharptest74c5e0c2011-07-14 13:06:22 -0500458 {
459 WriteEnumNoTag(((IEnumLite) value).Number);
460 }
csharptest71f662c2011-05-20 15:15:34 -0500461 break;
462 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500463 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500464 break;
csharptestc671a4b2011-06-08 11:51:24 -0500465 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500466 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500467 break;
468 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500469 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500470 break;
csharptestc671a4b2011-06-08 11:51:24 -0500471 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500472 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500473 break;
474 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500475 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500476 break;
477 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500478 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500479 break;
csharptestc671a4b2011-06-08 11:51:24 -0500480 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500481 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500482 break;
483 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500484 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500485 break;
486 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500487 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500488 break;
489 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500490 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500491 break;
492 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500493 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500494 break;
495 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500496 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500497 break;
498 }
499 }
500
csharptest71f662c2011-05-20 15:15:34 -0500501 /// <summary>
502 /// Writes a double field value, including tag, to the stream.
503 /// </summary>
504 public void WriteDoubleNoTag(double value)
505 {
csharptest71f662c2011-05-20 15:15:34 -0500506#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500507 byte[] rawBytes = BitConverter.GetBytes(value);
508 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500509 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500510
511 if (limit - position >= 8)
512 {
513 buffer[position++] = rawBytes[0];
514 buffer[position++] = rawBytes[1];
515 buffer[position++] = rawBytes[2];
516 buffer[position++] = rawBytes[3];
517 buffer[position++] = rawBytes[4];
518 buffer[position++] = rawBytes[5];
519 buffer[position++] = rawBytes[6];
520 buffer[position++] = rawBytes[7];
521 }
522 else
523 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500524#else
csharptest74c5e0c2011-07-14 13:06:22 -0500525 WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500526#endif
527 }
528
529 /// <summary>
530 /// Writes a float field value, without a tag, to the stream.
531 /// </summary>
532 public void WriteFloatNoTag(float value)
533 {
csharptest71f662c2011-05-20 15:15:34 -0500534 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500535 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500536 {
csharptestaef072a2011-06-08 18:00:43 -0500537 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500538 }
csharptest2772dfe2011-06-08 15:50:58 -0500539
540 if (limit - position >= 4)
541 {
542 buffer[position++] = rawBytes[0];
543 buffer[position++] = rawBytes[1];
544 buffer[position++] = rawBytes[2];
545 buffer[position++] = rawBytes[3];
546 }
547 else
csharptest74c5e0c2011-07-14 13:06:22 -0500548 {
csharptest2772dfe2011-06-08 15:50:58 -0500549 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500550 }
csharptest71f662c2011-05-20 15:15:34 -0500551 }
552
553 /// <summary>
554 /// Writes a uint64 field value, without a tag, to the stream.
555 /// </summary>
556 [CLSCompliant(false)]
557 public void WriteUInt64NoTag(ulong value)
558 {
559 WriteRawVarint64(value);
560 }
561
562 /// <summary>
563 /// Writes an int64 field value, without a tag, to the stream.
564 /// </summary>
565 public void WriteInt64NoTag(long value)
566 {
csharptest74c5e0c2011-07-14 13:06:22 -0500567 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500568 }
569
570 /// <summary>
571 /// Writes an int32 field value, without a tag, to the stream.
572 /// </summary>
573 public void WriteInt32NoTag(int value)
574 {
575 if (value >= 0)
576 {
csharptest74c5e0c2011-07-14 13:06:22 -0500577 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500578 }
579 else
580 {
581 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500582 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500583 }
584 }
585
586 /// <summary>
587 /// Writes a fixed64 field value, without a tag, to the stream.
588 /// </summary>
589 [CLSCompliant(false)]
590 public void WriteFixed64NoTag(ulong value)
591 {
592 WriteRawLittleEndian64(value);
593 }
594
595 /// <summary>
596 /// Writes a fixed32 field value, without a tag, to the stream.
597 /// </summary>
598 [CLSCompliant(false)]
599 public void WriteFixed32NoTag(uint value)
600 {
601 WriteRawLittleEndian32(value);
602 }
603
604 /// <summary>
605 /// Writes a bool field value, without a tag, to the stream.
606 /// </summary>
607 public void WriteBoolNoTag(bool value)
608 {
csharptest74c5e0c2011-07-14 13:06:22 -0500609 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500610 }
611
612 /// <summary>
613 /// Writes a string field value, without a tag, to the stream.
614 /// </summary>
615 public void WriteStringNoTag(string value)
616 {
617 // Optimise the case where we have enough space to write
618 // the string directly to the buffer, which should be common.
619 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500620 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500621 if (limit - position >= length)
622 {
623 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
624 position += length;
625 }
626 else
627 {
628 byte[] bytes = Encoding.UTF8.GetBytes(value);
629 WriteRawBytes(bytes);
630 }
631 }
632
633 /// <summary>
634 /// Writes a group field value, without a tag, to the stream.
635 /// </summary>
636 public void WriteGroupNoTag(IMessageLite value)
637 {
638 value.WriteTo(this);
639 }
640
641 public void WriteMessageNoTag(IMessageLite value)
642 {
csharptest74c5e0c2011-07-14 13:06:22 -0500643 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500644 value.WriteTo(this);
645 }
646
647 public void WriteBytesNoTag(ByteString value)
648 {
csharptest74c5e0c2011-07-14 13:06:22 -0500649 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500650 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500651 }
652
653 [CLSCompliant(false)]
654 public void WriteUInt32NoTag(uint value)
655 {
656 WriteRawVarint32(value);
657 }
658
659 public void WriteEnumNoTag(int value)
660 {
csharptest74c5e0c2011-07-14 13:06:22 -0500661 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500662 }
663
664 public void WriteSFixed32NoTag(int value)
665 {
csharptest74c5e0c2011-07-14 13:06:22 -0500666 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500667 }
668
669 public void WriteSFixed64NoTag(long value)
670 {
csharptest74c5e0c2011-07-14 13:06:22 -0500671 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500672 }
673
674 public void WriteSInt32NoTag(int value)
675 {
676 WriteRawVarint32(EncodeZigZag32(value));
677 }
678
679 public void WriteSInt64NoTag(long value)
680 {
681 WriteRawVarint64(EncodeZigZag64(value));
682 }
683
684 #endregion
685
csharptestb00ea132011-06-10 01:09:57 -0500686 #region Write array members
687
csharptest74c5e0c2011-07-14 13:06:22 -0500688 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500689 {
690 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500691 {
csharptestb00ea132011-06-10 01:09:57 -0500692 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500693 }
csharptestb00ea132011-06-10 01:09:57 -0500694 }
695
696 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
697 where T : IMessageLite
698 {
699 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500700 {
csharptestb00ea132011-06-10 01:09:57 -0500701 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500702 }
csharptestb00ea132011-06-10 01:09:57 -0500703 }
704
705 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
706 where T : IMessageLite
707 {
708 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500709 {
csharptestb00ea132011-06-10 01:09:57 -0500710 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500711 }
csharptestb00ea132011-06-10 01:09:57 -0500712 }
713
714 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
715 {
716 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500717 {
csharptestb00ea132011-06-10 01:09:57 -0500718 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500719 }
csharptestb00ea132011-06-10 01:09:57 -0500720 }
721
722 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
723 {
724 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500725 {
csharptestb00ea132011-06-10 01:09:57 -0500726 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500727 }
csharptestb00ea132011-06-10 01:09:57 -0500728 }
729
730 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
731 {
732 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500733 {
csharptestb00ea132011-06-10 01:09:57 -0500734 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500735 }
csharptestb00ea132011-06-10 01:09:57 -0500736 }
737
738 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
739 {
740 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500741 {
csharptestb00ea132011-06-10 01:09:57 -0500742 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500743 }
csharptestb00ea132011-06-10 01:09:57 -0500744 }
745
746 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
747 {
748 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500749 {
csharptestb00ea132011-06-10 01:09:57 -0500750 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500751 }
csharptestb00ea132011-06-10 01:09:57 -0500752 }
753
754 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
755 {
756 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500757 {
csharptestb00ea132011-06-10 01:09:57 -0500758 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500759 }
csharptestb00ea132011-06-10 01:09:57 -0500760 }
761
762 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
763 {
764 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500765 {
csharptestb00ea132011-06-10 01:09:57 -0500766 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500767 }
csharptestb00ea132011-06-10 01:09:57 -0500768 }
769
770 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
771 {
772 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500773 {
csharptestb00ea132011-06-10 01:09:57 -0500774 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500775 }
csharptestb00ea132011-06-10 01:09:57 -0500776 }
777
778 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
779 {
780 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500781 {
csharptestb00ea132011-06-10 01:09:57 -0500782 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500783 }
csharptestb00ea132011-06-10 01:09:57 -0500784 }
785
786 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
787 {
788 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500789 {
csharptestb00ea132011-06-10 01:09:57 -0500790 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500791 }
csharptestb00ea132011-06-10 01:09:57 -0500792 }
793
794 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
795 {
796 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500797 {
csharptestb00ea132011-06-10 01:09:57 -0500798 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500799 }
csharptestb00ea132011-06-10 01:09:57 -0500800 }
801
802 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
803 {
804 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500805 {
csharptestb00ea132011-06-10 01:09:57 -0500806 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500807 }
csharptestb00ea132011-06-10 01:09:57 -0500808 }
809
810 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
811 {
812 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500813 {
csharptestb00ea132011-06-10 01:09:57 -0500814 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500815 }
csharptestb00ea132011-06-10 01:09:57 -0500816 }
817
818 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
819 {
820 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500821 {
csharptestb00ea132011-06-10 01:09:57 -0500822 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500823 }
csharptestb00ea132011-06-10 01:09:57 -0500824 }
825
826 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
827 {
828 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500829 {
csharptestb00ea132011-06-10 01:09:57 -0500830 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500831 }
csharptestb00ea132011-06-10 01:09:57 -0500832 }
833
834 [CLSCompliant(false)]
835 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
836 where T : struct, IComparable, IFormattable, IConvertible
837 {
838 if (list is ICastArray)
839 {
csharptest74c5e0c2011-07-14 13:06:22 -0500840 foreach (int value in ((ICastArray) list).CastArray<int>())
841 {
csharptestb00ea132011-06-10 01:09:57 -0500842 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500843 }
csharptestb00ea132011-06-10 01:09:57 -0500844 }
845 else
846 {
847 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500848 {
csharptestb00ea132011-06-10 01:09:57 -0500849 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500850 }
csharptestb00ea132011-06-10 01:09:57 -0500851 }
852 }
853
854 #endregion
855
856 #region Write packed array members
857
csharptest74c5e0c2011-07-14 13:06:22 -0500858 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500859 {
860 int calculatedSize = 0;
861 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500862 {
863 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
864 }
csharptestb00ea132011-06-10 01:09:57 -0500865
866 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500867 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500868
869 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500870 {
csharptestb00ea132011-06-10 01:09:57 -0500871 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500872 }
csharptestb00ea132011-06-10 01:09:57 -0500873 }
874
875 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
876 where T : IMessageLite
877 {
878 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500879 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500880 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500881 {
csharptestb00ea132011-06-10 01:09:57 -0500882 WriteGroupNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500883 }
csharptestb00ea132011-06-10 01:09:57 -0500884 }
885
csharptest74c5e0c2011-07-14 13:06:22 -0500886 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
887 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500888 where T : IMessageLite
889 {
890 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500891 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500892 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500893 {
csharptestb00ea132011-06-10 01:09:57 -0500894 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500895 }
csharptestb00ea132011-06-10 01:09:57 -0500896 }
897
csharptest74c5e0c2011-07-14 13:06:22 -0500898 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
899 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500900 {
901 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500902 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500903 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500904 {
csharptestb00ea132011-06-10 01:09:57 -0500905 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500906 }
csharptestb00ea132011-06-10 01:09:57 -0500907 }
908
csharptest74c5e0c2011-07-14 13:06:22 -0500909 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
910 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500911 {
912 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500913 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500914 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500915 {
csharptestb00ea132011-06-10 01:09:57 -0500916 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500917 }
csharptestb00ea132011-06-10 01:09:57 -0500918 }
919
920 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
921 {
922 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500923 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500924 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500925 {
csharptestb00ea132011-06-10 01:09:57 -0500926 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500927 }
csharptestb00ea132011-06-10 01:09:57 -0500928 }
929
930 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
931 {
932 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500933 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500934 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500935 {
csharptestb00ea132011-06-10 01:09:57 -0500936 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500937 }
csharptestb00ea132011-06-10 01:09:57 -0500938 }
939
940 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
941 {
942 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500943 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500944 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500945 {
csharptestb00ea132011-06-10 01:09:57 -0500946 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500947 }
csharptestb00ea132011-06-10 01:09:57 -0500948 }
949
950 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
951 {
952 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500953 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500954 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500955 {
csharptestb00ea132011-06-10 01:09:57 -0500956 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500957 }
csharptestb00ea132011-06-10 01:09:57 -0500958 }
959
csharptest74c5e0c2011-07-14 13:06:22 -0500960 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
961 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500962 {
963 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500964 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500965 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500966 {
csharptestb00ea132011-06-10 01:09:57 -0500967 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500968 }
csharptestb00ea132011-06-10 01:09:57 -0500969 }
970
csharptest74c5e0c2011-07-14 13:06:22 -0500971 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
972 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500973 {
974 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500975 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500976 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500977 {
csharptestb00ea132011-06-10 01:09:57 -0500978 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500979 }
csharptestb00ea132011-06-10 01:09:57 -0500980 }
981
982 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
983 {
984 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500985 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500986 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500987 {
csharptestb00ea132011-06-10 01:09:57 -0500988 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500989 }
csharptestb00ea132011-06-10 01:09:57 -0500990 }
991
992 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
993 {
994 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500995 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500996 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500997 {
csharptestb00ea132011-06-10 01:09:57 -0500998 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500999 }
csharptestb00ea132011-06-10 01:09:57 -05001000 }
1001
csharptest74c5e0c2011-07-14 13:06:22 -05001002 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
1003 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001004 {
1005 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001006 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001007 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001008 {
csharptestb00ea132011-06-10 01:09:57 -05001009 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001010 }
csharptestb00ea132011-06-10 01:09:57 -05001011 }
1012
csharptest74c5e0c2011-07-14 13:06:22 -05001013 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1014 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001015 {
1016 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001017 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001018 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001019 {
csharptestb00ea132011-06-10 01:09:57 -05001020 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001021 }
csharptestb00ea132011-06-10 01:09:57 -05001022 }
1023
csharptest74c5e0c2011-07-14 13:06:22 -05001024 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1025 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001026 {
1027 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001028 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001029 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001030 {
csharptestb00ea132011-06-10 01:09:57 -05001031 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001032 }
csharptestb00ea132011-06-10 01:09:57 -05001033 }
1034
csharptest74c5e0c2011-07-14 13:06:22 -05001035 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1036 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001037 {
1038 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001039 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001040 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001041 {
csharptestb00ea132011-06-10 01:09:57 -05001042 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001043 }
csharptestb00ea132011-06-10 01:09:57 -05001044 }
1045
1046 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1047 {
1048 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001049 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001050 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001051 {
csharptestb00ea132011-06-10 01:09:57 -05001052 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001053 }
csharptestb00ea132011-06-10 01:09:57 -05001054 }
1055
1056 [CLSCompliant(false)]
1057 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1058 where T : struct, IComparable, IFormattable, IConvertible
1059 {
1060 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001061 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001062 if (list is ICastArray)
1063 {
csharptest74c5e0c2011-07-14 13:06:22 -05001064 foreach (int value in ((ICastArray) list).CastArray<int>())
1065 {
csharptestb00ea132011-06-10 01:09:57 -05001066 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001067 }
csharptestb00ea132011-06-10 01:09:57 -05001068 }
1069 else
1070 {
1071 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001072 {
1073 WriteEnumNoTag((int) value);
1074 }
csharptestb00ea132011-06-10 01:09:57 -05001075 }
1076 }
1077
1078 #endregion
1079
csharptest71f662c2011-05-20 15:15:34 -05001080 #region Underlying writing primitives
1081
1082 /// <summary>
1083 /// Encodes and writes a tag.
1084 /// </summary>
1085 [CLSCompliant(false)]
1086 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1087 {
1088 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1089 }
1090
csharptest71f662c2011-05-20 15:15:34 -05001091 /// <summary>
1092 /// Writes a 32 bit value as a varint. The fast route is taken when
1093 /// there's enough buffer space left to whizz through without checking
1094 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1095 /// </summary>
1096 [CLSCompliant(false)]
1097 public void WriteRawVarint32(uint value)
1098 {
csharptestc671a4b2011-06-08 11:51:24 -05001099 while (value > 127 && position < limit)
1100 {
csharptest74c5e0c2011-07-14 13:06:22 -05001101 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001102 value >>= 7;
1103 }
1104 while (value > 127)
1105 {
csharptest74c5e0c2011-07-14 13:06:22 -05001106 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001107 value >>= 7;
1108 }
csharptest74c5e0c2011-07-14 13:06:22 -05001109 if (position < limit)
1110 {
1111 buffer[position++] = (byte) value;
1112 }
csharptestc671a4b2011-06-08 11:51:24 -05001113 else
csharptest74c5e0c2011-07-14 13:06:22 -05001114 {
1115 WriteRawByte((byte) value);
1116 }
csharptest71f662c2011-05-20 15:15:34 -05001117 }
1118
1119 [CLSCompliant(false)]
1120 public void WriteRawVarint64(ulong value)
1121 {
csharptestc671a4b2011-06-08 11:51:24 -05001122 while (value > 127 && position < limit)
1123 {
csharptest74c5e0c2011-07-14 13:06:22 -05001124 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001125 value >>= 7;
1126 }
1127 while (value > 127)
1128 {
csharptest74c5e0c2011-07-14 13:06:22 -05001129 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001130 value >>= 7;
1131 }
csharptest74c5e0c2011-07-14 13:06:22 -05001132 if (position < limit)
1133 {
1134 buffer[position++] = (byte) value;
1135 }
csharptestc671a4b2011-06-08 11:51:24 -05001136 else
csharptest74c5e0c2011-07-14 13:06:22 -05001137 {
1138 WriteRawByte((byte) value);
1139 }
csharptest71f662c2011-05-20 15:15:34 -05001140 }
1141
1142 [CLSCompliant(false)]
1143 public void WriteRawLittleEndian32(uint value)
1144 {
csharptestc671a4b2011-06-08 11:51:24 -05001145 if (position + 4 > limit)
1146 {
1147 WriteRawByte((byte) value);
1148 WriteRawByte((byte) (value >> 8));
1149 WriteRawByte((byte) (value >> 16));
1150 WriteRawByte((byte) (value >> 24));
1151 }
1152 else
1153 {
csharptest74c5e0c2011-07-14 13:06:22 -05001154 buffer[position++] = ((byte) value);
1155 buffer[position++] = ((byte) (value >> 8));
1156 buffer[position++] = ((byte) (value >> 16));
1157 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001158 }
csharptest71f662c2011-05-20 15:15:34 -05001159 }
1160
1161 [CLSCompliant(false)]
1162 public void WriteRawLittleEndian64(ulong value)
1163 {
csharptestc671a4b2011-06-08 11:51:24 -05001164 if (position + 8 > limit)
1165 {
1166 WriteRawByte((byte) value);
1167 WriteRawByte((byte) (value >> 8));
1168 WriteRawByte((byte) (value >> 16));
1169 WriteRawByte((byte) (value >> 24));
1170 WriteRawByte((byte) (value >> 32));
1171 WriteRawByte((byte) (value >> 40));
1172 WriteRawByte((byte) (value >> 48));
1173 WriteRawByte((byte) (value >> 56));
1174 }
1175 else
1176 {
csharptest74c5e0c2011-07-14 13:06:22 -05001177 buffer[position++] = ((byte) value);
1178 buffer[position++] = ((byte) (value >> 8));
1179 buffer[position++] = ((byte) (value >> 16));
1180 buffer[position++] = ((byte) (value >> 24));
1181 buffer[position++] = ((byte) (value >> 32));
1182 buffer[position++] = ((byte) (value >> 40));
1183 buffer[position++] = ((byte) (value >> 48));
1184 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001185 }
csharptest71f662c2011-05-20 15:15:34 -05001186 }
1187
1188 public void WriteRawByte(byte value)
1189 {
1190 if (position == limit)
1191 {
1192 RefreshBuffer();
1193 }
1194
1195 buffer[position++] = value;
1196 }
1197
1198 [CLSCompliant(false)]
1199 public void WriteRawByte(uint value)
1200 {
1201 WriteRawByte((byte) value);
1202 }
1203
1204 /// <summary>
1205 /// Writes out an array of bytes.
1206 /// </summary>
1207 public void WriteRawBytes(byte[] value)
1208 {
1209 WriteRawBytes(value, 0, value.Length);
1210 }
1211
1212 /// <summary>
1213 /// Writes out part of an array of bytes.
1214 /// </summary>
1215 public void WriteRawBytes(byte[] value, int offset, int length)
1216 {
1217 if (limit - position >= length)
1218 {
csharptestaef072a2011-06-08 18:00:43 -05001219 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001220 // We have room in the current buffer.
1221 position += length;
1222 }
1223 else
1224 {
1225 // Write extends past current buffer. Fill the rest of this buffer and
1226 // flush.
1227 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001228 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001229 offset += bytesWritten;
1230 length -= bytesWritten;
1231 position = limit;
1232 RefreshBuffer();
1233
1234 // Now deal with the rest.
1235 // Since we have an output stream, this is our buffer
1236 // and buffer offset == 0
1237 if (length <= limit)
1238 {
1239 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001240 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001241 position = length;
1242 }
1243 else
1244 {
1245 // Write is very big. Let's do it all at once.
1246 output.Write(value, offset, length);
1247 }
1248 }
1249 }
1250
1251 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001252
csharptest71f662c2011-05-20 15:15:34 -05001253 /// <summary>
1254 /// Encode a 32-bit value with ZigZag encoding.
1255 /// </summary>
1256 /// <remarks>
1257 /// ZigZag encodes signed integers into values that can be efficiently
1258 /// encoded with varint. (Otherwise, negative values must be
1259 /// sign-extended to 64 bits to be varint encoded, thus always taking
1260 /// 10 bytes on the wire.)
1261 /// </remarks>
1262 [CLSCompliant(false)]
1263 public static uint EncodeZigZag32(int n)
1264 {
1265 // Note: the right-shift must be arithmetic
1266 return (uint) ((n << 1) ^ (n >> 31));
1267 }
1268
1269 /// <summary>
1270 /// Encode a 64-bit value with ZigZag encoding.
1271 /// </summary>
1272 /// <remarks>
1273 /// ZigZag encodes signed integers into values that can be efficiently
1274 /// encoded with varint. (Otherwise, negative values must be
1275 /// sign-extended to 64 bits to be varint encoded, thus always taking
1276 /// 10 bytes on the wire.)
1277 /// </remarks>
1278 [CLSCompliant(false)]
1279 public static ulong EncodeZigZag64(long n)
1280 {
1281 return (ulong) ((n << 1) ^ (n >> 63));
1282 }
1283
1284 private void RefreshBuffer()
1285 {
1286 if (output == null)
1287 {
1288 // We're writing to a single buffer.
1289 throw new OutOfSpaceException();
1290 }
1291
1292 // Since we have an output stream, this is our buffer
1293 // and buffer offset == 0
1294 output.Write(buffer, 0, position);
1295 position = 0;
1296 }
1297
1298 /// <summary>
1299 /// Indicates that a CodedOutputStream wrapping a flat byte array
1300 /// ran out of space.
1301 /// </summary>
1302 public sealed class OutOfSpaceException : IOException
1303 {
1304 internal OutOfSpaceException()
1305 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1306 {
1307 }
1308 }
1309
1310 public void Flush()
1311 {
1312 if (output != null)
1313 {
1314 RefreshBuffer();
1315 }
1316 }
1317
1318 /// <summary>
1319 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1320 /// that is exactly big enough to hold a message, then write to it with
1321 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1322 /// the message was actually as big as expected, which can help bugs.
1323 /// </summary>
1324 public void CheckNoSpaceLeft()
1325 {
1326 if (SpaceLeft != 0)
1327 {
1328 throw new InvalidOperationException("Did not write as much data as expected.");
1329 }
1330 }
1331
1332 /// <summary>
1333 /// If writing to a flat array, returns the space left in the array. Otherwise,
1334 /// throws an InvalidOperationException.
1335 /// </summary>
1336 public int SpaceLeft
1337 {
1338 get
1339 {
1340 if (output == null)
1341 {
1342 return limit - position;
1343 }
1344 else
1345 {
1346 throw new InvalidOperationException(
1347 "SpaceLeft can only be called on CodedOutputStreams that are " +
1348 "writing to a flat array.");
1349 }
1350 }
1351 }
1352 }
1353}