blob: b9c7b58740937f3ac5bf8dabc374f8c5c1f6623b [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>
csharptest353b0fa2011-09-29 16:33:31 -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
csharptest819b7152011-09-08 20:28:22 -0500128
csharptest60fd7732011-09-09 12:18:16 -0500129 void ICodedOutputStream.WriteMessageStart() { }
130 void ICodedOutputStream.WriteMessageEnd() { Flush(); }
131
csharptest2b868842011-06-10 14:41:47 -0500132 #region Writing of unknown fields
133
134 [Obsolete]
135 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
136 {
137 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
138 value.WriteTo(this);
139 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
140 }
141
142 public void WriteUnknownBytes(int fieldNumber, ByteString value)
143 {
144 WriteBytes(fieldNumber, null /*not used*/, value);
145 }
146
147 [CLSCompliant(false)]
148 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
149 {
csharptest74c5e0c2011-07-14 13:06:22 -0500150 if (wireType == WireFormat.WireType.Varint)
151 {
csharptest2b868842011-06-10 14:41:47 -0500152 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500153 }
csharptest2b868842011-06-10 14:41:47 -0500154 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500155 {
156 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
157 }
csharptest2b868842011-06-10 14:41:47 -0500158 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500159 {
csharptest2b868842011-06-10 14:41:47 -0500160 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500161 }
csharptest2b868842011-06-10 14:41:47 -0500162 else
csharptest74c5e0c2011-07-14 13:06:22 -0500163 {
csharptest2b868842011-06-10 14:41:47 -0500164 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500165 }
csharptest2b868842011-06-10 14:41:47 -0500166 }
167
168 #endregion
169
csharptestb00ea132011-06-10 01:09:57 -0500170 #region Writing of tags and fields
171
172 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
173 {
174 switch (fieldType)
175 {
176 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500177 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500178 break;
179 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500180 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500181 break;
182 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500183 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500184 break;
185 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500186 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500187 break;
188 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500189 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500190 break;
191 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500192 if (value is Enum)
193 {
194 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
195 }
csharptestb00ea132011-06-10 01:09:57 -0500196 else
csharptest74c5e0c2011-07-14 13:06:22 -0500197 {
198 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
199 }
csharptestb00ea132011-06-10 01:09:57 -0500200 break;
201 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500202 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500203 break;
204 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500205 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500206 break;
207 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500208 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500209 break;
210 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500211 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500212 break;
213 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500214 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500215 break;
216 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500217 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500218 break;
219 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500220 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500221 break;
222 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500223 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500224 break;
225 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500226 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500227 break;
228 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500229 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500230 break;
231 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500232 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500233 break;
234 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500235 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500236 break;
237 }
238 }
csharptest71f662c2011-05-20 15:15:34 -0500239
240 /// <summary>
241 /// Writes a double field value, including tag, to the stream.
242 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500243 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500244 {
245 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
246 WriteDoubleNoTag(value);
247 }
248
249 /// <summary>
250 /// Writes a float field value, including tag, to the stream.
251 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500252 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500253 {
254 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
255 WriteFloatNoTag(value);
256 }
257
258 /// <summary>
259 /// Writes a uint64 field value, including tag, to the stream.
260 /// </summary>
261 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500262 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500263 {
264 WriteTag(fieldNumber, WireFormat.WireType.Varint);
265 WriteRawVarint64(value);
266 }
267
268 /// <summary>
269 /// Writes an int64 field value, including tag, to the stream.
270 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500271 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500272 {
273 WriteTag(fieldNumber, WireFormat.WireType.Varint);
274 WriteRawVarint64((ulong) value);
275 }
276
277 /// <summary>
278 /// Writes an int32 field value, including tag, to the stream.
279 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500280 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500281 {
282 WriteTag(fieldNumber, WireFormat.WireType.Varint);
283 if (value >= 0)
284 {
285 WriteRawVarint32((uint) value);
286 }
287 else
288 {
289 // Must sign-extend.
290 WriteRawVarint64((ulong) value);
291 }
292 }
293
294 /// <summary>
295 /// Writes a fixed64 field value, including tag, to the stream.
296 /// </summary>
297 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500298 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500299 {
300 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
301 WriteRawLittleEndian64(value);
302 }
303
304 /// <summary>
305 /// Writes a fixed32 field value, including tag, to the stream.
306 /// </summary>
307 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500308 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500309 {
310 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
311 WriteRawLittleEndian32(value);
312 }
313
314 /// <summary>
315 /// Writes a bool field value, including tag, to the stream.
316 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500317 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500318 {
319 WriteTag(fieldNumber, WireFormat.WireType.Varint);
320 WriteRawByte(value ? (byte) 1 : (byte) 0);
321 }
322
323 /// <summary>
324 /// Writes a string field value, including tag, to the stream.
325 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500326 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500327 {
328 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
329 // Optimise the case where we have enough space to write
330 // the string directly to the buffer, which should be common.
331 int length = Encoding.UTF8.GetByteCount(value);
332 WriteRawVarint32((uint) length);
333 if (limit - position >= length)
334 {
335 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
336 position += length;
337 }
338 else
339 {
340 byte[] bytes = Encoding.UTF8.GetBytes(value);
341 WriteRawBytes(bytes);
342 }
343 }
344
345 /// <summary>
346 /// Writes a group field value, including tag, to the stream.
347 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500348 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500349 {
350 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
351 value.WriteTo(this);
352 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
353 }
354
csharptest90922db2011-06-03 11:57:47 -0500355 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500356 {
357 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
358 WriteRawVarint32((uint) value.SerializedSize);
359 value.WriteTo(this);
360 }
361
csharptest90922db2011-06-03 11:57:47 -0500362 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500363 {
csharptest71f662c2011-05-20 15:15:34 -0500364 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500365 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500366 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500367 }
368
369 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500370 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500371 {
372 WriteTag(fieldNumber, WireFormat.WireType.Varint);
373 WriteRawVarint32(value);
374 }
375
csharptest304ff3a2011-08-05 16:51:49 -0500376 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500377 {
378 WriteTag(fieldNumber, WireFormat.WireType.Varint);
csharptesta105eac2011-09-09 13:39:54 -0500379 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500380 }
381
csharptest90922db2011-06-03 11:57:47 -0500382 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500383 {
384 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
385 WriteRawLittleEndian32((uint) value);
386 }
387
csharptest90922db2011-06-03 11:57:47 -0500388 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500389 {
390 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
391 WriteRawLittleEndian64((ulong) value);
392 }
393
csharptest90922db2011-06-03 11:57:47 -0500394 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500395 {
396 WriteTag(fieldNumber, WireFormat.WireType.Varint);
397 WriteRawVarint32(EncodeZigZag32(value));
398 }
399
csharptest90922db2011-06-03 11:57:47 -0500400 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500401 {
402 WriteTag(fieldNumber, WireFormat.WireType.Varint);
403 WriteRawVarint64(EncodeZigZag64(value));
404 }
405
csharptest90922db2011-06-03 11:57:47 -0500406 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500407 {
408 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500409 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
410 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500411 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
412 }
413
csharptestffafdaa2011-06-03 12:58:14 -0500414 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500415 {
416 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500417 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
418 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500419 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
420 }
csharptest90922db2011-06-03 11:57:47 -0500421
csharptestb00ea132011-06-10 01:09:57 -0500422 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500423
csharptestb00ea132011-06-10 01:09:57 -0500424 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500425
426 public void WriteFieldNoTag(FieldType fieldType, object value)
427 {
428 switch (fieldType)
429 {
csharptestc671a4b2011-06-08 11:51:24 -0500430 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500431 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500432 break;
csharptestc671a4b2011-06-08 11:51:24 -0500433 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500434 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500435 break;
csharptestc671a4b2011-06-08 11:51:24 -0500436 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500437 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500438 break;
csharptestc671a4b2011-06-08 11:51:24 -0500439 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500440 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500441 break;
442 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500443 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500444 break;
445 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500446 if (value is Enum)
447 {
448 WriteEnumNoTag((int) value);
449 }
csharptestc671a4b2011-06-08 11:51:24 -0500450 else
csharptest74c5e0c2011-07-14 13:06:22 -0500451 {
452 WriteEnumNoTag(((IEnumLite) value).Number);
453 }
csharptest71f662c2011-05-20 15:15:34 -0500454 break;
455 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500456 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500457 break;
csharptestc671a4b2011-06-08 11:51:24 -0500458 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500459 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500460 break;
461 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500462 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500463 break;
csharptestc671a4b2011-06-08 11:51:24 -0500464 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500465 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500466 break;
467 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500468 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500469 break;
470 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500471 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500472 break;
csharptestc671a4b2011-06-08 11:51:24 -0500473 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500474 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500475 break;
476 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500477 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500478 break;
479 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500480 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500481 break;
482 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500483 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500484 break;
485 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500486 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500487 break;
488 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500489 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500490 break;
491 }
492 }
493
csharptest71f662c2011-05-20 15:15:34 -0500494 /// <summary>
495 /// Writes a double field value, including tag, to the stream.
496 /// </summary>
497 public void WriteDoubleNoTag(double value)
498 {
csharptest71f662c2011-05-20 15:15:34 -0500499#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500500 byte[] rawBytes = BitConverter.GetBytes(value);
501 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500502 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500503
504 if (limit - position >= 8)
505 {
506 buffer[position++] = rawBytes[0];
507 buffer[position++] = rawBytes[1];
508 buffer[position++] = rawBytes[2];
509 buffer[position++] = rawBytes[3];
510 buffer[position++] = rawBytes[4];
511 buffer[position++] = rawBytes[5];
512 buffer[position++] = rawBytes[6];
513 buffer[position++] = rawBytes[7];
514 }
515 else
516 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500517#else
csharptest74c5e0c2011-07-14 13:06:22 -0500518 WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500519#endif
520 }
521
522 /// <summary>
523 /// Writes a float field value, without a tag, to the stream.
524 /// </summary>
525 public void WriteFloatNoTag(float value)
526 {
csharptest71f662c2011-05-20 15:15:34 -0500527 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500528 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500529 {
csharptestaef072a2011-06-08 18:00:43 -0500530 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500531 }
csharptest2772dfe2011-06-08 15:50:58 -0500532
533 if (limit - position >= 4)
534 {
535 buffer[position++] = rawBytes[0];
536 buffer[position++] = rawBytes[1];
537 buffer[position++] = rawBytes[2];
538 buffer[position++] = rawBytes[3];
539 }
540 else
csharptest74c5e0c2011-07-14 13:06:22 -0500541 {
csharptest2772dfe2011-06-08 15:50:58 -0500542 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500543 }
csharptest71f662c2011-05-20 15:15:34 -0500544 }
545
546 /// <summary>
547 /// Writes a uint64 field value, without a tag, to the stream.
548 /// </summary>
549 [CLSCompliant(false)]
550 public void WriteUInt64NoTag(ulong value)
551 {
552 WriteRawVarint64(value);
553 }
554
555 /// <summary>
556 /// Writes an int64 field value, without a tag, to the stream.
557 /// </summary>
558 public void WriteInt64NoTag(long value)
559 {
csharptest74c5e0c2011-07-14 13:06:22 -0500560 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500561 }
562
563 /// <summary>
564 /// Writes an int32 field value, without a tag, to the stream.
565 /// </summary>
566 public void WriteInt32NoTag(int value)
567 {
568 if (value >= 0)
569 {
csharptest74c5e0c2011-07-14 13:06:22 -0500570 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500571 }
572 else
573 {
574 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500575 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500576 }
577 }
578
579 /// <summary>
580 /// Writes a fixed64 field value, without a tag, to the stream.
581 /// </summary>
582 [CLSCompliant(false)]
583 public void WriteFixed64NoTag(ulong value)
584 {
585 WriteRawLittleEndian64(value);
586 }
587
588 /// <summary>
589 /// Writes a fixed32 field value, without a tag, to the stream.
590 /// </summary>
591 [CLSCompliant(false)]
592 public void WriteFixed32NoTag(uint value)
593 {
594 WriteRawLittleEndian32(value);
595 }
596
597 /// <summary>
598 /// Writes a bool field value, without a tag, to the stream.
599 /// </summary>
600 public void WriteBoolNoTag(bool value)
601 {
csharptest74c5e0c2011-07-14 13:06:22 -0500602 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500603 }
604
605 /// <summary>
606 /// Writes a string field value, without a tag, to the stream.
607 /// </summary>
608 public void WriteStringNoTag(string value)
609 {
610 // Optimise the case where we have enough space to write
611 // the string directly to the buffer, which should be common.
612 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500613 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500614 if (limit - position >= length)
615 {
616 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
617 position += length;
618 }
619 else
620 {
621 byte[] bytes = Encoding.UTF8.GetBytes(value);
622 WriteRawBytes(bytes);
623 }
624 }
625
626 /// <summary>
627 /// Writes a group field value, without a tag, to the stream.
628 /// </summary>
629 public void WriteGroupNoTag(IMessageLite value)
630 {
631 value.WriteTo(this);
632 }
633
634 public void WriteMessageNoTag(IMessageLite value)
635 {
csharptest74c5e0c2011-07-14 13:06:22 -0500636 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500637 value.WriteTo(this);
638 }
639
640 public void WriteBytesNoTag(ByteString value)
641 {
csharptest74c5e0c2011-07-14 13:06:22 -0500642 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500643 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500644 }
645
646 [CLSCompliant(false)]
647 public void WriteUInt32NoTag(uint value)
648 {
649 WriteRawVarint32(value);
650 }
651
652 public void WriteEnumNoTag(int value)
653 {
csharptesta105eac2011-09-09 13:39:54 -0500654 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500655 }
656
657 public void WriteSFixed32NoTag(int value)
658 {
csharptest74c5e0c2011-07-14 13:06:22 -0500659 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500660 }
661
662 public void WriteSFixed64NoTag(long value)
663 {
csharptest74c5e0c2011-07-14 13:06:22 -0500664 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500665 }
666
667 public void WriteSInt32NoTag(int value)
668 {
669 WriteRawVarint32(EncodeZigZag32(value));
670 }
671
672 public void WriteSInt64NoTag(long value)
673 {
674 WriteRawVarint64(EncodeZigZag64(value));
675 }
676
677 #endregion
678
csharptestb00ea132011-06-10 01:09:57 -0500679 #region Write array members
680
csharptest74c5e0c2011-07-14 13:06:22 -0500681 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500682 {
683 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500684 {
csharptestb00ea132011-06-10 01:09:57 -0500685 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500686 }
csharptestb00ea132011-06-10 01:09:57 -0500687 }
688
689 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
690 where T : IMessageLite
691 {
692 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500693 {
csharptestb00ea132011-06-10 01:09:57 -0500694 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500695 }
csharptestb00ea132011-06-10 01:09:57 -0500696 }
697
698 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
699 where T : IMessageLite
700 {
701 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500702 {
csharptestb00ea132011-06-10 01:09:57 -0500703 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500704 }
csharptestb00ea132011-06-10 01:09:57 -0500705 }
706
707 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
708 {
709 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500710 {
csharptestb00ea132011-06-10 01:09:57 -0500711 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500712 }
csharptestb00ea132011-06-10 01:09:57 -0500713 }
714
715 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
716 {
717 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500718 {
csharptestb00ea132011-06-10 01:09:57 -0500719 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500720 }
csharptestb00ea132011-06-10 01:09:57 -0500721 }
722
723 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
724 {
725 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500726 {
csharptestb00ea132011-06-10 01:09:57 -0500727 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500728 }
csharptestb00ea132011-06-10 01:09:57 -0500729 }
730
731 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
732 {
733 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500734 {
csharptestb00ea132011-06-10 01:09:57 -0500735 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500736 }
csharptestb00ea132011-06-10 01:09:57 -0500737 }
738
739 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
740 {
741 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500742 {
csharptestb00ea132011-06-10 01:09:57 -0500743 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500744 }
csharptestb00ea132011-06-10 01:09:57 -0500745 }
746
747 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
748 {
749 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500750 {
csharptestb00ea132011-06-10 01:09:57 -0500751 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500752 }
csharptestb00ea132011-06-10 01:09:57 -0500753 }
754
755 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
756 {
757 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500758 {
csharptestb00ea132011-06-10 01:09:57 -0500759 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500760 }
csharptestb00ea132011-06-10 01:09:57 -0500761 }
762
763 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
764 {
765 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500766 {
csharptestb00ea132011-06-10 01:09:57 -0500767 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500768 }
csharptestb00ea132011-06-10 01:09:57 -0500769 }
770
771 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
772 {
773 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500774 {
csharptestb00ea132011-06-10 01:09:57 -0500775 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500776 }
csharptestb00ea132011-06-10 01:09:57 -0500777 }
778
779 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
780 {
781 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500782 {
csharptestb00ea132011-06-10 01:09:57 -0500783 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500784 }
csharptestb00ea132011-06-10 01:09:57 -0500785 }
786
787 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
788 {
789 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500790 {
csharptestb00ea132011-06-10 01:09:57 -0500791 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500792 }
csharptestb00ea132011-06-10 01:09:57 -0500793 }
794
795 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
796 {
797 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500798 {
csharptestb00ea132011-06-10 01:09:57 -0500799 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500800 }
csharptestb00ea132011-06-10 01:09:57 -0500801 }
802
803 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
804 {
805 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500806 {
csharptestb00ea132011-06-10 01:09:57 -0500807 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500808 }
csharptestb00ea132011-06-10 01:09:57 -0500809 }
810
811 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
812 {
813 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500814 {
csharptestb00ea132011-06-10 01:09:57 -0500815 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500816 }
csharptestb00ea132011-06-10 01:09:57 -0500817 }
818
819 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
820 {
821 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500822 {
csharptestb00ea132011-06-10 01:09:57 -0500823 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500824 }
csharptestb00ea132011-06-10 01:09:57 -0500825 }
826
827 [CLSCompliant(false)]
828 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
829 where T : struct, IComparable, IFormattable, IConvertible
830 {
831 if (list is ICastArray)
832 {
csharptest74c5e0c2011-07-14 13:06:22 -0500833 foreach (int value in ((ICastArray) list).CastArray<int>())
834 {
csharptestb00ea132011-06-10 01:09:57 -0500835 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500836 }
csharptestb00ea132011-06-10 01:09:57 -0500837 }
838 else
839 {
840 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500841 {
csharptestb00ea132011-06-10 01:09:57 -0500842 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500843 }
csharptestb00ea132011-06-10 01:09:57 -0500844 }
845 }
846
847 #endregion
848
849 #region Write packed array members
850
csharptest74c5e0c2011-07-14 13:06:22 -0500851 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500852 {
853 int calculatedSize = 0;
854 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500855 {
856 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
857 }
csharptestb00ea132011-06-10 01:09:57 -0500858
859 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500860 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500861
862 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500863 {
csharptestb00ea132011-06-10 01:09:57 -0500864 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500865 }
csharptestb00ea132011-06-10 01:09:57 -0500866 }
867
868 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
869 where T : IMessageLite
870 {
871 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500872 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500873 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500874 {
csharptestb00ea132011-06-10 01:09:57 -0500875 WriteGroupNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500876 }
csharptestb00ea132011-06-10 01:09:57 -0500877 }
878
csharptest74c5e0c2011-07-14 13:06:22 -0500879 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
880 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500881 where T : IMessageLite
882 {
883 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500884 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500885 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500886 {
csharptestb00ea132011-06-10 01:09:57 -0500887 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500888 }
csharptestb00ea132011-06-10 01:09:57 -0500889 }
890
csharptest74c5e0c2011-07-14 13:06:22 -0500891 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
892 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500893 {
894 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500895 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500896 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500897 {
csharptestb00ea132011-06-10 01:09:57 -0500898 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500899 }
csharptestb00ea132011-06-10 01:09:57 -0500900 }
901
csharptest74c5e0c2011-07-14 13:06:22 -0500902 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
903 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500904 {
905 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500906 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500907 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500908 {
csharptestb00ea132011-06-10 01:09:57 -0500909 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500910 }
csharptestb00ea132011-06-10 01:09:57 -0500911 }
912
913 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
914 {
915 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500916 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500917 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500918 {
csharptestb00ea132011-06-10 01:09:57 -0500919 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500920 }
csharptestb00ea132011-06-10 01:09:57 -0500921 }
922
923 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
924 {
925 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500926 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500927 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500928 {
csharptestb00ea132011-06-10 01:09:57 -0500929 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500930 }
csharptestb00ea132011-06-10 01:09:57 -0500931 }
932
933 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
934 {
935 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500936 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500937 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500938 {
csharptestb00ea132011-06-10 01:09:57 -0500939 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500940 }
csharptestb00ea132011-06-10 01:09:57 -0500941 }
942
943 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
944 {
945 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500946 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500947 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500948 {
csharptestb00ea132011-06-10 01:09:57 -0500949 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500950 }
csharptestb00ea132011-06-10 01:09:57 -0500951 }
952
csharptest74c5e0c2011-07-14 13:06:22 -0500953 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
954 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500955 {
956 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500957 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500958 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500959 {
csharptestb00ea132011-06-10 01:09:57 -0500960 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500961 }
csharptestb00ea132011-06-10 01:09:57 -0500962 }
963
csharptest74c5e0c2011-07-14 13:06:22 -0500964 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
965 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500966 {
967 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500968 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500969 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500970 {
csharptestb00ea132011-06-10 01:09:57 -0500971 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500972 }
csharptestb00ea132011-06-10 01:09:57 -0500973 }
974
975 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
976 {
977 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500978 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500979 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500980 {
csharptestb00ea132011-06-10 01:09:57 -0500981 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500982 }
csharptestb00ea132011-06-10 01:09:57 -0500983 }
984
985 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
986 {
987 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500988 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500989 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500990 {
csharptestb00ea132011-06-10 01:09:57 -0500991 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500992 }
csharptestb00ea132011-06-10 01:09:57 -0500993 }
994
csharptest74c5e0c2011-07-14 13:06:22 -0500995 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
996 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -0500997 {
998 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500999 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001000 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001001 {
csharptestb00ea132011-06-10 01:09:57 -05001002 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001003 }
csharptestb00ea132011-06-10 01:09:57 -05001004 }
1005
csharptest74c5e0c2011-07-14 13:06:22 -05001006 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1007 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001008 {
1009 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001010 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001011 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001012 {
csharptestb00ea132011-06-10 01:09:57 -05001013 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001014 }
csharptestb00ea132011-06-10 01:09:57 -05001015 }
1016
csharptest74c5e0c2011-07-14 13:06:22 -05001017 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1018 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001019 {
1020 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001021 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001022 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001023 {
csharptestb00ea132011-06-10 01:09:57 -05001024 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001025 }
csharptestb00ea132011-06-10 01:09:57 -05001026 }
1027
csharptest74c5e0c2011-07-14 13:06:22 -05001028 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1029 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001030 {
1031 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001032 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001033 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001034 {
csharptestb00ea132011-06-10 01:09:57 -05001035 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001036 }
csharptestb00ea132011-06-10 01:09:57 -05001037 }
1038
1039 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1040 {
1041 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001042 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001043 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001044 {
csharptestb00ea132011-06-10 01:09:57 -05001045 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001046 }
csharptestb00ea132011-06-10 01:09:57 -05001047 }
1048
1049 [CLSCompliant(false)]
1050 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1051 where T : struct, IComparable, IFormattable, IConvertible
1052 {
1053 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001054 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001055 if (list is ICastArray)
1056 {
csharptest74c5e0c2011-07-14 13:06:22 -05001057 foreach (int value in ((ICastArray) list).CastArray<int>())
1058 {
csharptestb00ea132011-06-10 01:09:57 -05001059 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001060 }
csharptestb00ea132011-06-10 01:09:57 -05001061 }
1062 else
1063 {
1064 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001065 {
1066 WriteEnumNoTag((int) value);
1067 }
csharptestb00ea132011-06-10 01:09:57 -05001068 }
1069 }
1070
1071 #endregion
1072
csharptest71f662c2011-05-20 15:15:34 -05001073 #region Underlying writing primitives
1074
1075 /// <summary>
1076 /// Encodes and writes a tag.
1077 /// </summary>
1078 [CLSCompliant(false)]
1079 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1080 {
1081 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1082 }
1083
csharptest71f662c2011-05-20 15:15:34 -05001084 /// <summary>
1085 /// Writes a 32 bit value as a varint. The fast route is taken when
1086 /// there's enough buffer space left to whizz through without checking
1087 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1088 /// </summary>
1089 [CLSCompliant(false)]
1090 public void WriteRawVarint32(uint value)
1091 {
csharptestc671a4b2011-06-08 11:51:24 -05001092 while (value > 127 && position < limit)
1093 {
csharptest74c5e0c2011-07-14 13:06:22 -05001094 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001095 value >>= 7;
1096 }
1097 while (value > 127)
1098 {
csharptest74c5e0c2011-07-14 13:06:22 -05001099 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001100 value >>= 7;
1101 }
csharptest74c5e0c2011-07-14 13:06:22 -05001102 if (position < limit)
1103 {
1104 buffer[position++] = (byte) value;
1105 }
csharptestc671a4b2011-06-08 11:51:24 -05001106 else
csharptest74c5e0c2011-07-14 13:06:22 -05001107 {
1108 WriteRawByte((byte) value);
1109 }
csharptest71f662c2011-05-20 15:15:34 -05001110 }
1111
1112 [CLSCompliant(false)]
1113 public void WriteRawVarint64(ulong value)
1114 {
csharptestc671a4b2011-06-08 11:51:24 -05001115 while (value > 127 && position < limit)
1116 {
csharptest74c5e0c2011-07-14 13:06:22 -05001117 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001118 value >>= 7;
1119 }
1120 while (value > 127)
1121 {
csharptest74c5e0c2011-07-14 13:06:22 -05001122 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001123 value >>= 7;
1124 }
csharptest74c5e0c2011-07-14 13:06:22 -05001125 if (position < limit)
1126 {
1127 buffer[position++] = (byte) value;
1128 }
csharptestc671a4b2011-06-08 11:51:24 -05001129 else
csharptest74c5e0c2011-07-14 13:06:22 -05001130 {
1131 WriteRawByte((byte) value);
1132 }
csharptest71f662c2011-05-20 15:15:34 -05001133 }
1134
1135 [CLSCompliant(false)]
1136 public void WriteRawLittleEndian32(uint value)
1137 {
csharptestc671a4b2011-06-08 11:51:24 -05001138 if (position + 4 > limit)
1139 {
1140 WriteRawByte((byte) value);
1141 WriteRawByte((byte) (value >> 8));
1142 WriteRawByte((byte) (value >> 16));
1143 WriteRawByte((byte) (value >> 24));
1144 }
1145 else
1146 {
csharptest74c5e0c2011-07-14 13:06:22 -05001147 buffer[position++] = ((byte) value);
1148 buffer[position++] = ((byte) (value >> 8));
1149 buffer[position++] = ((byte) (value >> 16));
1150 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001151 }
csharptest71f662c2011-05-20 15:15:34 -05001152 }
1153
1154 [CLSCompliant(false)]
1155 public void WriteRawLittleEndian64(ulong value)
1156 {
csharptestc671a4b2011-06-08 11:51:24 -05001157 if (position + 8 > limit)
1158 {
1159 WriteRawByte((byte) value);
1160 WriteRawByte((byte) (value >> 8));
1161 WriteRawByte((byte) (value >> 16));
1162 WriteRawByte((byte) (value >> 24));
1163 WriteRawByte((byte) (value >> 32));
1164 WriteRawByte((byte) (value >> 40));
1165 WriteRawByte((byte) (value >> 48));
1166 WriteRawByte((byte) (value >> 56));
1167 }
1168 else
1169 {
csharptest74c5e0c2011-07-14 13:06:22 -05001170 buffer[position++] = ((byte) value);
1171 buffer[position++] = ((byte) (value >> 8));
1172 buffer[position++] = ((byte) (value >> 16));
1173 buffer[position++] = ((byte) (value >> 24));
1174 buffer[position++] = ((byte) (value >> 32));
1175 buffer[position++] = ((byte) (value >> 40));
1176 buffer[position++] = ((byte) (value >> 48));
1177 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001178 }
csharptest71f662c2011-05-20 15:15:34 -05001179 }
1180
1181 public void WriteRawByte(byte value)
1182 {
1183 if (position == limit)
1184 {
1185 RefreshBuffer();
1186 }
1187
1188 buffer[position++] = value;
1189 }
1190
1191 [CLSCompliant(false)]
1192 public void WriteRawByte(uint value)
1193 {
1194 WriteRawByte((byte) value);
1195 }
1196
1197 /// <summary>
1198 /// Writes out an array of bytes.
1199 /// </summary>
1200 public void WriteRawBytes(byte[] value)
1201 {
1202 WriteRawBytes(value, 0, value.Length);
1203 }
1204
1205 /// <summary>
1206 /// Writes out part of an array of bytes.
1207 /// </summary>
1208 public void WriteRawBytes(byte[] value, int offset, int length)
1209 {
1210 if (limit - position >= length)
1211 {
csharptestaef072a2011-06-08 18:00:43 -05001212 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001213 // We have room in the current buffer.
1214 position += length;
1215 }
1216 else
1217 {
1218 // Write extends past current buffer. Fill the rest of this buffer and
1219 // flush.
1220 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001221 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001222 offset += bytesWritten;
1223 length -= bytesWritten;
1224 position = limit;
1225 RefreshBuffer();
1226
1227 // Now deal with the rest.
1228 // Since we have an output stream, this is our buffer
1229 // and buffer offset == 0
1230 if (length <= limit)
1231 {
1232 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001233 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001234 position = length;
1235 }
1236 else
1237 {
1238 // Write is very big. Let's do it all at once.
1239 output.Write(value, offset, length);
1240 }
1241 }
1242 }
1243
1244 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001245
csharptest71f662c2011-05-20 15:15:34 -05001246 /// <summary>
1247 /// Encode a 32-bit value with ZigZag encoding.
1248 /// </summary>
1249 /// <remarks>
1250 /// ZigZag encodes signed integers into values that can be efficiently
1251 /// encoded with varint. (Otherwise, negative values must be
1252 /// sign-extended to 64 bits to be varint encoded, thus always taking
1253 /// 10 bytes on the wire.)
1254 /// </remarks>
1255 [CLSCompliant(false)]
1256 public static uint EncodeZigZag32(int n)
1257 {
1258 // Note: the right-shift must be arithmetic
1259 return (uint) ((n << 1) ^ (n >> 31));
1260 }
1261
1262 /// <summary>
1263 /// Encode a 64-bit value with ZigZag encoding.
1264 /// </summary>
1265 /// <remarks>
1266 /// ZigZag encodes signed integers into values that can be efficiently
1267 /// encoded with varint. (Otherwise, negative values must be
1268 /// sign-extended to 64 bits to be varint encoded, thus always taking
1269 /// 10 bytes on the wire.)
1270 /// </remarks>
1271 [CLSCompliant(false)]
1272 public static ulong EncodeZigZag64(long n)
1273 {
1274 return (ulong) ((n << 1) ^ (n >> 63));
1275 }
1276
1277 private void RefreshBuffer()
1278 {
1279 if (output == null)
1280 {
1281 // We're writing to a single buffer.
1282 throw new OutOfSpaceException();
1283 }
1284
1285 // Since we have an output stream, this is our buffer
1286 // and buffer offset == 0
1287 output.Write(buffer, 0, position);
1288 position = 0;
1289 }
1290
1291 /// <summary>
1292 /// Indicates that a CodedOutputStream wrapping a flat byte array
1293 /// ran out of space.
1294 /// </summary>
1295 public sealed class OutOfSpaceException : IOException
1296 {
1297 internal OutOfSpaceException()
1298 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1299 {
1300 }
1301 }
1302
1303 public void Flush()
1304 {
1305 if (output != null)
1306 {
1307 RefreshBuffer();
1308 }
1309 }
1310
1311 /// <summary>
1312 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1313 /// that is exactly big enough to hold a message, then write to it with
1314 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1315 /// the message was actually as big as expected, which can help bugs.
1316 /// </summary>
1317 public void CheckNoSpaceLeft()
1318 {
1319 if (SpaceLeft != 0)
1320 {
1321 throw new InvalidOperationException("Did not write as much data as expected.");
1322 }
1323 }
1324
1325 /// <summary>
1326 /// If writing to a flat array, returns the space left in the array. Otherwise,
1327 /// throws an InvalidOperationException.
1328 /// </summary>
1329 public int SpaceLeft
1330 {
1331 get
1332 {
1333 if (output == null)
1334 {
1335 return limit - position;
1336 }
1337 else
1338 {
1339 throw new InvalidOperationException(
1340 "SpaceLeft can only be called on CodedOutputStreams that are " +
1341 "writing to a flat array.");
1342 }
1343 }
1344 }
1345 }
1346}