blob: 709082a71d67b18e4fcc7fddd18765ef90381e91 [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
csharptest74c5e0c2011-07-14 13:06:22 -050038using System.Collections;
csharptestc671a4b2011-06-08 11:51:24 -050039using System.Collections.Generic;
csharptest71f662c2011-05-20 15:15:34 -050040using System.IO;
41using System.Text;
csharptestced18e12011-06-09 19:47:56 -050042using Google.ProtocolBuffers.Collections;
csharptest71f662c2011-05-20 15:15:34 -050043using Google.ProtocolBuffers.Descriptors;
44
45namespace Google.ProtocolBuffers
46{
47 /// <summary>
48 /// Encodes and writes protocol message fields.
49 /// </summary>
50 /// <remarks>
51 /// This class contains two kinds of methods: methods that write specific
52 /// protocol message constructs and field types (e.g. WriteTag and
53 /// WriteInt32) and methods that write low-level values (e.g.
54 /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
55 /// messages, you should use the former methods, but if you are writing some
56 /// other format of your own design, use the latter. The names of the former
57 /// methods are taken from the protocol buffer type names, not .NET types.
58 /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
59 /// </remarks>
csharptest819b7152011-09-08 20:28:22 -050060 public sealed partial class CodedOutputStream : ICodedOutputStream, IDisposable
csharptest71f662c2011-05-20 15:15:34 -050061 {
62 /// <summary>
63 /// The buffer size used by CreateInstance(Stream).
64 /// </summary>
65 public static readonly int DefaultBufferSize = 4096;
66
67 private readonly byte[] buffer;
68 private readonly int limit;
69 private int position;
70 private readonly Stream output;
71
72 #region Construction
73
74 private CodedOutputStream(byte[] buffer, int offset, int length)
75 {
76 this.output = null;
77 this.buffer = buffer;
78 this.position = offset;
79 this.limit = offset + length;
80 }
81
82 private CodedOutputStream(Stream output, byte[] buffer)
83 {
84 this.output = output;
85 this.buffer = buffer;
86 this.position = 0;
87 this.limit = buffer.Length;
88 }
89
90 /// <summary>
91 /// Creates a new CodedOutputStream which write to the given stream.
92 /// </summary>
93 public static CodedOutputStream CreateInstance(Stream output)
94 {
95 return CreateInstance(output, DefaultBufferSize);
96 }
97
98 /// <summary>
99 /// Creates a new CodedOutputStream which write to the given stream and uses
100 /// the specified buffer size.
101 /// </summary>
102 public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
103 {
104 return new CodedOutputStream(output, new byte[bufferSize]);
105 }
106
107 /// <summary>
108 /// Creates a new CodedOutputStream that writes directly to the given
109 /// byte array. If more bytes are written than fit in the array,
110 /// OutOfSpaceException will be thrown.
111 /// </summary>
112 public static CodedOutputStream CreateInstance(byte[] flatArray)
113 {
114 return CreateInstance(flatArray, 0, flatArray.Length);
115 }
116
117 /// <summary>
118 /// Creates a new CodedOutputStream that writes directly to the given
119 /// byte array slice. If more bytes are written than fit in the array,
120 /// OutOfSpaceException will be thrown.
121 /// </summary>
122 public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
123 {
124 return new CodedOutputStream(flatArray, offset, length);
125 }
126
127 #endregion
csharptest819b7152011-09-08 20:28:22 -0500128
129 public void Dispose()
130 {
131 if (output != null)
132 {
133 if (position > 0)
csharptestc86b5042011-09-09 22:16:08 -0500134 {
csharptest819b7152011-09-08 20:28:22 -0500135 Flush();
csharptestc86b5042011-09-09 22:16:08 -0500136 }
csharptest819b7152011-09-08 20:28:22 -0500137 output.Dispose();
138 }
139 }
csharptest71f662c2011-05-20 15:15:34 -0500140
csharptest60fd7732011-09-09 12:18:16 -0500141 void ICodedOutputStream.WriteMessageStart() { }
142 void ICodedOutputStream.WriteMessageEnd() { Flush(); }
143
csharptest2b868842011-06-10 14:41:47 -0500144 #region Writing of unknown fields
145
146 [Obsolete]
147 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
148 {
149 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
150 value.WriteTo(this);
151 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
152 }
153
154 public void WriteUnknownBytes(int fieldNumber, ByteString value)
155 {
156 WriteBytes(fieldNumber, null /*not used*/, value);
157 }
158
159 [CLSCompliant(false)]
160 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
161 {
csharptest74c5e0c2011-07-14 13:06:22 -0500162 if (wireType == WireFormat.WireType.Varint)
163 {
csharptest2b868842011-06-10 14:41:47 -0500164 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500165 }
csharptest2b868842011-06-10 14:41:47 -0500166 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500167 {
168 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
169 }
csharptest2b868842011-06-10 14:41:47 -0500170 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500171 {
csharptest2b868842011-06-10 14:41:47 -0500172 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500173 }
csharptest2b868842011-06-10 14:41:47 -0500174 else
csharptest74c5e0c2011-07-14 13:06:22 -0500175 {
csharptest2b868842011-06-10 14:41:47 -0500176 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500177 }
csharptest2b868842011-06-10 14:41:47 -0500178 }
179
180 #endregion
181
csharptestb00ea132011-06-10 01:09:57 -0500182 #region Writing of tags and fields
183
184 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
185 {
186 switch (fieldType)
187 {
188 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500189 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500190 break;
191 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500192 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500193 break;
194 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500195 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500196 break;
197 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500198 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500199 break;
200 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500201 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500202 break;
203 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500204 if (value is Enum)
205 {
206 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
207 }
csharptestb00ea132011-06-10 01:09:57 -0500208 else
csharptest74c5e0c2011-07-14 13:06:22 -0500209 {
210 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
211 }
csharptestb00ea132011-06-10 01:09:57 -0500212 break;
213 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500214 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500215 break;
216 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500217 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500218 break;
219 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500220 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500221 break;
222 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500223 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500224 break;
225 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500226 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500227 break;
228 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500229 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500230 break;
231 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500232 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500233 break;
234 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500235 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500236 break;
237 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500238 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500239 break;
240 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500241 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500242 break;
243 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500244 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500245 break;
246 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500247 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500248 break;
249 }
250 }
csharptest71f662c2011-05-20 15:15:34 -0500251
252 /// <summary>
253 /// Writes a double field value, including tag, to the stream.
254 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500255 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500256 {
257 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
258 WriteDoubleNoTag(value);
259 }
260
261 /// <summary>
262 /// Writes a float field value, including tag, to the stream.
263 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500264 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500265 {
266 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
267 WriteFloatNoTag(value);
268 }
269
270 /// <summary>
271 /// Writes a uint64 field value, including tag, to the stream.
272 /// </summary>
273 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500274 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500275 {
276 WriteTag(fieldNumber, WireFormat.WireType.Varint);
277 WriteRawVarint64(value);
278 }
279
280 /// <summary>
281 /// Writes an int64 field value, including tag, to the stream.
282 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500283 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500284 {
285 WriteTag(fieldNumber, WireFormat.WireType.Varint);
286 WriteRawVarint64((ulong) value);
287 }
288
289 /// <summary>
290 /// Writes an int32 field value, including tag, to the stream.
291 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500292 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500293 {
294 WriteTag(fieldNumber, WireFormat.WireType.Varint);
295 if (value >= 0)
296 {
297 WriteRawVarint32((uint) value);
298 }
299 else
300 {
301 // Must sign-extend.
302 WriteRawVarint64((ulong) value);
303 }
304 }
305
306 /// <summary>
307 /// Writes a fixed64 field value, including tag, to the stream.
308 /// </summary>
309 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500310 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500311 {
312 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
313 WriteRawLittleEndian64(value);
314 }
315
316 /// <summary>
317 /// Writes a fixed32 field value, including tag, to the stream.
318 /// </summary>
319 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500320 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500321 {
322 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
323 WriteRawLittleEndian32(value);
324 }
325
326 /// <summary>
327 /// Writes a bool field value, including tag, to the stream.
328 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500329 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500330 {
331 WriteTag(fieldNumber, WireFormat.WireType.Varint);
332 WriteRawByte(value ? (byte) 1 : (byte) 0);
333 }
334
335 /// <summary>
336 /// Writes a string field value, including tag, to the stream.
337 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500338 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500339 {
340 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
341 // Optimise the case where we have enough space to write
342 // the string directly to the buffer, which should be common.
343 int length = Encoding.UTF8.GetByteCount(value);
344 WriteRawVarint32((uint) length);
345 if (limit - position >= length)
346 {
347 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
348 position += length;
349 }
350 else
351 {
352 byte[] bytes = Encoding.UTF8.GetBytes(value);
353 WriteRawBytes(bytes);
354 }
355 }
356
357 /// <summary>
358 /// Writes a group field value, including tag, to the stream.
359 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500360 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500361 {
362 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
363 value.WriteTo(this);
364 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
365 }
366
csharptest90922db2011-06-03 11:57:47 -0500367 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500368 {
369 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
370 WriteRawVarint32((uint) value.SerializedSize);
371 value.WriteTo(this);
372 }
373
csharptest90922db2011-06-03 11:57:47 -0500374 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500375 {
csharptest71f662c2011-05-20 15:15:34 -0500376 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500377 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500378 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500379 }
380
381 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500382 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500383 {
384 WriteTag(fieldNumber, WireFormat.WireType.Varint);
385 WriteRawVarint32(value);
386 }
387
csharptest304ff3a2011-08-05 16:51:49 -0500388 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500389 {
390 WriteTag(fieldNumber, WireFormat.WireType.Varint);
csharptesta105eac2011-09-09 13:39:54 -0500391 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500392 }
393
csharptest90922db2011-06-03 11:57:47 -0500394 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500395 {
396 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
397 WriteRawLittleEndian32((uint) value);
398 }
399
csharptest90922db2011-06-03 11:57:47 -0500400 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500401 {
402 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
403 WriteRawLittleEndian64((ulong) value);
404 }
405
csharptest90922db2011-06-03 11:57:47 -0500406 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500407 {
408 WriteTag(fieldNumber, WireFormat.WireType.Varint);
409 WriteRawVarint32(EncodeZigZag32(value));
410 }
411
csharptest90922db2011-06-03 11:57:47 -0500412 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500413 {
414 WriteTag(fieldNumber, WireFormat.WireType.Varint);
415 WriteRawVarint64(EncodeZigZag64(value));
416 }
417
csharptest90922db2011-06-03 11:57:47 -0500418 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500419 {
420 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500421 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
422 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500423 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
424 }
425
csharptestffafdaa2011-06-03 12:58:14 -0500426 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500427 {
428 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500429 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
430 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500431 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
432 }
csharptest90922db2011-06-03 11:57:47 -0500433
csharptestb00ea132011-06-10 01:09:57 -0500434 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500435
csharptestb00ea132011-06-10 01:09:57 -0500436 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500437
438 public void WriteFieldNoTag(FieldType fieldType, object value)
439 {
440 switch (fieldType)
441 {
csharptestc671a4b2011-06-08 11:51:24 -0500442 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500443 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500444 break;
csharptestc671a4b2011-06-08 11:51:24 -0500445 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500446 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500447 break;
csharptestc671a4b2011-06-08 11:51:24 -0500448 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500449 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500450 break;
csharptestc671a4b2011-06-08 11:51:24 -0500451 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500452 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500453 break;
454 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500455 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500456 break;
457 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500458 if (value is Enum)
459 {
460 WriteEnumNoTag((int) value);
461 }
csharptestc671a4b2011-06-08 11:51:24 -0500462 else
csharptest74c5e0c2011-07-14 13:06:22 -0500463 {
464 WriteEnumNoTag(((IEnumLite) value).Number);
465 }
csharptest71f662c2011-05-20 15:15:34 -0500466 break;
467 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500468 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500469 break;
csharptestc671a4b2011-06-08 11:51:24 -0500470 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500471 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500472 break;
473 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500474 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500475 break;
csharptestc671a4b2011-06-08 11:51:24 -0500476 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500477 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500478 break;
479 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500480 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500481 break;
482 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500483 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500484 break;
csharptestc671a4b2011-06-08 11:51:24 -0500485 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500486 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500487 break;
488 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500489 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500490 break;
491 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500492 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500493 break;
494 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500495 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500496 break;
497 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500498 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500499 break;
500 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500501 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500502 break;
503 }
504 }
505
csharptest71f662c2011-05-20 15:15:34 -0500506 /// <summary>
507 /// Writes a double field value, including tag, to the stream.
508 /// </summary>
509 public void WriteDoubleNoTag(double value)
510 {
csharptest71f662c2011-05-20 15:15:34 -0500511#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500512 byte[] rawBytes = BitConverter.GetBytes(value);
513 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500514 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500515
516 if (limit - position >= 8)
517 {
518 buffer[position++] = rawBytes[0];
519 buffer[position++] = rawBytes[1];
520 buffer[position++] = rawBytes[2];
521 buffer[position++] = rawBytes[3];
522 buffer[position++] = rawBytes[4];
523 buffer[position++] = rawBytes[5];
524 buffer[position++] = rawBytes[6];
525 buffer[position++] = rawBytes[7];
526 }
527 else
528 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500529#else
csharptest74c5e0c2011-07-14 13:06:22 -0500530 WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500531#endif
532 }
533
534 /// <summary>
535 /// Writes a float field value, without a tag, to the stream.
536 /// </summary>
537 public void WriteFloatNoTag(float value)
538 {
csharptest71f662c2011-05-20 15:15:34 -0500539 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500540 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500541 {
csharptestaef072a2011-06-08 18:00:43 -0500542 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500543 }
csharptest2772dfe2011-06-08 15:50:58 -0500544
545 if (limit - position >= 4)
546 {
547 buffer[position++] = rawBytes[0];
548 buffer[position++] = rawBytes[1];
549 buffer[position++] = rawBytes[2];
550 buffer[position++] = rawBytes[3];
551 }
552 else
csharptest74c5e0c2011-07-14 13:06:22 -0500553 {
csharptest2772dfe2011-06-08 15:50:58 -0500554 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500555 }
csharptest71f662c2011-05-20 15:15:34 -0500556 }
557
558 /// <summary>
559 /// Writes a uint64 field value, without a tag, to the stream.
560 /// </summary>
561 [CLSCompliant(false)]
562 public void WriteUInt64NoTag(ulong value)
563 {
564 WriteRawVarint64(value);
565 }
566
567 /// <summary>
568 /// Writes an int64 field value, without a tag, to the stream.
569 /// </summary>
570 public void WriteInt64NoTag(long value)
571 {
csharptest74c5e0c2011-07-14 13:06:22 -0500572 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500573 }
574
575 /// <summary>
576 /// Writes an int32 field value, without a tag, to the stream.
577 /// </summary>
578 public void WriteInt32NoTag(int value)
579 {
580 if (value >= 0)
581 {
csharptest74c5e0c2011-07-14 13:06:22 -0500582 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500583 }
584 else
585 {
586 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500587 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500588 }
589 }
590
591 /// <summary>
592 /// Writes a fixed64 field value, without a tag, to the stream.
593 /// </summary>
594 [CLSCompliant(false)]
595 public void WriteFixed64NoTag(ulong value)
596 {
597 WriteRawLittleEndian64(value);
598 }
599
600 /// <summary>
601 /// Writes a fixed32 field value, without a tag, to the stream.
602 /// </summary>
603 [CLSCompliant(false)]
604 public void WriteFixed32NoTag(uint value)
605 {
606 WriteRawLittleEndian32(value);
607 }
608
609 /// <summary>
610 /// Writes a bool field value, without a tag, to the stream.
611 /// </summary>
612 public void WriteBoolNoTag(bool value)
613 {
csharptest74c5e0c2011-07-14 13:06:22 -0500614 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500615 }
616
617 /// <summary>
618 /// Writes a string field value, without a tag, to the stream.
619 /// </summary>
620 public void WriteStringNoTag(string value)
621 {
622 // Optimise the case where we have enough space to write
623 // the string directly to the buffer, which should be common.
624 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500625 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500626 if (limit - position >= length)
627 {
628 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
629 position += length;
630 }
631 else
632 {
633 byte[] bytes = Encoding.UTF8.GetBytes(value);
634 WriteRawBytes(bytes);
635 }
636 }
637
638 /// <summary>
639 /// Writes a group field value, without a tag, to the stream.
640 /// </summary>
641 public void WriteGroupNoTag(IMessageLite value)
642 {
643 value.WriteTo(this);
644 }
645
646 public void WriteMessageNoTag(IMessageLite value)
647 {
csharptest74c5e0c2011-07-14 13:06:22 -0500648 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500649 value.WriteTo(this);
650 }
651
652 public void WriteBytesNoTag(ByteString value)
653 {
csharptest74c5e0c2011-07-14 13:06:22 -0500654 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500655 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500656 }
657
658 [CLSCompliant(false)]
659 public void WriteUInt32NoTag(uint value)
660 {
661 WriteRawVarint32(value);
662 }
663
664 public void WriteEnumNoTag(int value)
665 {
csharptesta105eac2011-09-09 13:39:54 -0500666 WriteInt32NoTag(value);
csharptest71f662c2011-05-20 15:15:34 -0500667 }
668
669 public void WriteSFixed32NoTag(int value)
670 {
csharptest74c5e0c2011-07-14 13:06:22 -0500671 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500672 }
673
674 public void WriteSFixed64NoTag(long value)
675 {
csharptest74c5e0c2011-07-14 13:06:22 -0500676 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500677 }
678
679 public void WriteSInt32NoTag(int value)
680 {
681 WriteRawVarint32(EncodeZigZag32(value));
682 }
683
684 public void WriteSInt64NoTag(long value)
685 {
686 WriteRawVarint64(EncodeZigZag64(value));
687 }
688
689 #endregion
690
csharptestb00ea132011-06-10 01:09:57 -0500691 #region Write array members
692
csharptest74c5e0c2011-07-14 13:06:22 -0500693 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500694 {
695 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500696 {
csharptestb00ea132011-06-10 01:09:57 -0500697 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500698 }
csharptestb00ea132011-06-10 01:09:57 -0500699 }
700
701 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
702 where T : IMessageLite
703 {
704 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500705 {
csharptestb00ea132011-06-10 01:09:57 -0500706 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500707 }
csharptestb00ea132011-06-10 01:09:57 -0500708 }
709
710 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
711 where T : IMessageLite
712 {
713 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500714 {
csharptestb00ea132011-06-10 01:09:57 -0500715 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500716 }
csharptestb00ea132011-06-10 01:09:57 -0500717 }
718
719 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
720 {
721 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500722 {
csharptestb00ea132011-06-10 01:09:57 -0500723 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500724 }
csharptestb00ea132011-06-10 01:09:57 -0500725 }
726
727 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
728 {
729 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500730 {
csharptestb00ea132011-06-10 01:09:57 -0500731 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500732 }
csharptestb00ea132011-06-10 01:09:57 -0500733 }
734
735 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
736 {
737 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500738 {
csharptestb00ea132011-06-10 01:09:57 -0500739 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500740 }
csharptestb00ea132011-06-10 01:09:57 -0500741 }
742
743 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
744 {
745 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500746 {
csharptestb00ea132011-06-10 01:09:57 -0500747 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500748 }
csharptestb00ea132011-06-10 01:09:57 -0500749 }
750
751 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
752 {
753 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500754 {
csharptestb00ea132011-06-10 01:09:57 -0500755 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500756 }
csharptestb00ea132011-06-10 01:09:57 -0500757 }
758
759 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
760 {
761 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500762 {
csharptestb00ea132011-06-10 01:09:57 -0500763 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500764 }
csharptestb00ea132011-06-10 01:09:57 -0500765 }
766
767 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
768 {
769 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500770 {
csharptestb00ea132011-06-10 01:09:57 -0500771 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500772 }
csharptestb00ea132011-06-10 01:09:57 -0500773 }
774
775 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
776 {
777 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500778 {
csharptestb00ea132011-06-10 01:09:57 -0500779 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500780 }
csharptestb00ea132011-06-10 01:09:57 -0500781 }
782
783 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
784 {
785 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500786 {
csharptestb00ea132011-06-10 01:09:57 -0500787 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500788 }
csharptestb00ea132011-06-10 01:09:57 -0500789 }
790
791 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
792 {
793 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500794 {
csharptestb00ea132011-06-10 01:09:57 -0500795 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500796 }
csharptestb00ea132011-06-10 01:09:57 -0500797 }
798
799 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
800 {
801 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500802 {
csharptestb00ea132011-06-10 01:09:57 -0500803 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500804 }
csharptestb00ea132011-06-10 01:09:57 -0500805 }
806
807 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
808 {
809 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500810 {
csharptestb00ea132011-06-10 01:09:57 -0500811 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500812 }
csharptestb00ea132011-06-10 01:09:57 -0500813 }
814
815 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
816 {
817 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500818 {
csharptestb00ea132011-06-10 01:09:57 -0500819 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500820 }
csharptestb00ea132011-06-10 01:09:57 -0500821 }
822
823 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
824 {
825 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500826 {
csharptestb00ea132011-06-10 01:09:57 -0500827 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500828 }
csharptestb00ea132011-06-10 01:09:57 -0500829 }
830
831 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
832 {
833 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500834 {
csharptestb00ea132011-06-10 01:09:57 -0500835 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500836 }
csharptestb00ea132011-06-10 01:09:57 -0500837 }
838
839 [CLSCompliant(false)]
840 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
841 where T : struct, IComparable, IFormattable, IConvertible
842 {
843 if (list is ICastArray)
844 {
csharptest74c5e0c2011-07-14 13:06:22 -0500845 foreach (int value in ((ICastArray) list).CastArray<int>())
846 {
csharptestb00ea132011-06-10 01:09:57 -0500847 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500848 }
csharptestb00ea132011-06-10 01:09:57 -0500849 }
850 else
851 {
852 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500853 {
csharptestb00ea132011-06-10 01:09:57 -0500854 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500855 }
csharptestb00ea132011-06-10 01:09:57 -0500856 }
857 }
858
859 #endregion
860
861 #region Write packed array members
862
csharptest74c5e0c2011-07-14 13:06:22 -0500863 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500864 {
865 int calculatedSize = 0;
866 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500867 {
868 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
869 }
csharptestb00ea132011-06-10 01:09:57 -0500870
871 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500872 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500873
874 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500875 {
csharptestb00ea132011-06-10 01:09:57 -0500876 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500877 }
csharptestb00ea132011-06-10 01:09:57 -0500878 }
879
880 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
881 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 WriteGroupNoTag(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 WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
892 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500893 where T : IMessageLite
894 {
895 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500896 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500897 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500898 {
csharptestb00ea132011-06-10 01:09:57 -0500899 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500900 }
csharptestb00ea132011-06-10 01:09:57 -0500901 }
902
csharptest74c5e0c2011-07-14 13:06:22 -0500903 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
904 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500905 {
906 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500907 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500908 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500909 {
csharptestb00ea132011-06-10 01:09:57 -0500910 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500911 }
csharptestb00ea132011-06-10 01:09:57 -0500912 }
913
csharptest74c5e0c2011-07-14 13:06:22 -0500914 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
915 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500916 {
917 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500918 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500919 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500920 {
csharptestb00ea132011-06-10 01:09:57 -0500921 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500922 }
csharptestb00ea132011-06-10 01:09:57 -0500923 }
924
925 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
926 {
927 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500928 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500929 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500930 {
csharptestb00ea132011-06-10 01:09:57 -0500931 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500932 }
csharptestb00ea132011-06-10 01:09:57 -0500933 }
934
935 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
936 {
937 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500938 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500939 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500940 {
csharptestb00ea132011-06-10 01:09:57 -0500941 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500942 }
csharptestb00ea132011-06-10 01:09:57 -0500943 }
944
945 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
946 {
947 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500948 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500949 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500950 {
csharptestb00ea132011-06-10 01:09:57 -0500951 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500952 }
csharptestb00ea132011-06-10 01:09:57 -0500953 }
954
955 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
956 {
957 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500958 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500959 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500960 {
csharptestb00ea132011-06-10 01:09:57 -0500961 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500962 }
csharptestb00ea132011-06-10 01:09:57 -0500963 }
964
csharptest74c5e0c2011-07-14 13:06:22 -0500965 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
966 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500967 {
968 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500969 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500970 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500971 {
csharptestb00ea132011-06-10 01:09:57 -0500972 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500973 }
csharptestb00ea132011-06-10 01:09:57 -0500974 }
975
csharptest74c5e0c2011-07-14 13:06:22 -0500976 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
977 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500978 {
979 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500980 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500981 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500982 {
csharptestb00ea132011-06-10 01:09:57 -0500983 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500984 }
csharptestb00ea132011-06-10 01:09:57 -0500985 }
986
987 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
988 {
989 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500990 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500991 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500992 {
csharptestb00ea132011-06-10 01:09:57 -0500993 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500994 }
csharptestb00ea132011-06-10 01:09:57 -0500995 }
996
997 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
998 {
999 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001000 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001001 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001002 {
csharptestb00ea132011-06-10 01:09:57 -05001003 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001004 }
csharptestb00ea132011-06-10 01:09:57 -05001005 }
1006
csharptest74c5e0c2011-07-14 13:06:22 -05001007 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
1008 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001009 {
1010 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001011 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001012 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001013 {
csharptestb00ea132011-06-10 01:09:57 -05001014 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001015 }
csharptestb00ea132011-06-10 01:09:57 -05001016 }
1017
csharptest74c5e0c2011-07-14 13:06:22 -05001018 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1019 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001020 {
1021 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001022 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001023 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001024 {
csharptestb00ea132011-06-10 01:09:57 -05001025 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001026 }
csharptestb00ea132011-06-10 01:09:57 -05001027 }
1028
csharptest74c5e0c2011-07-14 13:06:22 -05001029 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1030 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001031 {
1032 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001033 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001034 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001035 {
csharptestb00ea132011-06-10 01:09:57 -05001036 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001037 }
csharptestb00ea132011-06-10 01:09:57 -05001038 }
1039
csharptest74c5e0c2011-07-14 13:06:22 -05001040 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1041 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001042 {
1043 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001044 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001045 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001046 {
csharptestb00ea132011-06-10 01:09:57 -05001047 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001048 }
csharptestb00ea132011-06-10 01:09:57 -05001049 }
1050
1051 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1052 {
1053 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001054 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001055 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001056 {
csharptestb00ea132011-06-10 01:09:57 -05001057 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001058 }
csharptestb00ea132011-06-10 01:09:57 -05001059 }
1060
1061 [CLSCompliant(false)]
1062 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1063 where T : struct, IComparable, IFormattable, IConvertible
1064 {
1065 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001066 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001067 if (list is ICastArray)
1068 {
csharptest74c5e0c2011-07-14 13:06:22 -05001069 foreach (int value in ((ICastArray) list).CastArray<int>())
1070 {
csharptestb00ea132011-06-10 01:09:57 -05001071 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001072 }
csharptestb00ea132011-06-10 01:09:57 -05001073 }
1074 else
1075 {
1076 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001077 {
1078 WriteEnumNoTag((int) value);
1079 }
csharptestb00ea132011-06-10 01:09:57 -05001080 }
1081 }
1082
1083 #endregion
1084
csharptest71f662c2011-05-20 15:15:34 -05001085 #region Underlying writing primitives
1086
1087 /// <summary>
1088 /// Encodes and writes a tag.
1089 /// </summary>
1090 [CLSCompliant(false)]
1091 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1092 {
1093 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1094 }
1095
csharptest71f662c2011-05-20 15:15:34 -05001096 /// <summary>
1097 /// Writes a 32 bit value as a varint. The fast route is taken when
1098 /// there's enough buffer space left to whizz through without checking
1099 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1100 /// </summary>
1101 [CLSCompliant(false)]
1102 public void WriteRawVarint32(uint value)
1103 {
csharptestc671a4b2011-06-08 11:51:24 -05001104 while (value > 127 && position < limit)
1105 {
csharptest74c5e0c2011-07-14 13:06:22 -05001106 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001107 value >>= 7;
1108 }
1109 while (value > 127)
1110 {
csharptest74c5e0c2011-07-14 13:06:22 -05001111 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001112 value >>= 7;
1113 }
csharptest74c5e0c2011-07-14 13:06:22 -05001114 if (position < limit)
1115 {
1116 buffer[position++] = (byte) value;
1117 }
csharptestc671a4b2011-06-08 11:51:24 -05001118 else
csharptest74c5e0c2011-07-14 13:06:22 -05001119 {
1120 WriteRawByte((byte) value);
1121 }
csharptest71f662c2011-05-20 15:15:34 -05001122 }
1123
1124 [CLSCompliant(false)]
1125 public void WriteRawVarint64(ulong value)
1126 {
csharptestc671a4b2011-06-08 11:51:24 -05001127 while (value > 127 && position < limit)
1128 {
csharptest74c5e0c2011-07-14 13:06:22 -05001129 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001130 value >>= 7;
1131 }
1132 while (value > 127)
1133 {
csharptest74c5e0c2011-07-14 13:06:22 -05001134 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001135 value >>= 7;
1136 }
csharptest74c5e0c2011-07-14 13:06:22 -05001137 if (position < limit)
1138 {
1139 buffer[position++] = (byte) value;
1140 }
csharptestc671a4b2011-06-08 11:51:24 -05001141 else
csharptest74c5e0c2011-07-14 13:06:22 -05001142 {
1143 WriteRawByte((byte) value);
1144 }
csharptest71f662c2011-05-20 15:15:34 -05001145 }
1146
1147 [CLSCompliant(false)]
1148 public void WriteRawLittleEndian32(uint value)
1149 {
csharptestc671a4b2011-06-08 11:51:24 -05001150 if (position + 4 > limit)
1151 {
1152 WriteRawByte((byte) value);
1153 WriteRawByte((byte) (value >> 8));
1154 WriteRawByte((byte) (value >> 16));
1155 WriteRawByte((byte) (value >> 24));
1156 }
1157 else
1158 {
csharptest74c5e0c2011-07-14 13:06:22 -05001159 buffer[position++] = ((byte) value);
1160 buffer[position++] = ((byte) (value >> 8));
1161 buffer[position++] = ((byte) (value >> 16));
1162 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001163 }
csharptest71f662c2011-05-20 15:15:34 -05001164 }
1165
1166 [CLSCompliant(false)]
1167 public void WriteRawLittleEndian64(ulong value)
1168 {
csharptestc671a4b2011-06-08 11:51:24 -05001169 if (position + 8 > limit)
1170 {
1171 WriteRawByte((byte) value);
1172 WriteRawByte((byte) (value >> 8));
1173 WriteRawByte((byte) (value >> 16));
1174 WriteRawByte((byte) (value >> 24));
1175 WriteRawByte((byte) (value >> 32));
1176 WriteRawByte((byte) (value >> 40));
1177 WriteRawByte((byte) (value >> 48));
1178 WriteRawByte((byte) (value >> 56));
1179 }
1180 else
1181 {
csharptest74c5e0c2011-07-14 13:06:22 -05001182 buffer[position++] = ((byte) value);
1183 buffer[position++] = ((byte) (value >> 8));
1184 buffer[position++] = ((byte) (value >> 16));
1185 buffer[position++] = ((byte) (value >> 24));
1186 buffer[position++] = ((byte) (value >> 32));
1187 buffer[position++] = ((byte) (value >> 40));
1188 buffer[position++] = ((byte) (value >> 48));
1189 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001190 }
csharptest71f662c2011-05-20 15:15:34 -05001191 }
1192
1193 public void WriteRawByte(byte value)
1194 {
1195 if (position == limit)
1196 {
1197 RefreshBuffer();
1198 }
1199
1200 buffer[position++] = value;
1201 }
1202
1203 [CLSCompliant(false)]
1204 public void WriteRawByte(uint value)
1205 {
1206 WriteRawByte((byte) value);
1207 }
1208
1209 /// <summary>
1210 /// Writes out an array of bytes.
1211 /// </summary>
1212 public void WriteRawBytes(byte[] value)
1213 {
1214 WriteRawBytes(value, 0, value.Length);
1215 }
1216
1217 /// <summary>
1218 /// Writes out part of an array of bytes.
1219 /// </summary>
1220 public void WriteRawBytes(byte[] value, int offset, int length)
1221 {
1222 if (limit - position >= length)
1223 {
csharptestaef072a2011-06-08 18:00:43 -05001224 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001225 // We have room in the current buffer.
1226 position += length;
1227 }
1228 else
1229 {
1230 // Write extends past current buffer. Fill the rest of this buffer and
1231 // flush.
1232 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001233 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001234 offset += bytesWritten;
1235 length -= bytesWritten;
1236 position = limit;
1237 RefreshBuffer();
1238
1239 // Now deal with the rest.
1240 // Since we have an output stream, this is our buffer
1241 // and buffer offset == 0
1242 if (length <= limit)
1243 {
1244 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001245 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001246 position = length;
1247 }
1248 else
1249 {
1250 // Write is very big. Let's do it all at once.
1251 output.Write(value, offset, length);
1252 }
1253 }
1254 }
1255
1256 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001257
csharptest71f662c2011-05-20 15:15:34 -05001258 /// <summary>
1259 /// Encode a 32-bit value with ZigZag encoding.
1260 /// </summary>
1261 /// <remarks>
1262 /// ZigZag encodes signed integers into values that can be efficiently
1263 /// encoded with varint. (Otherwise, negative values must be
1264 /// sign-extended to 64 bits to be varint encoded, thus always taking
1265 /// 10 bytes on the wire.)
1266 /// </remarks>
1267 [CLSCompliant(false)]
1268 public static uint EncodeZigZag32(int n)
1269 {
1270 // Note: the right-shift must be arithmetic
1271 return (uint) ((n << 1) ^ (n >> 31));
1272 }
1273
1274 /// <summary>
1275 /// Encode a 64-bit value with ZigZag encoding.
1276 /// </summary>
1277 /// <remarks>
1278 /// ZigZag encodes signed integers into values that can be efficiently
1279 /// encoded with varint. (Otherwise, negative values must be
1280 /// sign-extended to 64 bits to be varint encoded, thus always taking
1281 /// 10 bytes on the wire.)
1282 /// </remarks>
1283 [CLSCompliant(false)]
1284 public static ulong EncodeZigZag64(long n)
1285 {
1286 return (ulong) ((n << 1) ^ (n >> 63));
1287 }
1288
1289 private void RefreshBuffer()
1290 {
1291 if (output == null)
1292 {
1293 // We're writing to a single buffer.
1294 throw new OutOfSpaceException();
1295 }
1296
1297 // Since we have an output stream, this is our buffer
1298 // and buffer offset == 0
1299 output.Write(buffer, 0, position);
1300 position = 0;
1301 }
1302
1303 /// <summary>
1304 /// Indicates that a CodedOutputStream wrapping a flat byte array
1305 /// ran out of space.
1306 /// </summary>
1307 public sealed class OutOfSpaceException : IOException
1308 {
1309 internal OutOfSpaceException()
1310 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1311 {
1312 }
1313 }
1314
1315 public void Flush()
1316 {
1317 if (output != null)
1318 {
1319 RefreshBuffer();
1320 }
1321 }
1322
1323 /// <summary>
1324 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1325 /// that is exactly big enough to hold a message, then write to it with
1326 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1327 /// the message was actually as big as expected, which can help bugs.
1328 /// </summary>
1329 public void CheckNoSpaceLeft()
1330 {
1331 if (SpaceLeft != 0)
1332 {
1333 throw new InvalidOperationException("Did not write as much data as expected.");
1334 }
1335 }
1336
1337 /// <summary>
1338 /// If writing to a flat array, returns the space left in the array. Otherwise,
1339 /// throws an InvalidOperationException.
1340 /// </summary>
1341 public int SpaceLeft
1342 {
1343 get
1344 {
1345 if (output == null)
1346 {
1347 return limit - position;
1348 }
1349 else
1350 {
1351 throw new InvalidOperationException(
1352 "SpaceLeft can only be called on CodedOutputStreams that are " +
1353 "writing to a flat array.");
1354 }
1355 }
1356 }
1357 }
1358}