blob: c14f5e0d44513b23c674e631a5513dff33f490db [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>
csharptestcc8d2aa2011-06-03 12:15:42 -050060 public sealed partial class CodedOutputStream : ICodedOutputStream
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
128
csharptest2b868842011-06-10 14:41:47 -0500129 #region Writing of unknown fields
130
131 [Obsolete]
132 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
133 {
134 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
135 value.WriteTo(this);
136 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
137 }
138
139 public void WriteUnknownBytes(int fieldNumber, ByteString value)
140 {
141 WriteBytes(fieldNumber, null /*not used*/, value);
142 }
143
144 [CLSCompliant(false)]
145 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
146 {
csharptest74c5e0c2011-07-14 13:06:22 -0500147 if (wireType == WireFormat.WireType.Varint)
148 {
csharptest2b868842011-06-10 14:41:47 -0500149 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500150 }
csharptest2b868842011-06-10 14:41:47 -0500151 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500152 {
153 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
154 }
csharptest2b868842011-06-10 14:41:47 -0500155 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500156 {
csharptest2b868842011-06-10 14:41:47 -0500157 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500158 }
csharptest2b868842011-06-10 14:41:47 -0500159 else
csharptest74c5e0c2011-07-14 13:06:22 -0500160 {
csharptest2b868842011-06-10 14:41:47 -0500161 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500162 }
csharptest2b868842011-06-10 14:41:47 -0500163 }
164
165 #endregion
166
csharptestb00ea132011-06-10 01:09:57 -0500167 #region Writing of tags and fields
168
169 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
170 {
171 switch (fieldType)
172 {
173 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500174 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500175 break;
176 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500177 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500178 break;
179 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500180 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500181 break;
182 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500183 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500184 break;
185 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500186 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500187 break;
188 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500189 if (value is Enum)
190 {
191 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
192 }
csharptestb00ea132011-06-10 01:09:57 -0500193 else
csharptest74c5e0c2011-07-14 13:06:22 -0500194 {
195 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
196 }
csharptestb00ea132011-06-10 01:09:57 -0500197 break;
198 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500199 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500200 break;
201 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500202 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500203 break;
204 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500205 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500206 break;
207 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500208 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500209 break;
210 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500211 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500212 break;
213 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500214 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500215 break;
216 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500217 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500218 break;
219 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500220 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500221 break;
222 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500223 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500224 break;
225 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500226 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500227 break;
228 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500229 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500230 break;
231 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500232 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500233 break;
234 }
235 }
csharptest71f662c2011-05-20 15:15:34 -0500236
237 /// <summary>
238 /// Writes a double field value, including tag, to the stream.
239 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500240 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500241 {
242 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
243 WriteDoubleNoTag(value);
244 }
245
246 /// <summary>
247 /// Writes a float field value, including tag, to the stream.
248 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500249 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500250 {
251 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
252 WriteFloatNoTag(value);
253 }
254
255 /// <summary>
256 /// Writes a uint64 field value, including tag, to the stream.
257 /// </summary>
258 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500259 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500260 {
261 WriteTag(fieldNumber, WireFormat.WireType.Varint);
262 WriteRawVarint64(value);
263 }
264
265 /// <summary>
266 /// Writes an int64 field value, including tag, to the stream.
267 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500268 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500269 {
270 WriteTag(fieldNumber, WireFormat.WireType.Varint);
271 WriteRawVarint64((ulong) value);
272 }
273
274 /// <summary>
275 /// Writes an int32 field value, including tag, to the stream.
276 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500277 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500278 {
279 WriteTag(fieldNumber, WireFormat.WireType.Varint);
280 if (value >= 0)
281 {
282 WriteRawVarint32((uint) value);
283 }
284 else
285 {
286 // Must sign-extend.
287 WriteRawVarint64((ulong) value);
288 }
289 }
290
291 /// <summary>
292 /// Writes a fixed64 field value, including tag, to the stream.
293 /// </summary>
294 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500295 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500296 {
297 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
298 WriteRawLittleEndian64(value);
299 }
300
301 /// <summary>
302 /// Writes a fixed32 field value, including tag, to the stream.
303 /// </summary>
304 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500305 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500306 {
307 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
308 WriteRawLittleEndian32(value);
309 }
310
311 /// <summary>
312 /// Writes a bool field value, including tag, to the stream.
313 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500314 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500315 {
316 WriteTag(fieldNumber, WireFormat.WireType.Varint);
317 WriteRawByte(value ? (byte) 1 : (byte) 0);
318 }
319
320 /// <summary>
321 /// Writes a string field value, including tag, to the stream.
322 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500323 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500324 {
325 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
326 // Optimise the case where we have enough space to write
327 // the string directly to the buffer, which should be common.
328 int length = Encoding.UTF8.GetByteCount(value);
329 WriteRawVarint32((uint) length);
330 if (limit - position >= length)
331 {
332 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
333 position += length;
334 }
335 else
336 {
337 byte[] bytes = Encoding.UTF8.GetBytes(value);
338 WriteRawBytes(bytes);
339 }
340 }
341
342 /// <summary>
343 /// Writes a group field value, including tag, to the stream.
344 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500345 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500346 {
347 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
348 value.WriteTo(this);
349 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
350 }
351
csharptest90922db2011-06-03 11:57:47 -0500352 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500353 {
354 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
355 WriteRawVarint32((uint) value.SerializedSize);
356 value.WriteTo(this);
357 }
358
csharptest90922db2011-06-03 11:57:47 -0500359 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500360 {
csharptest71f662c2011-05-20 15:15:34 -0500361 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500362 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500363 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500364 }
365
366 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500367 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500368 {
369 WriteTag(fieldNumber, WireFormat.WireType.Varint);
370 WriteRawVarint32(value);
371 }
372
csharptest304ff3a2011-08-05 16:51:49 -0500373 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500374 {
375 WriteTag(fieldNumber, WireFormat.WireType.Varint);
376 WriteRawVarint32((uint) value);
377 }
378
csharptest90922db2011-06-03 11:57:47 -0500379 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500380 {
381 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
382 WriteRawLittleEndian32((uint) value);
383 }
384
csharptest90922db2011-06-03 11:57:47 -0500385 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500386 {
387 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
388 WriteRawLittleEndian64((ulong) value);
389 }
390
csharptest90922db2011-06-03 11:57:47 -0500391 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500392 {
393 WriteTag(fieldNumber, WireFormat.WireType.Varint);
394 WriteRawVarint32(EncodeZigZag32(value));
395 }
396
csharptest90922db2011-06-03 11:57:47 -0500397 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500398 {
399 WriteTag(fieldNumber, WireFormat.WireType.Varint);
400 WriteRawVarint64(EncodeZigZag64(value));
401 }
402
csharptest90922db2011-06-03 11:57:47 -0500403 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500404 {
405 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500406 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
407 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500408 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
409 }
410
csharptestffafdaa2011-06-03 12:58:14 -0500411 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500412 {
413 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500414 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
415 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500416 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
417 }
csharptest90922db2011-06-03 11:57:47 -0500418
csharptestb00ea132011-06-10 01:09:57 -0500419 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500420
csharptestb00ea132011-06-10 01:09:57 -0500421 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500422
423 public void WriteFieldNoTag(FieldType fieldType, object value)
424 {
425 switch (fieldType)
426 {
csharptestc671a4b2011-06-08 11:51:24 -0500427 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500428 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500429 break;
csharptestc671a4b2011-06-08 11:51:24 -0500430 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500431 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500432 break;
csharptestc671a4b2011-06-08 11:51:24 -0500433 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500434 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500435 break;
csharptestc671a4b2011-06-08 11:51:24 -0500436 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500437 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500438 break;
439 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500440 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500441 break;
442 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500443 if (value is Enum)
444 {
445 WriteEnumNoTag((int) value);
446 }
csharptestc671a4b2011-06-08 11:51:24 -0500447 else
csharptest74c5e0c2011-07-14 13:06:22 -0500448 {
449 WriteEnumNoTag(((IEnumLite) value).Number);
450 }
csharptest71f662c2011-05-20 15:15:34 -0500451 break;
452 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500453 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500454 break;
csharptestc671a4b2011-06-08 11:51:24 -0500455 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500456 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500457 break;
458 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500459 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500460 break;
csharptestc671a4b2011-06-08 11:51:24 -0500461 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500462 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500463 break;
464 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500465 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500466 break;
467 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500468 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500469 break;
csharptestc671a4b2011-06-08 11:51:24 -0500470 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500471 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500472 break;
473 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500474 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500475 break;
476 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500477 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500478 break;
479 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500480 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500481 break;
482 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500483 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500484 break;
485 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500486 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500487 break;
488 }
489 }
490
csharptest71f662c2011-05-20 15:15:34 -0500491 /// <summary>
492 /// Writes a double field value, including tag, to the stream.
493 /// </summary>
494 public void WriteDoubleNoTag(double value)
495 {
csharptest71f662c2011-05-20 15:15:34 -0500496#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500497 byte[] rawBytes = BitConverter.GetBytes(value);
498 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500499 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500500
501 if (limit - position >= 8)
502 {
503 buffer[position++] = rawBytes[0];
504 buffer[position++] = rawBytes[1];
505 buffer[position++] = rawBytes[2];
506 buffer[position++] = rawBytes[3];
507 buffer[position++] = rawBytes[4];
508 buffer[position++] = rawBytes[5];
509 buffer[position++] = rawBytes[6];
510 buffer[position++] = rawBytes[7];
511 }
512 else
513 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500514#else
csharptest74c5e0c2011-07-14 13:06:22 -0500515 WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500516#endif
517 }
518
519 /// <summary>
520 /// Writes a float field value, without a tag, to the stream.
521 /// </summary>
522 public void WriteFloatNoTag(float value)
523 {
csharptest71f662c2011-05-20 15:15:34 -0500524 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500525 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500526 {
csharptestaef072a2011-06-08 18:00:43 -0500527 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500528 }
csharptest2772dfe2011-06-08 15:50:58 -0500529
530 if (limit - position >= 4)
531 {
532 buffer[position++] = rawBytes[0];
533 buffer[position++] = rawBytes[1];
534 buffer[position++] = rawBytes[2];
535 buffer[position++] = rawBytes[3];
536 }
537 else
csharptest74c5e0c2011-07-14 13:06:22 -0500538 {
csharptest2772dfe2011-06-08 15:50:58 -0500539 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500540 }
csharptest71f662c2011-05-20 15:15:34 -0500541 }
542
543 /// <summary>
544 /// Writes a uint64 field value, without a tag, to the stream.
545 /// </summary>
546 [CLSCompliant(false)]
547 public void WriteUInt64NoTag(ulong value)
548 {
549 WriteRawVarint64(value);
550 }
551
552 /// <summary>
553 /// Writes an int64 field value, without a tag, to the stream.
554 /// </summary>
555 public void WriteInt64NoTag(long value)
556 {
csharptest74c5e0c2011-07-14 13:06:22 -0500557 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500558 }
559
560 /// <summary>
561 /// Writes an int32 field value, without a tag, to the stream.
562 /// </summary>
563 public void WriteInt32NoTag(int value)
564 {
565 if (value >= 0)
566 {
csharptest74c5e0c2011-07-14 13:06:22 -0500567 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500568 }
569 else
570 {
571 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500572 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500573 }
574 }
575
576 /// <summary>
577 /// Writes a fixed64 field value, without a tag, to the stream.
578 /// </summary>
579 [CLSCompliant(false)]
580 public void WriteFixed64NoTag(ulong value)
581 {
582 WriteRawLittleEndian64(value);
583 }
584
585 /// <summary>
586 /// Writes a fixed32 field value, without a tag, to the stream.
587 /// </summary>
588 [CLSCompliant(false)]
589 public void WriteFixed32NoTag(uint value)
590 {
591 WriteRawLittleEndian32(value);
592 }
593
594 /// <summary>
595 /// Writes a bool field value, without a tag, to the stream.
596 /// </summary>
597 public void WriteBoolNoTag(bool value)
598 {
csharptest74c5e0c2011-07-14 13:06:22 -0500599 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500600 }
601
602 /// <summary>
603 /// Writes a string field value, without a tag, to the stream.
604 /// </summary>
605 public void WriteStringNoTag(string value)
606 {
607 // Optimise the case where we have enough space to write
608 // the string directly to the buffer, which should be common.
609 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500610 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500611 if (limit - position >= length)
612 {
613 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
614 position += length;
615 }
616 else
617 {
618 byte[] bytes = Encoding.UTF8.GetBytes(value);
619 WriteRawBytes(bytes);
620 }
621 }
622
623 /// <summary>
624 /// Writes a group field value, without a tag, to the stream.
625 /// </summary>
626 public void WriteGroupNoTag(IMessageLite value)
627 {
628 value.WriteTo(this);
629 }
630
631 public void WriteMessageNoTag(IMessageLite value)
632 {
csharptest74c5e0c2011-07-14 13:06:22 -0500633 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500634 value.WriteTo(this);
635 }
636
637 public void WriteBytesNoTag(ByteString value)
638 {
csharptest74c5e0c2011-07-14 13:06:22 -0500639 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500640 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500641 }
642
643 [CLSCompliant(false)]
644 public void WriteUInt32NoTag(uint value)
645 {
646 WriteRawVarint32(value);
647 }
648
649 public void WriteEnumNoTag(int value)
650 {
csharptest74c5e0c2011-07-14 13:06:22 -0500651 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500652 }
653
654 public void WriteSFixed32NoTag(int value)
655 {
csharptest74c5e0c2011-07-14 13:06:22 -0500656 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500657 }
658
659 public void WriteSFixed64NoTag(long value)
660 {
csharptest74c5e0c2011-07-14 13:06:22 -0500661 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500662 }
663
664 public void WriteSInt32NoTag(int value)
665 {
666 WriteRawVarint32(EncodeZigZag32(value));
667 }
668
669 public void WriteSInt64NoTag(long value)
670 {
671 WriteRawVarint64(EncodeZigZag64(value));
672 }
673
674 #endregion
675
csharptestb00ea132011-06-10 01:09:57 -0500676 #region Write array members
677
csharptest74c5e0c2011-07-14 13:06:22 -0500678 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500679 {
680 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500681 {
csharptestb00ea132011-06-10 01:09:57 -0500682 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500683 }
csharptestb00ea132011-06-10 01:09:57 -0500684 }
685
686 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
687 where T : IMessageLite
688 {
689 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500690 {
csharptestb00ea132011-06-10 01:09:57 -0500691 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500692 }
csharptestb00ea132011-06-10 01:09:57 -0500693 }
694
695 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
696 where T : IMessageLite
697 {
698 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500699 {
csharptestb00ea132011-06-10 01:09:57 -0500700 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500701 }
csharptestb00ea132011-06-10 01:09:57 -0500702 }
703
704 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
705 {
706 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500707 {
csharptestb00ea132011-06-10 01:09:57 -0500708 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500709 }
csharptestb00ea132011-06-10 01:09:57 -0500710 }
711
712 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
713 {
714 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500715 {
csharptestb00ea132011-06-10 01:09:57 -0500716 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500717 }
csharptestb00ea132011-06-10 01:09:57 -0500718 }
719
720 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
721 {
722 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500723 {
csharptestb00ea132011-06-10 01:09:57 -0500724 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500725 }
csharptestb00ea132011-06-10 01:09:57 -0500726 }
727
728 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
729 {
730 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500731 {
csharptestb00ea132011-06-10 01:09:57 -0500732 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500733 }
csharptestb00ea132011-06-10 01:09:57 -0500734 }
735
736 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
737 {
738 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500739 {
csharptestb00ea132011-06-10 01:09:57 -0500740 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500741 }
csharptestb00ea132011-06-10 01:09:57 -0500742 }
743
744 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
745 {
746 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500747 {
csharptestb00ea132011-06-10 01:09:57 -0500748 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500749 }
csharptestb00ea132011-06-10 01:09:57 -0500750 }
751
752 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
753 {
754 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500755 {
csharptestb00ea132011-06-10 01:09:57 -0500756 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500757 }
csharptestb00ea132011-06-10 01:09:57 -0500758 }
759
760 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
761 {
762 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500763 {
csharptestb00ea132011-06-10 01:09:57 -0500764 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500765 }
csharptestb00ea132011-06-10 01:09:57 -0500766 }
767
768 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
769 {
770 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500771 {
csharptestb00ea132011-06-10 01:09:57 -0500772 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500773 }
csharptestb00ea132011-06-10 01:09:57 -0500774 }
775
776 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
777 {
778 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500779 {
csharptestb00ea132011-06-10 01:09:57 -0500780 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500781 }
csharptestb00ea132011-06-10 01:09:57 -0500782 }
783
784 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
785 {
786 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500787 {
csharptestb00ea132011-06-10 01:09:57 -0500788 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500789 }
csharptestb00ea132011-06-10 01:09:57 -0500790 }
791
792 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
793 {
794 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500795 {
csharptestb00ea132011-06-10 01:09:57 -0500796 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500797 }
csharptestb00ea132011-06-10 01:09:57 -0500798 }
799
800 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
801 {
802 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500803 {
csharptestb00ea132011-06-10 01:09:57 -0500804 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500805 }
csharptestb00ea132011-06-10 01:09:57 -0500806 }
807
808 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
809 {
810 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500811 {
csharptestb00ea132011-06-10 01:09:57 -0500812 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500813 }
csharptestb00ea132011-06-10 01:09:57 -0500814 }
815
816 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
817 {
818 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500819 {
csharptestb00ea132011-06-10 01:09:57 -0500820 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500821 }
csharptestb00ea132011-06-10 01:09:57 -0500822 }
823
824 [CLSCompliant(false)]
825 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
826 where T : struct, IComparable, IFormattable, IConvertible
827 {
828 if (list is ICastArray)
829 {
csharptest74c5e0c2011-07-14 13:06:22 -0500830 foreach (int value in ((ICastArray) list).CastArray<int>())
831 {
csharptestb00ea132011-06-10 01:09:57 -0500832 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500833 }
csharptestb00ea132011-06-10 01:09:57 -0500834 }
835 else
836 {
837 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500838 {
csharptestb00ea132011-06-10 01:09:57 -0500839 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500840 }
csharptestb00ea132011-06-10 01:09:57 -0500841 }
842 }
843
844 #endregion
845
846 #region Write packed array members
847
csharptest74c5e0c2011-07-14 13:06:22 -0500848 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500849 {
850 int calculatedSize = 0;
851 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500852 {
853 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
854 }
csharptestb00ea132011-06-10 01:09:57 -0500855
856 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500857 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500858
859 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500860 {
csharptestb00ea132011-06-10 01:09:57 -0500861 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500862 }
csharptestb00ea132011-06-10 01:09:57 -0500863 }
864
865 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
866 where T : IMessageLite
867 {
868 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500869 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500870 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500871 {
csharptestb00ea132011-06-10 01:09:57 -0500872 WriteGroupNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500873 }
csharptestb00ea132011-06-10 01:09:57 -0500874 }
875
csharptest74c5e0c2011-07-14 13:06:22 -0500876 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
877 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500878 where T : IMessageLite
879 {
880 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500881 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500882 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500883 {
csharptestb00ea132011-06-10 01:09:57 -0500884 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500885 }
csharptestb00ea132011-06-10 01:09:57 -0500886 }
887
csharptest74c5e0c2011-07-14 13:06:22 -0500888 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
889 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500890 {
891 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500892 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500893 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500894 {
csharptestb00ea132011-06-10 01:09:57 -0500895 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500896 }
csharptestb00ea132011-06-10 01:09:57 -0500897 }
898
csharptest74c5e0c2011-07-14 13:06:22 -0500899 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
900 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500901 {
902 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500903 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500904 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500905 {
csharptestb00ea132011-06-10 01:09:57 -0500906 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500907 }
csharptestb00ea132011-06-10 01:09:57 -0500908 }
909
910 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
911 {
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 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500917 }
csharptestb00ea132011-06-10 01:09:57 -0500918 }
919
920 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> 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 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500927 }
csharptestb00ea132011-06-10 01:09:57 -0500928 }
929
930 public void WritePackedSInt32Array(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 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500937 }
csharptestb00ea132011-06-10 01:09:57 -0500938 }
939
940 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> 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 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500947 }
csharptestb00ea132011-06-10 01:09:57 -0500948 }
949
csharptest74c5e0c2011-07-14 13:06:22 -0500950 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
951 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500952 {
953 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500954 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500955 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500956 {
csharptestb00ea132011-06-10 01:09:57 -0500957 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500958 }
csharptestb00ea132011-06-10 01:09:57 -0500959 }
960
csharptest74c5e0c2011-07-14 13:06:22 -0500961 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
962 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500963 {
964 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500965 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500966 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500967 {
csharptestb00ea132011-06-10 01:09:57 -0500968 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500969 }
csharptestb00ea132011-06-10 01:09:57 -0500970 }
971
972 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
973 {
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 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500979 }
csharptestb00ea132011-06-10 01:09:57 -0500980 }
981
982 public void WritePackedSInt64Array(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 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500989 }
csharptestb00ea132011-06-10 01:09:57 -0500990 }
991
csharptest74c5e0c2011-07-14 13:06:22 -0500992 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
993 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -0500994 {
995 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500996 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500997 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500998 {
csharptestb00ea132011-06-10 01:09:57 -0500999 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001000 }
csharptestb00ea132011-06-10 01:09:57 -05001001 }
1002
csharptest74c5e0c2011-07-14 13:06:22 -05001003 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1004 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001005 {
1006 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001007 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001008 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001009 {
csharptestb00ea132011-06-10 01:09:57 -05001010 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001011 }
csharptestb00ea132011-06-10 01:09:57 -05001012 }
1013
csharptest74c5e0c2011-07-14 13:06:22 -05001014 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1015 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001016 {
1017 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001018 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001019 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001020 {
csharptestb00ea132011-06-10 01:09:57 -05001021 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001022 }
csharptestb00ea132011-06-10 01:09:57 -05001023 }
1024
csharptest74c5e0c2011-07-14 13:06:22 -05001025 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1026 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001027 {
1028 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001029 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001030 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001031 {
csharptestb00ea132011-06-10 01:09:57 -05001032 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001033 }
csharptestb00ea132011-06-10 01:09:57 -05001034 }
1035
1036 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1037 {
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 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001043 }
csharptestb00ea132011-06-10 01:09:57 -05001044 }
1045
1046 [CLSCompliant(false)]
1047 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1048 where T : struct, IComparable, IFormattable, IConvertible
1049 {
1050 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001051 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001052 if (list is ICastArray)
1053 {
csharptest74c5e0c2011-07-14 13:06:22 -05001054 foreach (int value in ((ICastArray) list).CastArray<int>())
1055 {
csharptestb00ea132011-06-10 01:09:57 -05001056 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001057 }
csharptestb00ea132011-06-10 01:09:57 -05001058 }
1059 else
1060 {
1061 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001062 {
1063 WriteEnumNoTag((int) value);
1064 }
csharptestb00ea132011-06-10 01:09:57 -05001065 }
1066 }
1067
1068 #endregion
1069
csharptest71f662c2011-05-20 15:15:34 -05001070 #region Underlying writing primitives
1071
1072 /// <summary>
1073 /// Encodes and writes a tag.
1074 /// </summary>
1075 [CLSCompliant(false)]
1076 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1077 {
1078 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1079 }
1080
csharptest71f662c2011-05-20 15:15:34 -05001081 /// <summary>
1082 /// Writes a 32 bit value as a varint. The fast route is taken when
1083 /// there's enough buffer space left to whizz through without checking
1084 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1085 /// </summary>
1086 [CLSCompliant(false)]
1087 public void WriteRawVarint32(uint value)
1088 {
csharptestc671a4b2011-06-08 11:51:24 -05001089 while (value > 127 && position < limit)
1090 {
csharptest74c5e0c2011-07-14 13:06:22 -05001091 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001092 value >>= 7;
1093 }
1094 while (value > 127)
1095 {
csharptest74c5e0c2011-07-14 13:06:22 -05001096 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001097 value >>= 7;
1098 }
csharptest74c5e0c2011-07-14 13:06:22 -05001099 if (position < limit)
1100 {
1101 buffer[position++] = (byte) value;
1102 }
csharptestc671a4b2011-06-08 11:51:24 -05001103 else
csharptest74c5e0c2011-07-14 13:06:22 -05001104 {
1105 WriteRawByte((byte) value);
1106 }
csharptest71f662c2011-05-20 15:15:34 -05001107 }
1108
1109 [CLSCompliant(false)]
1110 public void WriteRawVarint64(ulong value)
1111 {
csharptestc671a4b2011-06-08 11:51:24 -05001112 while (value > 127 && position < limit)
1113 {
csharptest74c5e0c2011-07-14 13:06:22 -05001114 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001115 value >>= 7;
1116 }
1117 while (value > 127)
1118 {
csharptest74c5e0c2011-07-14 13:06:22 -05001119 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001120 value >>= 7;
1121 }
csharptest74c5e0c2011-07-14 13:06:22 -05001122 if (position < limit)
1123 {
1124 buffer[position++] = (byte) value;
1125 }
csharptestc671a4b2011-06-08 11:51:24 -05001126 else
csharptest74c5e0c2011-07-14 13:06:22 -05001127 {
1128 WriteRawByte((byte) value);
1129 }
csharptest71f662c2011-05-20 15:15:34 -05001130 }
1131
1132 [CLSCompliant(false)]
1133 public void WriteRawLittleEndian32(uint value)
1134 {
csharptestc671a4b2011-06-08 11:51:24 -05001135 if (position + 4 > limit)
1136 {
1137 WriteRawByte((byte) value);
1138 WriteRawByte((byte) (value >> 8));
1139 WriteRawByte((byte) (value >> 16));
1140 WriteRawByte((byte) (value >> 24));
1141 }
1142 else
1143 {
csharptest74c5e0c2011-07-14 13:06:22 -05001144 buffer[position++] = ((byte) value);
1145 buffer[position++] = ((byte) (value >> 8));
1146 buffer[position++] = ((byte) (value >> 16));
1147 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001148 }
csharptest71f662c2011-05-20 15:15:34 -05001149 }
1150
1151 [CLSCompliant(false)]
1152 public void WriteRawLittleEndian64(ulong value)
1153 {
csharptestc671a4b2011-06-08 11:51:24 -05001154 if (position + 8 > limit)
1155 {
1156 WriteRawByte((byte) value);
1157 WriteRawByte((byte) (value >> 8));
1158 WriteRawByte((byte) (value >> 16));
1159 WriteRawByte((byte) (value >> 24));
1160 WriteRawByte((byte) (value >> 32));
1161 WriteRawByte((byte) (value >> 40));
1162 WriteRawByte((byte) (value >> 48));
1163 WriteRawByte((byte) (value >> 56));
1164 }
1165 else
1166 {
csharptest74c5e0c2011-07-14 13:06:22 -05001167 buffer[position++] = ((byte) value);
1168 buffer[position++] = ((byte) (value >> 8));
1169 buffer[position++] = ((byte) (value >> 16));
1170 buffer[position++] = ((byte) (value >> 24));
1171 buffer[position++] = ((byte) (value >> 32));
1172 buffer[position++] = ((byte) (value >> 40));
1173 buffer[position++] = ((byte) (value >> 48));
1174 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001175 }
csharptest71f662c2011-05-20 15:15:34 -05001176 }
1177
1178 public void WriteRawByte(byte value)
1179 {
1180 if (position == limit)
1181 {
1182 RefreshBuffer();
1183 }
1184
1185 buffer[position++] = value;
1186 }
1187
1188 [CLSCompliant(false)]
1189 public void WriteRawByte(uint value)
1190 {
1191 WriteRawByte((byte) value);
1192 }
1193
1194 /// <summary>
1195 /// Writes out an array of bytes.
1196 /// </summary>
1197 public void WriteRawBytes(byte[] value)
1198 {
1199 WriteRawBytes(value, 0, value.Length);
1200 }
1201
1202 /// <summary>
1203 /// Writes out part of an array of bytes.
1204 /// </summary>
1205 public void WriteRawBytes(byte[] value, int offset, int length)
1206 {
1207 if (limit - position >= length)
1208 {
csharptestaef072a2011-06-08 18:00:43 -05001209 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001210 // We have room in the current buffer.
1211 position += length;
1212 }
1213 else
1214 {
1215 // Write extends past current buffer. Fill the rest of this buffer and
1216 // flush.
1217 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001218 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001219 offset += bytesWritten;
1220 length -= bytesWritten;
1221 position = limit;
1222 RefreshBuffer();
1223
1224 // Now deal with the rest.
1225 // Since we have an output stream, this is our buffer
1226 // and buffer offset == 0
1227 if (length <= limit)
1228 {
1229 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001230 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001231 position = length;
1232 }
1233 else
1234 {
1235 // Write is very big. Let's do it all at once.
1236 output.Write(value, offset, length);
1237 }
1238 }
1239 }
1240
1241 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001242
csharptest71f662c2011-05-20 15:15:34 -05001243 /// <summary>
1244 /// Encode a 32-bit value with ZigZag encoding.
1245 /// </summary>
1246 /// <remarks>
1247 /// ZigZag encodes signed integers into values that can be efficiently
1248 /// encoded with varint. (Otherwise, negative values must be
1249 /// sign-extended to 64 bits to be varint encoded, thus always taking
1250 /// 10 bytes on the wire.)
1251 /// </remarks>
1252 [CLSCompliant(false)]
1253 public static uint EncodeZigZag32(int n)
1254 {
1255 // Note: the right-shift must be arithmetic
1256 return (uint) ((n << 1) ^ (n >> 31));
1257 }
1258
1259 /// <summary>
1260 /// Encode a 64-bit value with ZigZag encoding.
1261 /// </summary>
1262 /// <remarks>
1263 /// ZigZag encodes signed integers into values that can be efficiently
1264 /// encoded with varint. (Otherwise, negative values must be
1265 /// sign-extended to 64 bits to be varint encoded, thus always taking
1266 /// 10 bytes on the wire.)
1267 /// </remarks>
1268 [CLSCompliant(false)]
1269 public static ulong EncodeZigZag64(long n)
1270 {
1271 return (ulong) ((n << 1) ^ (n >> 63));
1272 }
1273
1274 private void RefreshBuffer()
1275 {
1276 if (output == null)
1277 {
1278 // We're writing to a single buffer.
1279 throw new OutOfSpaceException();
1280 }
1281
1282 // Since we have an output stream, this is our buffer
1283 // and buffer offset == 0
1284 output.Write(buffer, 0, position);
1285 position = 0;
1286 }
1287
1288 /// <summary>
1289 /// Indicates that a CodedOutputStream wrapping a flat byte array
1290 /// ran out of space.
1291 /// </summary>
1292 public sealed class OutOfSpaceException : IOException
1293 {
1294 internal OutOfSpaceException()
1295 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1296 {
1297 }
1298 }
1299
1300 public void Flush()
1301 {
1302 if (output != null)
1303 {
1304 RefreshBuffer();
1305 }
1306 }
1307
1308 /// <summary>
1309 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1310 /// that is exactly big enough to hold a message, then write to it with
1311 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1312 /// the message was actually as big as expected, which can help bugs.
1313 /// </summary>
1314 public void CheckNoSpaceLeft()
1315 {
1316 if (SpaceLeft != 0)
1317 {
1318 throw new InvalidOperationException("Did not write as much data as expected.");
1319 }
1320 }
1321
1322 /// <summary>
1323 /// If writing to a flat array, returns the space left in the array. Otherwise,
1324 /// throws an InvalidOperationException.
1325 /// </summary>
1326 public int SpaceLeft
1327 {
1328 get
1329 {
1330 if (output == null)
1331 {
1332 return limit - position;
1333 }
1334 else
1335 {
1336 throw new InvalidOperationException(
1337 "SpaceLeft can only be called on CodedOutputStreams that are " +
1338 "writing to a flat array.");
1339 }
1340 }
1341 }
1342 }
1343}