blob: d267b75e4d94a4e55e0af48678b608308d659976 [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
csharptest0a0dd032013-05-16 13:59:34 -0500128
129 /// <summary>
130 /// Returns the current position in the stream, or the position in the output buffer
131 /// </summary>
132 public long Position
133 {
134 get
135 {
136 if (output != null)
csharptestd63096d2013-09-21 13:51:04 -0500137 {
csharptest0a0dd032013-05-16 13:59:34 -0500138 return output.Position + position;
csharptestd63096d2013-09-21 13:51:04 -0500139 }
csharptest0a0dd032013-05-16 13:59:34 -0500140 return position;
141 }
142 }
143
csharptest60fd7732011-09-09 12:18:16 -0500144 void ICodedOutputStream.WriteMessageStart() { }
145 void ICodedOutputStream.WriteMessageEnd() { Flush(); }
146
csharptest2b868842011-06-10 14:41:47 -0500147 #region Writing of unknown fields
148
149 [Obsolete]
150 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
151 {
152 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
153 value.WriteTo(this);
154 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
155 }
156
157 public void WriteUnknownBytes(int fieldNumber, ByteString value)
158 {
159 WriteBytes(fieldNumber, null /*not used*/, value);
160 }
161
162 [CLSCompliant(false)]
163 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
164 {
csharptest74c5e0c2011-07-14 13:06:22 -0500165 if (wireType == WireFormat.WireType.Varint)
166 {
csharptest2b868842011-06-10 14:41:47 -0500167 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500168 }
csharptest2b868842011-06-10 14:41:47 -0500169 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500170 {
171 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
172 }
csharptest2b868842011-06-10 14:41:47 -0500173 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500174 {
csharptest2b868842011-06-10 14:41:47 -0500175 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500176 }
csharptest2b868842011-06-10 14:41:47 -0500177 else
csharptest74c5e0c2011-07-14 13:06:22 -0500178 {
csharptest2b868842011-06-10 14:41:47 -0500179 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500180 }
csharptest2b868842011-06-10 14:41:47 -0500181 }
182
183 #endregion
184
csharptestb00ea132011-06-10 01:09:57 -0500185 #region Writing of tags and fields
186
187 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
188 {
189 switch (fieldType)
190 {
191 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500192 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500193 break;
194 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500195 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500196 break;
197 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500198 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500199 break;
200 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500201 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500202 break;
203 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500204 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500205 break;
206 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500207 if (value is Enum)
208 {
209 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
210 }
csharptestb00ea132011-06-10 01:09:57 -0500211 else
csharptest74c5e0c2011-07-14 13:06:22 -0500212 {
213 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
214 }
csharptestb00ea132011-06-10 01:09:57 -0500215 break;
216 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500217 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500218 break;
219 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500220 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500221 break;
222 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500223 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500224 break;
225 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500226 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500227 break;
228 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500229 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500230 break;
231 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500232 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500233 break;
234 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500235 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500236 break;
237 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500238 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500239 break;
240 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500241 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500242 break;
243 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500244 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500245 break;
246 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500247 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500248 break;
249 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500250 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500251 break;
252 }
253 }
csharptest71f662c2011-05-20 15:15:34 -0500254
255 /// <summary>
256 /// Writes a double field value, including tag, to the stream.
257 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500258 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500259 {
260 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
261 WriteDoubleNoTag(value);
262 }
263
264 /// <summary>
265 /// Writes a float field value, including tag, to the stream.
266 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500267 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500268 {
269 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
270 WriteFloatNoTag(value);
271 }
272
273 /// <summary>
274 /// Writes a uint64 field value, including tag, to the stream.
275 /// </summary>
276 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500277 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500278 {
279 WriteTag(fieldNumber, WireFormat.WireType.Varint);
280 WriteRawVarint64(value);
281 }
282
283 /// <summary>
284 /// Writes an int64 field value, including tag, to the stream.
285 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500286 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500287 {
288 WriteTag(fieldNumber, WireFormat.WireType.Varint);
289 WriteRawVarint64((ulong) value);
290 }
291
292 /// <summary>
293 /// Writes an int32 field value, including tag, to the stream.
294 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500295 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500296 {
297 WriteTag(fieldNumber, WireFormat.WireType.Varint);
298 if (value >= 0)
299 {
300 WriteRawVarint32((uint) value);
301 }
302 else
303 {
304 // Must sign-extend.
305 WriteRawVarint64((ulong) value);
306 }
307 }
308
309 /// <summary>
310 /// Writes a fixed64 field value, including tag, to the stream.
311 /// </summary>
312 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500313 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500314 {
315 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
316 WriteRawLittleEndian64(value);
317 }
318
319 /// <summary>
320 /// Writes a fixed32 field value, including tag, to the stream.
321 /// </summary>
322 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500323 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500324 {
325 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
326 WriteRawLittleEndian32(value);
327 }
328
329 /// <summary>
330 /// Writes a bool field value, including tag, to the stream.
331 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500332 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500333 {
334 WriteTag(fieldNumber, WireFormat.WireType.Varint);
335 WriteRawByte(value ? (byte) 1 : (byte) 0);
336 }
337
338 /// <summary>
339 /// Writes a string field value, including tag, to the stream.
340 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500341 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500342 {
343 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
344 // Optimise the case where we have enough space to write
345 // the string directly to the buffer, which should be common.
346 int length = Encoding.UTF8.GetByteCount(value);
347 WriteRawVarint32((uint) length);
348 if (limit - position >= length)
349 {
350 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
351 position += length;
352 }
353 else
354 {
355 byte[] bytes = Encoding.UTF8.GetBytes(value);
356 WriteRawBytes(bytes);
357 }
358 }
359
360 /// <summary>
361 /// Writes a group field value, including tag, to the stream.
362 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500363 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500364 {
365 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
366 value.WriteTo(this);
367 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
368 }
369
csharptest90922db2011-06-03 11:57:47 -0500370 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500371 {
372 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
373 WriteRawVarint32((uint) value.SerializedSize);
374 value.WriteTo(this);
375 }
376
csharptest90922db2011-06-03 11:57:47 -0500377 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500378 {
csharptest71f662c2011-05-20 15:15:34 -0500379 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500380 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500381 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500382 }
383
384 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500385 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500386 {
387 WriteTag(fieldNumber, WireFormat.WireType.Varint);
388 WriteRawVarint32(value);
389 }
390
csharptest304ff3a2011-08-05 16:51:49 -0500391 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500392 {
393 WriteTag(fieldNumber, WireFormat.WireType.Varint);
csharptesta105eac2011-09-09 13:39:54 -0500394 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500395 }
396
csharptest90922db2011-06-03 11:57:47 -0500397 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500398 {
399 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
400 WriteRawLittleEndian32((uint) value);
401 }
402
csharptest90922db2011-06-03 11:57:47 -0500403 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500404 {
405 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
406 WriteRawLittleEndian64((ulong) value);
407 }
408
csharptest90922db2011-06-03 11:57:47 -0500409 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500410 {
411 WriteTag(fieldNumber, WireFormat.WireType.Varint);
412 WriteRawVarint32(EncodeZigZag32(value));
413 }
414
csharptest90922db2011-06-03 11:57:47 -0500415 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500416 {
417 WriteTag(fieldNumber, WireFormat.WireType.Varint);
418 WriteRawVarint64(EncodeZigZag64(value));
419 }
420
csharptest90922db2011-06-03 11:57:47 -0500421 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500422 {
423 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500424 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
425 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500426 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
427 }
428
csharptestffafdaa2011-06-03 12:58:14 -0500429 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500430 {
431 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500432 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
433 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500434 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
435 }
csharptest90922db2011-06-03 11:57:47 -0500436
csharptestb00ea132011-06-10 01:09:57 -0500437 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500438
csharptestb00ea132011-06-10 01:09:57 -0500439 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500440
441 public void WriteFieldNoTag(FieldType fieldType, object value)
442 {
443 switch (fieldType)
444 {
csharptestc671a4b2011-06-08 11:51:24 -0500445 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500446 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500447 break;
csharptestc671a4b2011-06-08 11:51:24 -0500448 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500449 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500450 break;
csharptestc671a4b2011-06-08 11:51:24 -0500451 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500452 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500453 break;
csharptestc671a4b2011-06-08 11:51:24 -0500454 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500455 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500456 break;
457 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500458 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500459 break;
460 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500461 if (value is Enum)
462 {
463 WriteEnumNoTag((int) value);
464 }
csharptestc671a4b2011-06-08 11:51:24 -0500465 else
csharptest74c5e0c2011-07-14 13:06:22 -0500466 {
467 WriteEnumNoTag(((IEnumLite) value).Number);
468 }
csharptest71f662c2011-05-20 15:15:34 -0500469 break;
470 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500471 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500472 break;
csharptestc671a4b2011-06-08 11:51:24 -0500473 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500474 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500475 break;
476 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500477 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500478 break;
csharptestc671a4b2011-06-08 11:51:24 -0500479 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500480 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500481 break;
482 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500483 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500484 break;
485 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500486 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500487 break;
csharptestc671a4b2011-06-08 11:51:24 -0500488 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500489 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500490 break;
491 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500492 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500493 break;
494 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500495 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500496 break;
497 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500498 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500499 break;
500 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500501 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500502 break;
503 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500504 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500505 break;
506 }
507 }
508
csharptest71f662c2011-05-20 15:15:34 -0500509 /// <summary>
510 /// Writes a double field value, including tag, to the stream.
511 /// </summary>
512 public void WriteDoubleNoTag(double value)
513 {
csharptest67164322012-10-14 18:47:48 -0500514 WriteRawLittleEndian64((ulong)FrameworkPortability.DoubleToInt64(value));
csharptest71f662c2011-05-20 15:15:34 -0500515 }
516
517 /// <summary>
518 /// Writes a float field value, without a tag, to the stream.
519 /// </summary>
520 public void WriteFloatNoTag(float value)
521 {
csharptest71f662c2011-05-20 15:15:34 -0500522 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500523 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500524 {
csharptestaef072a2011-06-08 18:00:43 -0500525 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500526 }
csharptest2772dfe2011-06-08 15:50:58 -0500527
528 if (limit - position >= 4)
529 {
530 buffer[position++] = rawBytes[0];
531 buffer[position++] = rawBytes[1];
532 buffer[position++] = rawBytes[2];
533 buffer[position++] = rawBytes[3];
534 }
535 else
csharptest74c5e0c2011-07-14 13:06:22 -0500536 {
csharptest2772dfe2011-06-08 15:50:58 -0500537 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500538 }
csharptest71f662c2011-05-20 15:15:34 -0500539 }
540
541 /// <summary>
542 /// Writes a uint64 field value, without a tag, to the stream.
543 /// </summary>
544 [CLSCompliant(false)]
545 public void WriteUInt64NoTag(ulong value)
546 {
547 WriteRawVarint64(value);
548 }
549
550 /// <summary>
551 /// Writes an int64 field value, without a tag, to the stream.
552 /// </summary>
553 public void WriteInt64NoTag(long value)
554 {
csharptest74c5e0c2011-07-14 13:06:22 -0500555 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500556 }
557
558 /// <summary>
559 /// Writes an int32 field value, without a tag, to the stream.
560 /// </summary>
561 public void WriteInt32NoTag(int value)
562 {
563 if (value >= 0)
564 {
csharptest74c5e0c2011-07-14 13:06:22 -0500565 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500566 }
567 else
568 {
569 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500570 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500571 }
572 }
573
574 /// <summary>
575 /// Writes a fixed64 field value, without a tag, to the stream.
576 /// </summary>
577 [CLSCompliant(false)]
578 public void WriteFixed64NoTag(ulong value)
579 {
580 WriteRawLittleEndian64(value);
581 }
582
583 /// <summary>
584 /// Writes a fixed32 field value, without a tag, to the stream.
585 /// </summary>
586 [CLSCompliant(false)]
587 public void WriteFixed32NoTag(uint value)
588 {
589 WriteRawLittleEndian32(value);
590 }
591
592 /// <summary>
593 /// Writes a bool field value, without a tag, to the stream.
594 /// </summary>
595 public void WriteBoolNoTag(bool value)
596 {
csharptest74c5e0c2011-07-14 13:06:22 -0500597 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500598 }
599
600 /// <summary>
601 /// Writes a string field value, without a tag, to the stream.
602 /// </summary>
603 public void WriteStringNoTag(string value)
604 {
605 // Optimise the case where we have enough space to write
606 // the string directly to the buffer, which should be common.
607 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500608 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500609 if (limit - position >= length)
610 {
611 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
612 position += length;
613 }
614 else
615 {
616 byte[] bytes = Encoding.UTF8.GetBytes(value);
617 WriteRawBytes(bytes);
618 }
619 }
620
621 /// <summary>
622 /// Writes a group field value, without a tag, to the stream.
623 /// </summary>
624 public void WriteGroupNoTag(IMessageLite value)
625 {
626 value.WriteTo(this);
627 }
628
629 public void WriteMessageNoTag(IMessageLite value)
630 {
csharptest74c5e0c2011-07-14 13:06:22 -0500631 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500632 value.WriteTo(this);
633 }
634
635 public void WriteBytesNoTag(ByteString value)
636 {
csharptest74c5e0c2011-07-14 13:06:22 -0500637 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500638 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500639 }
640
641 [CLSCompliant(false)]
642 public void WriteUInt32NoTag(uint value)
643 {
644 WriteRawVarint32(value);
645 }
646
647 public void WriteEnumNoTag(int value)
648 {
csharptesta105eac2011-09-09 13:39:54 -0500649 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500650 }
651
652 public void WriteSFixed32NoTag(int value)
653 {
csharptest74c5e0c2011-07-14 13:06:22 -0500654 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500655 }
656
657 public void WriteSFixed64NoTag(long value)
658 {
csharptest74c5e0c2011-07-14 13:06:22 -0500659 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500660 }
661
662 public void WriteSInt32NoTag(int value)
663 {
664 WriteRawVarint32(EncodeZigZag32(value));
665 }
666
667 public void WriteSInt64NoTag(long value)
668 {
669 WriteRawVarint64(EncodeZigZag64(value));
670 }
671
672 #endregion
673
csharptestb00ea132011-06-10 01:09:57 -0500674 #region Write array members
675
csharptest74c5e0c2011-07-14 13:06:22 -0500676 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500677 {
678 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500679 {
csharptestb00ea132011-06-10 01:09:57 -0500680 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500681 }
csharptestb00ea132011-06-10 01:09:57 -0500682 }
683
684 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
685 where T : IMessageLite
686 {
687 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500688 {
csharptestb00ea132011-06-10 01:09:57 -0500689 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500690 }
csharptestb00ea132011-06-10 01:09:57 -0500691 }
692
693 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
694 where T : IMessageLite
695 {
696 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500697 {
csharptestb00ea132011-06-10 01:09:57 -0500698 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500699 }
csharptestb00ea132011-06-10 01:09:57 -0500700 }
701
702 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
703 {
704 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500705 {
csharptestb00ea132011-06-10 01:09:57 -0500706 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500707 }
csharptestb00ea132011-06-10 01:09:57 -0500708 }
709
710 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
711 {
712 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500713 {
csharptestb00ea132011-06-10 01:09:57 -0500714 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500715 }
csharptestb00ea132011-06-10 01:09:57 -0500716 }
717
718 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
719 {
720 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500721 {
csharptestb00ea132011-06-10 01:09:57 -0500722 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500723 }
csharptestb00ea132011-06-10 01:09:57 -0500724 }
725
726 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
727 {
728 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500729 {
csharptestb00ea132011-06-10 01:09:57 -0500730 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500731 }
csharptestb00ea132011-06-10 01:09:57 -0500732 }
733
734 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
735 {
736 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500737 {
csharptestb00ea132011-06-10 01:09:57 -0500738 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500739 }
csharptestb00ea132011-06-10 01:09:57 -0500740 }
741
742 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
743 {
744 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500745 {
csharptestb00ea132011-06-10 01:09:57 -0500746 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500747 }
csharptestb00ea132011-06-10 01:09:57 -0500748 }
749
750 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
751 {
752 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500753 {
csharptestb00ea132011-06-10 01:09:57 -0500754 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500755 }
csharptestb00ea132011-06-10 01:09:57 -0500756 }
757
758 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
759 {
760 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500761 {
csharptestb00ea132011-06-10 01:09:57 -0500762 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500763 }
csharptestb00ea132011-06-10 01:09:57 -0500764 }
765
766 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
767 {
768 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500769 {
csharptestb00ea132011-06-10 01:09:57 -0500770 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500771 }
csharptestb00ea132011-06-10 01:09:57 -0500772 }
773
774 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
775 {
776 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500777 {
csharptestb00ea132011-06-10 01:09:57 -0500778 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500779 }
csharptestb00ea132011-06-10 01:09:57 -0500780 }
781
782 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
783 {
784 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500785 {
csharptestb00ea132011-06-10 01:09:57 -0500786 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500787 }
csharptestb00ea132011-06-10 01:09:57 -0500788 }
789
790 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
791 {
792 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500793 {
csharptestb00ea132011-06-10 01:09:57 -0500794 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500795 }
csharptestb00ea132011-06-10 01:09:57 -0500796 }
797
798 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
799 {
800 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500801 {
csharptestb00ea132011-06-10 01:09:57 -0500802 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500803 }
csharptestb00ea132011-06-10 01:09:57 -0500804 }
805
806 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
807 {
808 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500809 {
csharptestb00ea132011-06-10 01:09:57 -0500810 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500811 }
csharptestb00ea132011-06-10 01:09:57 -0500812 }
813
814 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
815 {
816 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500817 {
csharptestb00ea132011-06-10 01:09:57 -0500818 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500819 }
csharptestb00ea132011-06-10 01:09:57 -0500820 }
821
822 [CLSCompliant(false)]
823 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
csharptestc9bce452012-10-14 23:03:24 -0500824 where T : struct, IComparable, IFormattable
csharptestb00ea132011-06-10 01:09:57 -0500825 {
826 if (list is ICastArray)
827 {
csharptest74c5e0c2011-07-14 13:06:22 -0500828 foreach (int value in ((ICastArray) list).CastArray<int>())
829 {
csharptestb00ea132011-06-10 01:09:57 -0500830 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500831 }
csharptestb00ea132011-06-10 01:09:57 -0500832 }
833 else
834 {
835 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500836 {
csharptestb00ea132011-06-10 01:09:57 -0500837 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500838 }
csharptestb00ea132011-06-10 01:09:57 -0500839 }
840 }
841
842 #endregion
843
844 #region Write packed array members
845
csharptest74c5e0c2011-07-14 13:06:22 -0500846 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500847 {
848 int calculatedSize = 0;
849 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500850 {
851 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
852 }
csharptestb00ea132011-06-10 01:09:57 -0500853
854 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500855 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500856
857 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500858 {
csharptestb00ea132011-06-10 01:09:57 -0500859 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500860 }
csharptestb00ea132011-06-10 01:09:57 -0500861 }
862
863 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
864 where T : IMessageLite
865 {
866 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500867 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500868 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500869 {
csharptestb00ea132011-06-10 01:09:57 -0500870 WriteGroupNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500871 }
csharptestb00ea132011-06-10 01:09:57 -0500872 }
873
csharptest74c5e0c2011-07-14 13:06:22 -0500874 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
875 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500876 where T : IMessageLite
877 {
878 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500879 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500880 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500881 {
csharptestb00ea132011-06-10 01:09:57 -0500882 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500883 }
csharptestb00ea132011-06-10 01:09:57 -0500884 }
885
csharptest74c5e0c2011-07-14 13:06:22 -0500886 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
887 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500888 {
889 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500890 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500891 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500892 {
csharptestb00ea132011-06-10 01:09:57 -0500893 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500894 }
csharptestb00ea132011-06-10 01:09:57 -0500895 }
896
csharptest74c5e0c2011-07-14 13:06:22 -0500897 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
898 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500899 {
900 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500901 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500902 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500903 {
csharptestb00ea132011-06-10 01:09:57 -0500904 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500905 }
csharptestb00ea132011-06-10 01:09:57 -0500906 }
907
908 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
909 {
910 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500911 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500912 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500913 {
csharptestb00ea132011-06-10 01:09:57 -0500914 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500915 }
csharptestb00ea132011-06-10 01:09:57 -0500916 }
917
918 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
919 {
920 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500921 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500922 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500923 {
csharptestb00ea132011-06-10 01:09:57 -0500924 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500925 }
csharptestb00ea132011-06-10 01:09:57 -0500926 }
927
928 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
929 {
930 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500931 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500932 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500933 {
csharptestb00ea132011-06-10 01:09:57 -0500934 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500935 }
csharptestb00ea132011-06-10 01:09:57 -0500936 }
937
938 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
939 {
940 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500941 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500942 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500943 {
csharptestb00ea132011-06-10 01:09:57 -0500944 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500945 }
csharptestb00ea132011-06-10 01:09:57 -0500946 }
947
csharptest74c5e0c2011-07-14 13:06:22 -0500948 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
949 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500950 {
951 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500952 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500953 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500954 {
csharptestb00ea132011-06-10 01:09:57 -0500955 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500956 }
csharptestb00ea132011-06-10 01:09:57 -0500957 }
958
csharptest74c5e0c2011-07-14 13:06:22 -0500959 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
960 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500961 {
962 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500963 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500964 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500965 {
csharptestb00ea132011-06-10 01:09:57 -0500966 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500967 }
csharptestb00ea132011-06-10 01:09:57 -0500968 }
969
970 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
971 {
972 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500973 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500974 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500975 {
csharptestb00ea132011-06-10 01:09:57 -0500976 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500977 }
csharptestb00ea132011-06-10 01:09:57 -0500978 }
979
980 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
981 {
982 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500983 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500984 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500985 {
csharptestb00ea132011-06-10 01:09:57 -0500986 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500987 }
csharptestb00ea132011-06-10 01:09:57 -0500988 }
989
csharptest74c5e0c2011-07-14 13:06:22 -0500990 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
991 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -0500992 {
993 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500994 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500995 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500996 {
csharptestb00ea132011-06-10 01:09:57 -0500997 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500998 }
csharptestb00ea132011-06-10 01:09:57 -0500999 }
1000
csharptest74c5e0c2011-07-14 13:06:22 -05001001 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1002 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001003 {
1004 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001005 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001006 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001007 {
csharptestb00ea132011-06-10 01:09:57 -05001008 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001009 }
csharptestb00ea132011-06-10 01:09:57 -05001010 }
1011
csharptest74c5e0c2011-07-14 13:06:22 -05001012 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1013 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001014 {
1015 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001016 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001017 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001018 {
csharptestb00ea132011-06-10 01:09:57 -05001019 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001020 }
csharptestb00ea132011-06-10 01:09:57 -05001021 }
1022
csharptest74c5e0c2011-07-14 13:06:22 -05001023 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1024 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001025 {
1026 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001027 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001028 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001029 {
csharptestb00ea132011-06-10 01:09:57 -05001030 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001031 }
csharptestb00ea132011-06-10 01:09:57 -05001032 }
1033
1034 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1035 {
1036 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001037 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001038 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001039 {
csharptestb00ea132011-06-10 01:09:57 -05001040 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001041 }
csharptestb00ea132011-06-10 01:09:57 -05001042 }
1043
1044 [CLSCompliant(false)]
1045 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
csharptestc9bce452012-10-14 23:03:24 -05001046 where T : struct, IComparable, IFormattable
csharptestb00ea132011-06-10 01:09:57 -05001047 {
1048 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001049 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001050 if (list is ICastArray)
1051 {
csharptest74c5e0c2011-07-14 13:06:22 -05001052 foreach (int value in ((ICastArray) list).CastArray<int>())
1053 {
csharptestb00ea132011-06-10 01:09:57 -05001054 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001055 }
csharptestb00ea132011-06-10 01:09:57 -05001056 }
1057 else
1058 {
1059 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001060 {
1061 WriteEnumNoTag((int) value);
1062 }
csharptestb00ea132011-06-10 01:09:57 -05001063 }
1064 }
1065
1066 #endregion
1067
csharptest71f662c2011-05-20 15:15:34 -05001068 #region Underlying writing primitives
1069
1070 /// <summary>
1071 /// Encodes and writes a tag.
1072 /// </summary>
1073 [CLSCompliant(false)]
1074 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1075 {
1076 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1077 }
1078
csharptest71f662c2011-05-20 15:15:34 -05001079 /// <summary>
1080 /// Writes a 32 bit value as a varint. The fast route is taken when
1081 /// there's enough buffer space left to whizz through without checking
1082 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1083 /// </summary>
1084 [CLSCompliant(false)]
1085 public void WriteRawVarint32(uint value)
1086 {
csharptestc671a4b2011-06-08 11:51:24 -05001087 while (value > 127 && position < limit)
1088 {
csharptest74c5e0c2011-07-14 13:06:22 -05001089 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001090 value >>= 7;
1091 }
1092 while (value > 127)
1093 {
csharptest74c5e0c2011-07-14 13:06:22 -05001094 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001095 value >>= 7;
1096 }
csharptest74c5e0c2011-07-14 13:06:22 -05001097 if (position < limit)
1098 {
1099 buffer[position++] = (byte) value;
1100 }
csharptestc671a4b2011-06-08 11:51:24 -05001101 else
csharptest74c5e0c2011-07-14 13:06:22 -05001102 {
1103 WriteRawByte((byte) value);
1104 }
csharptest71f662c2011-05-20 15:15:34 -05001105 }
1106
1107 [CLSCompliant(false)]
1108 public void WriteRawVarint64(ulong value)
1109 {
csharptestc671a4b2011-06-08 11:51:24 -05001110 while (value > 127 && position < limit)
1111 {
csharptest74c5e0c2011-07-14 13:06:22 -05001112 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001113 value >>= 7;
1114 }
1115 while (value > 127)
1116 {
csharptest74c5e0c2011-07-14 13:06:22 -05001117 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001118 value >>= 7;
1119 }
csharptest74c5e0c2011-07-14 13:06:22 -05001120 if (position < limit)
1121 {
1122 buffer[position++] = (byte) value;
1123 }
csharptestc671a4b2011-06-08 11:51:24 -05001124 else
csharptest74c5e0c2011-07-14 13:06:22 -05001125 {
1126 WriteRawByte((byte) value);
1127 }
csharptest71f662c2011-05-20 15:15:34 -05001128 }
1129
1130 [CLSCompliant(false)]
1131 public void WriteRawLittleEndian32(uint value)
1132 {
csharptestc671a4b2011-06-08 11:51:24 -05001133 if (position + 4 > limit)
1134 {
1135 WriteRawByte((byte) value);
1136 WriteRawByte((byte) (value >> 8));
1137 WriteRawByte((byte) (value >> 16));
1138 WriteRawByte((byte) (value >> 24));
1139 }
1140 else
1141 {
csharptest74c5e0c2011-07-14 13:06:22 -05001142 buffer[position++] = ((byte) value);
1143 buffer[position++] = ((byte) (value >> 8));
1144 buffer[position++] = ((byte) (value >> 16));
1145 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001146 }
csharptest71f662c2011-05-20 15:15:34 -05001147 }
1148
1149 [CLSCompliant(false)]
1150 public void WriteRawLittleEndian64(ulong value)
1151 {
csharptestc671a4b2011-06-08 11:51:24 -05001152 if (position + 8 > limit)
1153 {
1154 WriteRawByte((byte) value);
1155 WriteRawByte((byte) (value >> 8));
1156 WriteRawByte((byte) (value >> 16));
1157 WriteRawByte((byte) (value >> 24));
1158 WriteRawByte((byte) (value >> 32));
1159 WriteRawByte((byte) (value >> 40));
1160 WriteRawByte((byte) (value >> 48));
1161 WriteRawByte((byte) (value >> 56));
1162 }
1163 else
1164 {
csharptest74c5e0c2011-07-14 13:06:22 -05001165 buffer[position++] = ((byte) value);
1166 buffer[position++] = ((byte) (value >> 8));
1167 buffer[position++] = ((byte) (value >> 16));
1168 buffer[position++] = ((byte) (value >> 24));
1169 buffer[position++] = ((byte) (value >> 32));
1170 buffer[position++] = ((byte) (value >> 40));
1171 buffer[position++] = ((byte) (value >> 48));
1172 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001173 }
csharptest71f662c2011-05-20 15:15:34 -05001174 }
1175
1176 public void WriteRawByte(byte value)
1177 {
1178 if (position == limit)
1179 {
1180 RefreshBuffer();
1181 }
1182
1183 buffer[position++] = value;
1184 }
1185
1186 [CLSCompliant(false)]
1187 public void WriteRawByte(uint value)
1188 {
1189 WriteRawByte((byte) value);
1190 }
1191
1192 /// <summary>
1193 /// Writes out an array of bytes.
1194 /// </summary>
1195 public void WriteRawBytes(byte[] value)
1196 {
1197 WriteRawBytes(value, 0, value.Length);
1198 }
1199
1200 /// <summary>
1201 /// Writes out part of an array of bytes.
1202 /// </summary>
1203 public void WriteRawBytes(byte[] value, int offset, int length)
1204 {
1205 if (limit - position >= length)
1206 {
csharptestaef072a2011-06-08 18:00:43 -05001207 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001208 // We have room in the current buffer.
1209 position += length;
1210 }
1211 else
1212 {
1213 // Write extends past current buffer. Fill the rest of this buffer and
1214 // flush.
1215 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001216 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001217 offset += bytesWritten;
1218 length -= bytesWritten;
1219 position = limit;
1220 RefreshBuffer();
1221
1222 // Now deal with the rest.
1223 // Since we have an output stream, this is our buffer
1224 // and buffer offset == 0
1225 if (length <= limit)
1226 {
1227 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001228 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001229 position = length;
1230 }
1231 else
1232 {
1233 // Write is very big. Let's do it all at once.
1234 output.Write(value, offset, length);
1235 }
1236 }
1237 }
1238
1239 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001240
csharptest71f662c2011-05-20 15:15:34 -05001241 /// <summary>
1242 /// Encode a 32-bit value with ZigZag encoding.
1243 /// </summary>
1244 /// <remarks>
1245 /// ZigZag encodes signed integers into values that can be efficiently
1246 /// encoded with varint. (Otherwise, negative values must be
1247 /// sign-extended to 64 bits to be varint encoded, thus always taking
1248 /// 10 bytes on the wire.)
1249 /// </remarks>
1250 [CLSCompliant(false)]
1251 public static uint EncodeZigZag32(int n)
1252 {
1253 // Note: the right-shift must be arithmetic
1254 return (uint) ((n << 1) ^ (n >> 31));
1255 }
1256
1257 /// <summary>
1258 /// Encode a 64-bit value with ZigZag encoding.
1259 /// </summary>
1260 /// <remarks>
1261 /// ZigZag encodes signed integers into values that can be efficiently
1262 /// encoded with varint. (Otherwise, negative values must be
1263 /// sign-extended to 64 bits to be varint encoded, thus always taking
1264 /// 10 bytes on the wire.)
1265 /// </remarks>
1266 [CLSCompliant(false)]
1267 public static ulong EncodeZigZag64(long n)
1268 {
1269 return (ulong) ((n << 1) ^ (n >> 63));
1270 }
1271
1272 private void RefreshBuffer()
1273 {
1274 if (output == null)
1275 {
1276 // We're writing to a single buffer.
1277 throw new OutOfSpaceException();
1278 }
1279
1280 // Since we have an output stream, this is our buffer
1281 // and buffer offset == 0
1282 output.Write(buffer, 0, position);
1283 position = 0;
1284 }
1285
1286 /// <summary>
1287 /// Indicates that a CodedOutputStream wrapping a flat byte array
1288 /// ran out of space.
1289 /// </summary>
1290 public sealed class OutOfSpaceException : IOException
1291 {
1292 internal OutOfSpaceException()
1293 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1294 {
1295 }
1296 }
1297
1298 public void Flush()
1299 {
1300 if (output != null)
1301 {
1302 RefreshBuffer();
1303 }
1304 }
1305
1306 /// <summary>
1307 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1308 /// that is exactly big enough to hold a message, then write to it with
1309 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1310 /// the message was actually as big as expected, which can help bugs.
1311 /// </summary>
1312 public void CheckNoSpaceLeft()
1313 {
1314 if (SpaceLeft != 0)
1315 {
1316 throw new InvalidOperationException("Did not write as much data as expected.");
1317 }
1318 }
1319
1320 /// <summary>
1321 /// If writing to a flat array, returns the space left in the array. Otherwise,
1322 /// throws an InvalidOperationException.
1323 /// </summary>
1324 public int SpaceLeft
1325 {
1326 get
1327 {
1328 if (output == null)
1329 {
1330 return limit - position;
1331 }
1332 else
1333 {
1334 throw new InvalidOperationException(
1335 "SpaceLeft can only be called on CodedOutputStreams that are " +
1336 "writing to a flat array.");
1337 }
1338 }
1339 }
1340 }
1341}