blob: 560719afa3f5e8586378083e3b32080ba53b1d29 [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc. All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15// * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19// * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
csharptest74c5e0c2011-07-14 13:06:22 -050038using System.Collections;
csharptestc671a4b2011-06-08 11:51:24 -050039using System.Collections.Generic;
csharptest71f662c2011-05-20 15:15:34 -050040using System.IO;
41using System.Text;
csharptestced18e12011-06-09 19:47:56 -050042using Google.ProtocolBuffers.Collections;
csharptest71f662c2011-05-20 15:15:34 -050043using Google.ProtocolBuffers.Descriptors;
44
45namespace Google.ProtocolBuffers
46{
47 /// <summary>
48 /// Encodes and writes protocol message fields.
49 /// </summary>
50 /// <remarks>
51 /// This class contains two kinds of methods: methods that write specific
52 /// protocol message constructs and field types (e.g. WriteTag and
53 /// WriteInt32) and methods that write low-level values (e.g.
54 /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
55 /// messages, you should use the former methods, but if you are writing some
56 /// other format of your own design, use the latter. The names of the former
57 /// methods are taken from the protocol buffer type names, not .NET types.
58 /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
59 /// </remarks>
csharptest819b7152011-09-08 20:28:22 -050060 public sealed partial class CodedOutputStream : ICodedOutputStream, IDisposable
csharptest71f662c2011-05-20 15:15:34 -050061 {
62 /// <summary>
63 /// The buffer size used by CreateInstance(Stream).
64 /// </summary>
65 public static readonly int DefaultBufferSize = 4096;
66
67 private readonly byte[] buffer;
68 private readonly int limit;
69 private int position;
70 private readonly Stream output;
71
72 #region Construction
73
74 private CodedOutputStream(byte[] buffer, int offset, int length)
75 {
76 this.output = null;
77 this.buffer = buffer;
78 this.position = offset;
79 this.limit = offset + length;
80 }
81
82 private CodedOutputStream(Stream output, byte[] buffer)
83 {
84 this.output = output;
85 this.buffer = buffer;
86 this.position = 0;
87 this.limit = buffer.Length;
88 }
89
90 /// <summary>
91 /// Creates a new CodedOutputStream which write to the given stream.
92 /// </summary>
93 public static CodedOutputStream CreateInstance(Stream output)
94 {
95 return CreateInstance(output, DefaultBufferSize);
96 }
97
98 /// <summary>
99 /// Creates a new CodedOutputStream which write to the given stream and uses
100 /// the specified buffer size.
101 /// </summary>
102 public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
103 {
104 return new CodedOutputStream(output, new byte[bufferSize]);
105 }
106
107 /// <summary>
108 /// Creates a new CodedOutputStream that writes directly to the given
109 /// byte array. If more bytes are written than fit in the array,
110 /// OutOfSpaceException will be thrown.
111 /// </summary>
112 public static CodedOutputStream CreateInstance(byte[] flatArray)
113 {
114 return CreateInstance(flatArray, 0, flatArray.Length);
115 }
116
117 /// <summary>
118 /// Creates a new CodedOutputStream that writes directly to the given
119 /// byte array slice. If more bytes are written than fit in the array,
120 /// OutOfSpaceException will be thrown.
121 /// </summary>
122 public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
123 {
124 return new CodedOutputStream(flatArray, offset, length);
125 }
126
127 #endregion
csharptest819b7152011-09-08 20:28:22 -0500128
129 public void Dispose()
130 {
131 if (output != null)
132 {
133 if (position > 0)
134 Flush();
135 output.Dispose();
136 }
137 }
csharptest71f662c2011-05-20 15:15:34 -0500138
csharptest60fd7732011-09-09 12:18:16 -0500139 void ICodedOutputStream.WriteMessageStart() { }
140 void ICodedOutputStream.WriteMessageEnd() { Flush(); }
141
csharptest2b868842011-06-10 14:41:47 -0500142 #region Writing of unknown fields
143
144 [Obsolete]
145 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
146 {
147 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
148 value.WriteTo(this);
149 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
150 }
151
152 public void WriteUnknownBytes(int fieldNumber, ByteString value)
153 {
154 WriteBytes(fieldNumber, null /*not used*/, value);
155 }
156
157 [CLSCompliant(false)]
158 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
159 {
csharptest74c5e0c2011-07-14 13:06:22 -0500160 if (wireType == WireFormat.WireType.Varint)
161 {
csharptest2b868842011-06-10 14:41:47 -0500162 WriteUInt64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500163 }
csharptest2b868842011-06-10 14:41:47 -0500164 else if (wireType == WireFormat.WireType.Fixed32)
csharptest74c5e0c2011-07-14 13:06:22 -0500165 {
166 WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
167 }
csharptest2b868842011-06-10 14:41:47 -0500168 else if (wireType == WireFormat.WireType.Fixed64)
csharptest74c5e0c2011-07-14 13:06:22 -0500169 {
csharptest2b868842011-06-10 14:41:47 -0500170 WriteFixed64(fieldNumber, null /*not used*/, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500171 }
csharptest2b868842011-06-10 14:41:47 -0500172 else
csharptest74c5e0c2011-07-14 13:06:22 -0500173 {
csharptest2b868842011-06-10 14:41:47 -0500174 throw InvalidProtocolBufferException.InvalidWireType();
csharptest74c5e0c2011-07-14 13:06:22 -0500175 }
csharptest2b868842011-06-10 14:41:47 -0500176 }
177
178 #endregion
179
csharptestb00ea132011-06-10 01:09:57 -0500180 #region Writing of tags and fields
181
182 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
183 {
184 switch (fieldType)
185 {
186 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500187 WriteString(fieldNumber, fieldName, (string) value);
csharptestb00ea132011-06-10 01:09:57 -0500188 break;
189 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500190 WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500191 break;
192 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500193 WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
csharptestb00ea132011-06-10 01:09:57 -0500194 break;
195 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500196 WriteBytes(fieldNumber, fieldName, (ByteString) value);
csharptestb00ea132011-06-10 01:09:57 -0500197 break;
198 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500199 WriteBool(fieldNumber, fieldName, (bool) value);
csharptestb00ea132011-06-10 01:09:57 -0500200 break;
201 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500202 if (value is Enum)
203 {
204 WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
205 }
csharptestb00ea132011-06-10 01:09:57 -0500206 else
csharptest74c5e0c2011-07-14 13:06:22 -0500207 {
208 WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
209 }
csharptestb00ea132011-06-10 01:09:57 -0500210 break;
211 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500212 WriteInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500213 break;
214 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500215 WriteInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500216 break;
217 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500218 WriteUInt32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500219 break;
220 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500221 WriteUInt64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500222 break;
223 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500224 WriteSInt32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500225 break;
226 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500227 WriteSInt64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500228 break;
229 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500230 WriteFixed32(fieldNumber, fieldName, (uint) value);
csharptestb00ea132011-06-10 01:09:57 -0500231 break;
232 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500233 WriteFixed64(fieldNumber, fieldName, (ulong) value);
csharptestb00ea132011-06-10 01:09:57 -0500234 break;
235 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500236 WriteSFixed32(fieldNumber, fieldName, (int) value);
csharptestb00ea132011-06-10 01:09:57 -0500237 break;
238 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500239 WriteSFixed64(fieldNumber, fieldName, (long) value);
csharptestb00ea132011-06-10 01:09:57 -0500240 break;
241 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500242 WriteDouble(fieldNumber, fieldName, (double) value);
csharptestb00ea132011-06-10 01:09:57 -0500243 break;
244 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500245 WriteFloat(fieldNumber, fieldName, (float) value);
csharptestb00ea132011-06-10 01:09:57 -0500246 break;
247 }
248 }
csharptest71f662c2011-05-20 15:15:34 -0500249
250 /// <summary>
251 /// Writes a double field value, including tag, to the stream.
252 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500253 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500254 {
255 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
256 WriteDoubleNoTag(value);
257 }
258
259 /// <summary>
260 /// Writes a float field value, including tag, to the stream.
261 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500262 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500263 {
264 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
265 WriteFloatNoTag(value);
266 }
267
268 /// <summary>
269 /// Writes a uint64 field value, including tag, to the stream.
270 /// </summary>
271 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500272 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500273 {
274 WriteTag(fieldNumber, WireFormat.WireType.Varint);
275 WriteRawVarint64(value);
276 }
277
278 /// <summary>
279 /// Writes an int64 field value, including tag, to the stream.
280 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500281 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500282 {
283 WriteTag(fieldNumber, WireFormat.WireType.Varint);
284 WriteRawVarint64((ulong) value);
285 }
286
287 /// <summary>
288 /// Writes an int32 field value, including tag, to the stream.
289 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500290 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500291 {
292 WriteTag(fieldNumber, WireFormat.WireType.Varint);
293 if (value >= 0)
294 {
295 WriteRawVarint32((uint) value);
296 }
297 else
298 {
299 // Must sign-extend.
300 WriteRawVarint64((ulong) value);
301 }
302 }
303
304 /// <summary>
305 /// Writes a fixed64 field value, including tag, to the stream.
306 /// </summary>
307 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500308 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500309 {
310 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
311 WriteRawLittleEndian64(value);
312 }
313
314 /// <summary>
315 /// Writes a fixed32 field value, including tag, to the stream.
316 /// </summary>
317 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500318 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500319 {
320 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
321 WriteRawLittleEndian32(value);
322 }
323
324 /// <summary>
325 /// Writes a bool field value, including tag, to the stream.
326 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500327 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500328 {
329 WriteTag(fieldNumber, WireFormat.WireType.Varint);
330 WriteRawByte(value ? (byte) 1 : (byte) 0);
331 }
332
333 /// <summary>
334 /// Writes a string field value, including tag, to the stream.
335 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500336 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500337 {
338 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
339 // Optimise the case where we have enough space to write
340 // the string directly to the buffer, which should be common.
341 int length = Encoding.UTF8.GetByteCount(value);
342 WriteRawVarint32((uint) length);
343 if (limit - position >= length)
344 {
345 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
346 position += length;
347 }
348 else
349 {
350 byte[] bytes = Encoding.UTF8.GetBytes(value);
351 WriteRawBytes(bytes);
352 }
353 }
354
355 /// <summary>
356 /// Writes a group field value, including tag, to the stream.
357 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500358 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500359 {
360 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
361 value.WriteTo(this);
362 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
363 }
364
csharptest90922db2011-06-03 11:57:47 -0500365 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500366 {
367 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
368 WriteRawVarint32((uint) value.SerializedSize);
369 value.WriteTo(this);
370 }
371
csharptest90922db2011-06-03 11:57:47 -0500372 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500373 {
csharptest71f662c2011-05-20 15:15:34 -0500374 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500375 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500376 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500377 }
378
379 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500380 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500381 {
382 WriteTag(fieldNumber, WireFormat.WireType.Varint);
383 WriteRawVarint32(value);
384 }
385
csharptest304ff3a2011-08-05 16:51:49 -0500386 public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
csharptest71f662c2011-05-20 15:15:34 -0500387 {
388 WriteTag(fieldNumber, WireFormat.WireType.Varint);
389 WriteRawVarint32((uint) value);
390 }
391
csharptest90922db2011-06-03 11:57:47 -0500392 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500393 {
394 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
395 WriteRawLittleEndian32((uint) value);
396 }
397
csharptest90922db2011-06-03 11:57:47 -0500398 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500399 {
400 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
401 WriteRawLittleEndian64((ulong) value);
402 }
403
csharptest90922db2011-06-03 11:57:47 -0500404 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500405 {
406 WriteTag(fieldNumber, WireFormat.WireType.Varint);
407 WriteRawVarint32(EncodeZigZag32(value));
408 }
409
csharptest90922db2011-06-03 11:57:47 -0500410 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500411 {
412 WriteTag(fieldNumber, WireFormat.WireType.Varint);
413 WriteRawVarint64(EncodeZigZag64(value));
414 }
415
csharptest90922db2011-06-03 11:57:47 -0500416 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500417 {
418 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500419 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
420 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500421 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
422 }
423
csharptestffafdaa2011-06-03 12:58:14 -0500424 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500425 {
426 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500427 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
428 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500429 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
430 }
csharptest90922db2011-06-03 11:57:47 -0500431
csharptestb00ea132011-06-10 01:09:57 -0500432 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500433
csharptestb00ea132011-06-10 01:09:57 -0500434 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500435
436 public void WriteFieldNoTag(FieldType fieldType, object value)
437 {
438 switch (fieldType)
439 {
csharptestc671a4b2011-06-08 11:51:24 -0500440 case FieldType.String:
csharptest74c5e0c2011-07-14 13:06:22 -0500441 WriteStringNoTag((string) value);
csharptest71f662c2011-05-20 15:15:34 -0500442 break;
csharptestc671a4b2011-06-08 11:51:24 -0500443 case FieldType.Message:
csharptest74c5e0c2011-07-14 13:06:22 -0500444 WriteMessageNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500445 break;
csharptestc671a4b2011-06-08 11:51:24 -0500446 case FieldType.Group:
csharptest74c5e0c2011-07-14 13:06:22 -0500447 WriteGroupNoTag((IMessageLite) value);
csharptest71f662c2011-05-20 15:15:34 -0500448 break;
csharptestc671a4b2011-06-08 11:51:24 -0500449 case FieldType.Bytes:
csharptest74c5e0c2011-07-14 13:06:22 -0500450 WriteBytesNoTag((ByteString) value);
csharptestc671a4b2011-06-08 11:51:24 -0500451 break;
452 case FieldType.Bool:
csharptest74c5e0c2011-07-14 13:06:22 -0500453 WriteBoolNoTag((bool) value);
csharptestc671a4b2011-06-08 11:51:24 -0500454 break;
455 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500456 if (value is Enum)
457 {
458 WriteEnumNoTag((int) value);
459 }
csharptestc671a4b2011-06-08 11:51:24 -0500460 else
csharptest74c5e0c2011-07-14 13:06:22 -0500461 {
462 WriteEnumNoTag(((IEnumLite) value).Number);
463 }
csharptest71f662c2011-05-20 15:15:34 -0500464 break;
465 case FieldType.Int32:
csharptest74c5e0c2011-07-14 13:06:22 -0500466 WriteInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500467 break;
csharptestc671a4b2011-06-08 11:51:24 -0500468 case FieldType.Int64:
csharptest74c5e0c2011-07-14 13:06:22 -0500469 WriteInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500470 break;
471 case FieldType.UInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500472 WriteUInt32NoTag((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500473 break;
csharptestc671a4b2011-06-08 11:51:24 -0500474 case FieldType.UInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500475 WriteUInt64NoTag((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500476 break;
477 case FieldType.SInt32:
csharptest74c5e0c2011-07-14 13:06:22 -0500478 WriteSInt32NoTag((int) value);
csharptest71f662c2011-05-20 15:15:34 -0500479 break;
480 case FieldType.SInt64:
csharptest74c5e0c2011-07-14 13:06:22 -0500481 WriteSInt64NoTag((long) value);
csharptest71f662c2011-05-20 15:15:34 -0500482 break;
csharptestc671a4b2011-06-08 11:51:24 -0500483 case FieldType.Fixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500484 WriteFixed32NoTag((uint) value);
csharptestc671a4b2011-06-08 11:51:24 -0500485 break;
486 case FieldType.Fixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500487 WriteFixed64NoTag((ulong) value);
csharptestc671a4b2011-06-08 11:51:24 -0500488 break;
489 case FieldType.SFixed32:
csharptest74c5e0c2011-07-14 13:06:22 -0500490 WriteSFixed32NoTag((int) value);
csharptestc671a4b2011-06-08 11:51:24 -0500491 break;
492 case FieldType.SFixed64:
csharptest74c5e0c2011-07-14 13:06:22 -0500493 WriteSFixed64NoTag((long) value);
csharptestc671a4b2011-06-08 11:51:24 -0500494 break;
495 case FieldType.Double:
csharptest74c5e0c2011-07-14 13:06:22 -0500496 WriteDoubleNoTag((double) value);
csharptestc671a4b2011-06-08 11:51:24 -0500497 break;
498 case FieldType.Float:
csharptest74c5e0c2011-07-14 13:06:22 -0500499 WriteFloatNoTag((float) value);
csharptest71f662c2011-05-20 15:15:34 -0500500 break;
501 }
502 }
503
csharptest71f662c2011-05-20 15:15:34 -0500504 /// <summary>
505 /// Writes a double field value, including tag, to the stream.
506 /// </summary>
507 public void WriteDoubleNoTag(double value)
508 {
csharptest71f662c2011-05-20 15:15:34 -0500509#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500510 byte[] rawBytes = BitConverter.GetBytes(value);
511 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500512 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500513
514 if (limit - position >= 8)
515 {
516 buffer[position++] = rawBytes[0];
517 buffer[position++] = rawBytes[1];
518 buffer[position++] = rawBytes[2];
519 buffer[position++] = rawBytes[3];
520 buffer[position++] = rawBytes[4];
521 buffer[position++] = rawBytes[5];
522 buffer[position++] = rawBytes[6];
523 buffer[position++] = rawBytes[7];
524 }
525 else
526 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500527#else
csharptest74c5e0c2011-07-14 13:06:22 -0500528 WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500529#endif
530 }
531
532 /// <summary>
533 /// Writes a float field value, without a tag, to the stream.
534 /// </summary>
535 public void WriteFloatNoTag(float value)
536 {
csharptest71f662c2011-05-20 15:15:34 -0500537 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500538 if (!BitConverter.IsLittleEndian)
csharptest74c5e0c2011-07-14 13:06:22 -0500539 {
csharptestaef072a2011-06-08 18:00:43 -0500540 ByteArray.Reverse(rawBytes);
csharptest74c5e0c2011-07-14 13:06:22 -0500541 }
csharptest2772dfe2011-06-08 15:50:58 -0500542
543 if (limit - position >= 4)
544 {
545 buffer[position++] = rawBytes[0];
546 buffer[position++] = rawBytes[1];
547 buffer[position++] = rawBytes[2];
548 buffer[position++] = rawBytes[3];
549 }
550 else
csharptest74c5e0c2011-07-14 13:06:22 -0500551 {
csharptest2772dfe2011-06-08 15:50:58 -0500552 WriteRawBytes(rawBytes, 0, 4);
csharptest74c5e0c2011-07-14 13:06:22 -0500553 }
csharptest71f662c2011-05-20 15:15:34 -0500554 }
555
556 /// <summary>
557 /// Writes a uint64 field value, without a tag, to the stream.
558 /// </summary>
559 [CLSCompliant(false)]
560 public void WriteUInt64NoTag(ulong value)
561 {
562 WriteRawVarint64(value);
563 }
564
565 /// <summary>
566 /// Writes an int64 field value, without a tag, to the stream.
567 /// </summary>
568 public void WriteInt64NoTag(long value)
569 {
csharptest74c5e0c2011-07-14 13:06:22 -0500570 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500571 }
572
573 /// <summary>
574 /// Writes an int32 field value, without a tag, to the stream.
575 /// </summary>
576 public void WriteInt32NoTag(int value)
577 {
578 if (value >= 0)
579 {
csharptest74c5e0c2011-07-14 13:06:22 -0500580 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500581 }
582 else
583 {
584 // Must sign-extend.
csharptest74c5e0c2011-07-14 13:06:22 -0500585 WriteRawVarint64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500586 }
587 }
588
589 /// <summary>
590 /// Writes a fixed64 field value, without a tag, to the stream.
591 /// </summary>
592 [CLSCompliant(false)]
593 public void WriteFixed64NoTag(ulong value)
594 {
595 WriteRawLittleEndian64(value);
596 }
597
598 /// <summary>
599 /// Writes a fixed32 field value, without a tag, to the stream.
600 /// </summary>
601 [CLSCompliant(false)]
602 public void WriteFixed32NoTag(uint value)
603 {
604 WriteRawLittleEndian32(value);
605 }
606
607 /// <summary>
608 /// Writes a bool field value, without a tag, to the stream.
609 /// </summary>
610 public void WriteBoolNoTag(bool value)
611 {
csharptest74c5e0c2011-07-14 13:06:22 -0500612 WriteRawByte(value ? (byte) 1 : (byte) 0);
csharptest71f662c2011-05-20 15:15:34 -0500613 }
614
615 /// <summary>
616 /// Writes a string field value, without a tag, to the stream.
617 /// </summary>
618 public void WriteStringNoTag(string value)
619 {
620 // Optimise the case where we have enough space to write
621 // the string directly to the buffer, which should be common.
622 int length = Encoding.UTF8.GetByteCount(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500623 WriteRawVarint32((uint) length);
csharptest71f662c2011-05-20 15:15:34 -0500624 if (limit - position >= length)
625 {
626 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
627 position += length;
628 }
629 else
630 {
631 byte[] bytes = Encoding.UTF8.GetBytes(value);
632 WriteRawBytes(bytes);
633 }
634 }
635
636 /// <summary>
637 /// Writes a group field value, without a tag, to the stream.
638 /// </summary>
639 public void WriteGroupNoTag(IMessageLite value)
640 {
641 value.WriteTo(this);
642 }
643
644 public void WriteMessageNoTag(IMessageLite value)
645 {
csharptest74c5e0c2011-07-14 13:06:22 -0500646 WriteRawVarint32((uint) value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500647 value.WriteTo(this);
648 }
649
650 public void WriteBytesNoTag(ByteString value)
651 {
csharptest74c5e0c2011-07-14 13:06:22 -0500652 WriteRawVarint32((uint) value.Length);
csharptested701ad2011-07-14 13:20:11 -0500653 value.WriteRawBytesTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500654 }
655
656 [CLSCompliant(false)]
657 public void WriteUInt32NoTag(uint value)
658 {
659 WriteRawVarint32(value);
660 }
661
662 public void WriteEnumNoTag(int value)
663 {
csharptest74c5e0c2011-07-14 13:06:22 -0500664 WriteRawVarint32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500665 }
666
667 public void WriteSFixed32NoTag(int value)
668 {
csharptest74c5e0c2011-07-14 13:06:22 -0500669 WriteRawLittleEndian32((uint) value);
csharptest71f662c2011-05-20 15:15:34 -0500670 }
671
672 public void WriteSFixed64NoTag(long value)
673 {
csharptest74c5e0c2011-07-14 13:06:22 -0500674 WriteRawLittleEndian64((ulong) value);
csharptest71f662c2011-05-20 15:15:34 -0500675 }
676
677 public void WriteSInt32NoTag(int value)
678 {
679 WriteRawVarint32(EncodeZigZag32(value));
680 }
681
682 public void WriteSInt64NoTag(long value)
683 {
684 WriteRawVarint64(EncodeZigZag64(value));
685 }
686
687 #endregion
688
csharptestb00ea132011-06-10 01:09:57 -0500689 #region Write array members
690
csharptest74c5e0c2011-07-14 13:06:22 -0500691 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500692 {
693 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500694 {
csharptestb00ea132011-06-10 01:09:57 -0500695 WriteField(fieldType, fieldNumber, fieldName, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500696 }
csharptestb00ea132011-06-10 01:09:57 -0500697 }
698
699 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
700 where T : IMessageLite
701 {
702 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500703 {
csharptestb00ea132011-06-10 01:09:57 -0500704 WriteGroup(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500705 }
csharptestb00ea132011-06-10 01:09:57 -0500706 }
707
708 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
709 where T : IMessageLite
710 {
711 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500712 {
csharptestb00ea132011-06-10 01:09:57 -0500713 WriteMessage(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500714 }
csharptestb00ea132011-06-10 01:09:57 -0500715 }
716
717 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
718 {
719 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500720 {
csharptestb00ea132011-06-10 01:09:57 -0500721 WriteString(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500722 }
csharptestb00ea132011-06-10 01:09:57 -0500723 }
724
725 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
726 {
727 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500728 {
csharptestb00ea132011-06-10 01:09:57 -0500729 WriteBytes(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500730 }
csharptestb00ea132011-06-10 01:09:57 -0500731 }
732
733 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
734 {
735 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500736 {
csharptestb00ea132011-06-10 01:09:57 -0500737 WriteBool(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500738 }
csharptestb00ea132011-06-10 01:09:57 -0500739 }
740
741 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
742 {
743 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500744 {
csharptestb00ea132011-06-10 01:09:57 -0500745 WriteInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500746 }
csharptestb00ea132011-06-10 01:09:57 -0500747 }
748
749 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
750 {
751 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500752 {
csharptestb00ea132011-06-10 01:09:57 -0500753 WriteSInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500754 }
csharptestb00ea132011-06-10 01:09:57 -0500755 }
756
757 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
758 {
759 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500760 {
csharptestb00ea132011-06-10 01:09:57 -0500761 WriteUInt32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500762 }
csharptestb00ea132011-06-10 01:09:57 -0500763 }
764
765 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
766 {
767 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500768 {
csharptestb00ea132011-06-10 01:09:57 -0500769 WriteFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500770 }
csharptestb00ea132011-06-10 01:09:57 -0500771 }
772
773 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
774 {
775 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500776 {
csharptestb00ea132011-06-10 01:09:57 -0500777 WriteSFixed32(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500778 }
csharptestb00ea132011-06-10 01:09:57 -0500779 }
780
781 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
782 {
783 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500784 {
csharptestb00ea132011-06-10 01:09:57 -0500785 WriteInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500786 }
csharptestb00ea132011-06-10 01:09:57 -0500787 }
788
789 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
790 {
791 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500792 {
csharptestb00ea132011-06-10 01:09:57 -0500793 WriteSInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500794 }
csharptestb00ea132011-06-10 01:09:57 -0500795 }
796
797 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
798 {
799 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500800 {
csharptestb00ea132011-06-10 01:09:57 -0500801 WriteUInt64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500802 }
csharptestb00ea132011-06-10 01:09:57 -0500803 }
804
805 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
806 {
807 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500808 {
csharptestb00ea132011-06-10 01:09:57 -0500809 WriteFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500810 }
csharptestb00ea132011-06-10 01:09:57 -0500811 }
812
813 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
814 {
815 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500816 {
csharptestb00ea132011-06-10 01:09:57 -0500817 WriteSFixed64(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500818 }
csharptestb00ea132011-06-10 01:09:57 -0500819 }
820
821 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
822 {
823 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500824 {
csharptestb00ea132011-06-10 01:09:57 -0500825 WriteDouble(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500826 }
csharptestb00ea132011-06-10 01:09:57 -0500827 }
828
829 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
830 {
831 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500832 {
csharptestb00ea132011-06-10 01:09:57 -0500833 WriteFloat(fieldNumber, fieldName, value);
csharptest74c5e0c2011-07-14 13:06:22 -0500834 }
csharptestb00ea132011-06-10 01:09:57 -0500835 }
836
837 [CLSCompliant(false)]
838 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
839 where T : struct, IComparable, IFormattable, IConvertible
840 {
841 if (list is ICastArray)
842 {
csharptest74c5e0c2011-07-14 13:06:22 -0500843 foreach (int value in ((ICastArray) list).CastArray<int>())
844 {
csharptestb00ea132011-06-10 01:09:57 -0500845 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500846 }
csharptestb00ea132011-06-10 01:09:57 -0500847 }
848 else
849 {
850 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500851 {
csharptestb00ea132011-06-10 01:09:57 -0500852 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
csharptest74c5e0c2011-07-14 13:06:22 -0500853 }
csharptestb00ea132011-06-10 01:09:57 -0500854 }
855 }
856
857 #endregion
858
859 #region Write packed array members
860
csharptest74c5e0c2011-07-14 13:06:22 -0500861 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
csharptestb00ea132011-06-10 01:09:57 -0500862 {
863 int calculatedSize = 0;
864 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500865 {
866 calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
867 }
csharptestb00ea132011-06-10 01:09:57 -0500868
869 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500870 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500871
872 foreach (object element in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500873 {
csharptestb00ea132011-06-10 01:09:57 -0500874 WriteFieldNoTag(fieldType, element);
csharptest74c5e0c2011-07-14 13:06:22 -0500875 }
csharptestb00ea132011-06-10 01:09:57 -0500876 }
877
878 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
879 where T : IMessageLite
880 {
881 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500882 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500883 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500884 {
csharptestb00ea132011-06-10 01:09:57 -0500885 WriteGroupNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500886 }
csharptestb00ea132011-06-10 01:09:57 -0500887 }
888
csharptest74c5e0c2011-07-14 13:06:22 -0500889 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
890 IEnumerable<T> list)
csharptestb00ea132011-06-10 01:09:57 -0500891 where T : IMessageLite
892 {
893 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500894 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500895 foreach (IMessageLite value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500896 {
csharptestb00ea132011-06-10 01:09:57 -0500897 WriteMessageNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500898 }
csharptestb00ea132011-06-10 01:09:57 -0500899 }
900
csharptest74c5e0c2011-07-14 13:06:22 -0500901 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
902 IEnumerable<string> list)
csharptestb00ea132011-06-10 01:09:57 -0500903 {
904 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500905 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500906 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500907 {
csharptestb00ea132011-06-10 01:09:57 -0500908 WriteStringNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500909 }
csharptestb00ea132011-06-10 01:09:57 -0500910 }
911
csharptest74c5e0c2011-07-14 13:06:22 -0500912 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
913 IEnumerable<ByteString> list)
csharptestb00ea132011-06-10 01:09:57 -0500914 {
915 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500916 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500917 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500918 {
csharptestb00ea132011-06-10 01:09:57 -0500919 WriteBytesNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500920 }
csharptestb00ea132011-06-10 01:09:57 -0500921 }
922
923 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
924 {
925 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500926 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500927 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500928 {
csharptestb00ea132011-06-10 01:09:57 -0500929 WriteBoolNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500930 }
csharptestb00ea132011-06-10 01:09:57 -0500931 }
932
933 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
934 {
935 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500936 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500937 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500938 {
csharptestb00ea132011-06-10 01:09:57 -0500939 WriteInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500940 }
csharptestb00ea132011-06-10 01:09:57 -0500941 }
942
943 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
944 {
945 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500946 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500947 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500948 {
csharptestb00ea132011-06-10 01:09:57 -0500949 WriteSInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500950 }
csharptestb00ea132011-06-10 01:09:57 -0500951 }
952
953 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
954 {
955 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500956 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500957 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500958 {
csharptestb00ea132011-06-10 01:09:57 -0500959 WriteUInt32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500960 }
csharptestb00ea132011-06-10 01:09:57 -0500961 }
962
csharptest74c5e0c2011-07-14 13:06:22 -0500963 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
964 IEnumerable<uint> list)
csharptestb00ea132011-06-10 01:09:57 -0500965 {
966 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500967 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500968 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500969 {
csharptestb00ea132011-06-10 01:09:57 -0500970 WriteFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500971 }
csharptestb00ea132011-06-10 01:09:57 -0500972 }
973
csharptest74c5e0c2011-07-14 13:06:22 -0500974 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
975 IEnumerable<int> list)
csharptestb00ea132011-06-10 01:09:57 -0500976 {
977 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500978 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500979 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500980 {
csharptestb00ea132011-06-10 01:09:57 -0500981 WriteSFixed32NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500982 }
csharptestb00ea132011-06-10 01:09:57 -0500983 }
984
985 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
986 {
987 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500988 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500989 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -0500990 {
csharptestb00ea132011-06-10 01:09:57 -0500991 WriteInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -0500992 }
csharptestb00ea132011-06-10 01:09:57 -0500993 }
994
995 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
996 {
997 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -0500998 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -0500999 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001000 {
csharptestb00ea132011-06-10 01:09:57 -05001001 WriteSInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001002 }
csharptestb00ea132011-06-10 01:09:57 -05001003 }
1004
csharptest74c5e0c2011-07-14 13:06:22 -05001005 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
1006 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001007 {
1008 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001009 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001010 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001011 {
csharptestb00ea132011-06-10 01:09:57 -05001012 WriteUInt64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001013 }
csharptestb00ea132011-06-10 01:09:57 -05001014 }
1015
csharptest74c5e0c2011-07-14 13:06:22 -05001016 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1017 IEnumerable<ulong> list)
csharptestb00ea132011-06-10 01:09:57 -05001018 {
1019 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001020 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001021 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001022 {
csharptestb00ea132011-06-10 01:09:57 -05001023 WriteFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001024 }
csharptestb00ea132011-06-10 01:09:57 -05001025 }
1026
csharptest74c5e0c2011-07-14 13:06:22 -05001027 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1028 IEnumerable<long> list)
csharptestb00ea132011-06-10 01:09:57 -05001029 {
1030 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001031 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001032 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001033 {
csharptestb00ea132011-06-10 01:09:57 -05001034 WriteSFixed64NoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001035 }
csharptestb00ea132011-06-10 01:09:57 -05001036 }
1037
csharptest74c5e0c2011-07-14 13:06:22 -05001038 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1039 IEnumerable<double> list)
csharptestb00ea132011-06-10 01:09:57 -05001040 {
1041 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001042 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001043 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001044 {
csharptestb00ea132011-06-10 01:09:57 -05001045 WriteDoubleNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001046 }
csharptestb00ea132011-06-10 01:09:57 -05001047 }
1048
1049 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1050 {
1051 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001052 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001053 foreach (var value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001054 {
csharptestb00ea132011-06-10 01:09:57 -05001055 WriteFloatNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001056 }
csharptestb00ea132011-06-10 01:09:57 -05001057 }
1058
1059 [CLSCompliant(false)]
1060 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1061 where T : struct, IComparable, IFormattable, IConvertible
1062 {
1063 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest74c5e0c2011-07-14 13:06:22 -05001064 WriteRawVarint32((uint) calculatedSize);
csharptestb00ea132011-06-10 01:09:57 -05001065 if (list is ICastArray)
1066 {
csharptest74c5e0c2011-07-14 13:06:22 -05001067 foreach (int value in ((ICastArray) list).CastArray<int>())
1068 {
csharptestb00ea132011-06-10 01:09:57 -05001069 WriteEnumNoTag(value);
csharptest74c5e0c2011-07-14 13:06:22 -05001070 }
csharptestb00ea132011-06-10 01:09:57 -05001071 }
1072 else
1073 {
1074 foreach (object value in list)
csharptest74c5e0c2011-07-14 13:06:22 -05001075 {
1076 WriteEnumNoTag((int) value);
1077 }
csharptestb00ea132011-06-10 01:09:57 -05001078 }
1079 }
1080
1081 #endregion
1082
csharptest71f662c2011-05-20 15:15:34 -05001083 #region Underlying writing primitives
1084
1085 /// <summary>
1086 /// Encodes and writes a tag.
1087 /// </summary>
1088 [CLSCompliant(false)]
1089 public void WriteTag(int fieldNumber, WireFormat.WireType type)
1090 {
1091 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1092 }
1093
csharptest71f662c2011-05-20 15:15:34 -05001094 /// <summary>
1095 /// Writes a 32 bit value as a varint. The fast route is taken when
1096 /// there's enough buffer space left to whizz through without checking
1097 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1098 /// </summary>
1099 [CLSCompliant(false)]
1100 public void WriteRawVarint32(uint value)
1101 {
csharptestc671a4b2011-06-08 11:51:24 -05001102 while (value > 127 && position < limit)
1103 {
csharptest74c5e0c2011-07-14 13:06:22 -05001104 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001105 value >>= 7;
1106 }
1107 while (value > 127)
1108 {
csharptest74c5e0c2011-07-14 13:06:22 -05001109 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001110 value >>= 7;
1111 }
csharptest74c5e0c2011-07-14 13:06:22 -05001112 if (position < limit)
1113 {
1114 buffer[position++] = (byte) value;
1115 }
csharptestc671a4b2011-06-08 11:51:24 -05001116 else
csharptest74c5e0c2011-07-14 13:06:22 -05001117 {
1118 WriteRawByte((byte) value);
1119 }
csharptest71f662c2011-05-20 15:15:34 -05001120 }
1121
1122 [CLSCompliant(false)]
1123 public void WriteRawVarint64(ulong value)
1124 {
csharptestc671a4b2011-06-08 11:51:24 -05001125 while (value > 127 && position < limit)
1126 {
csharptest74c5e0c2011-07-14 13:06:22 -05001127 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
csharptestc671a4b2011-06-08 11:51:24 -05001128 value >>= 7;
1129 }
1130 while (value > 127)
1131 {
csharptest74c5e0c2011-07-14 13:06:22 -05001132 WriteRawByte((byte) ((value & 0x7F) | 0x80));
csharptestc671a4b2011-06-08 11:51:24 -05001133 value >>= 7;
1134 }
csharptest74c5e0c2011-07-14 13:06:22 -05001135 if (position < limit)
1136 {
1137 buffer[position++] = (byte) value;
1138 }
csharptestc671a4b2011-06-08 11:51:24 -05001139 else
csharptest74c5e0c2011-07-14 13:06:22 -05001140 {
1141 WriteRawByte((byte) value);
1142 }
csharptest71f662c2011-05-20 15:15:34 -05001143 }
1144
1145 [CLSCompliant(false)]
1146 public void WriteRawLittleEndian32(uint value)
1147 {
csharptestc671a4b2011-06-08 11:51:24 -05001148 if (position + 4 > limit)
1149 {
1150 WriteRawByte((byte) value);
1151 WriteRawByte((byte) (value >> 8));
1152 WriteRawByte((byte) (value >> 16));
1153 WriteRawByte((byte) (value >> 24));
1154 }
1155 else
1156 {
csharptest74c5e0c2011-07-14 13:06:22 -05001157 buffer[position++] = ((byte) value);
1158 buffer[position++] = ((byte) (value >> 8));
1159 buffer[position++] = ((byte) (value >> 16));
1160 buffer[position++] = ((byte) (value >> 24));
csharptestc671a4b2011-06-08 11:51:24 -05001161 }
csharptest71f662c2011-05-20 15:15:34 -05001162 }
1163
1164 [CLSCompliant(false)]
1165 public void WriteRawLittleEndian64(ulong value)
1166 {
csharptestc671a4b2011-06-08 11:51:24 -05001167 if (position + 8 > limit)
1168 {
1169 WriteRawByte((byte) value);
1170 WriteRawByte((byte) (value >> 8));
1171 WriteRawByte((byte) (value >> 16));
1172 WriteRawByte((byte) (value >> 24));
1173 WriteRawByte((byte) (value >> 32));
1174 WriteRawByte((byte) (value >> 40));
1175 WriteRawByte((byte) (value >> 48));
1176 WriteRawByte((byte) (value >> 56));
1177 }
1178 else
1179 {
csharptest74c5e0c2011-07-14 13:06:22 -05001180 buffer[position++] = ((byte) value);
1181 buffer[position++] = ((byte) (value >> 8));
1182 buffer[position++] = ((byte) (value >> 16));
1183 buffer[position++] = ((byte) (value >> 24));
1184 buffer[position++] = ((byte) (value >> 32));
1185 buffer[position++] = ((byte) (value >> 40));
1186 buffer[position++] = ((byte) (value >> 48));
1187 buffer[position++] = ((byte) (value >> 56));
csharptestc671a4b2011-06-08 11:51:24 -05001188 }
csharptest71f662c2011-05-20 15:15:34 -05001189 }
1190
1191 public void WriteRawByte(byte value)
1192 {
1193 if (position == limit)
1194 {
1195 RefreshBuffer();
1196 }
1197
1198 buffer[position++] = value;
1199 }
1200
1201 [CLSCompliant(false)]
1202 public void WriteRawByte(uint value)
1203 {
1204 WriteRawByte((byte) value);
1205 }
1206
1207 /// <summary>
1208 /// Writes out an array of bytes.
1209 /// </summary>
1210 public void WriteRawBytes(byte[] value)
1211 {
1212 WriteRawBytes(value, 0, value.Length);
1213 }
1214
1215 /// <summary>
1216 /// Writes out part of an array of bytes.
1217 /// </summary>
1218 public void WriteRawBytes(byte[] value, int offset, int length)
1219 {
1220 if (limit - position >= length)
1221 {
csharptestaef072a2011-06-08 18:00:43 -05001222 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001223 // We have room in the current buffer.
1224 position += length;
1225 }
1226 else
1227 {
1228 // Write extends past current buffer. Fill the rest of this buffer and
1229 // flush.
1230 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001231 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001232 offset += bytesWritten;
1233 length -= bytesWritten;
1234 position = limit;
1235 RefreshBuffer();
1236
1237 // Now deal with the rest.
1238 // Since we have an output stream, this is our buffer
1239 // and buffer offset == 0
1240 if (length <= limit)
1241 {
1242 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001243 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001244 position = length;
1245 }
1246 else
1247 {
1248 // Write is very big. Let's do it all at once.
1249 output.Write(value, offset, length);
1250 }
1251 }
1252 }
1253
1254 #endregion
csharptest74c5e0c2011-07-14 13:06:22 -05001255
csharptest71f662c2011-05-20 15:15:34 -05001256 /// <summary>
1257 /// Encode a 32-bit value with ZigZag encoding.
1258 /// </summary>
1259 /// <remarks>
1260 /// ZigZag encodes signed integers into values that can be efficiently
1261 /// encoded with varint. (Otherwise, negative values must be
1262 /// sign-extended to 64 bits to be varint encoded, thus always taking
1263 /// 10 bytes on the wire.)
1264 /// </remarks>
1265 [CLSCompliant(false)]
1266 public static uint EncodeZigZag32(int n)
1267 {
1268 // Note: the right-shift must be arithmetic
1269 return (uint) ((n << 1) ^ (n >> 31));
1270 }
1271
1272 /// <summary>
1273 /// Encode a 64-bit value with ZigZag encoding.
1274 /// </summary>
1275 /// <remarks>
1276 /// ZigZag encodes signed integers into values that can be efficiently
1277 /// encoded with varint. (Otherwise, negative values must be
1278 /// sign-extended to 64 bits to be varint encoded, thus always taking
1279 /// 10 bytes on the wire.)
1280 /// </remarks>
1281 [CLSCompliant(false)]
1282 public static ulong EncodeZigZag64(long n)
1283 {
1284 return (ulong) ((n << 1) ^ (n >> 63));
1285 }
1286
1287 private void RefreshBuffer()
1288 {
1289 if (output == null)
1290 {
1291 // We're writing to a single buffer.
1292 throw new OutOfSpaceException();
1293 }
1294
1295 // Since we have an output stream, this is our buffer
1296 // and buffer offset == 0
1297 output.Write(buffer, 0, position);
1298 position = 0;
1299 }
1300
1301 /// <summary>
1302 /// Indicates that a CodedOutputStream wrapping a flat byte array
1303 /// ran out of space.
1304 /// </summary>
1305 public sealed class OutOfSpaceException : IOException
1306 {
1307 internal OutOfSpaceException()
1308 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1309 {
1310 }
1311 }
1312
1313 public void Flush()
1314 {
1315 if (output != null)
1316 {
1317 RefreshBuffer();
1318 }
1319 }
1320
1321 /// <summary>
1322 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1323 /// that is exactly big enough to hold a message, then write to it with
1324 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1325 /// the message was actually as big as expected, which can help bugs.
1326 /// </summary>
1327 public void CheckNoSpaceLeft()
1328 {
1329 if (SpaceLeft != 0)
1330 {
1331 throw new InvalidOperationException("Did not write as much data as expected.");
1332 }
1333 }
1334
1335 /// <summary>
1336 /// If writing to a flat array, returns the space left in the array. Otherwise,
1337 /// throws an InvalidOperationException.
1338 /// </summary>
1339 public int SpaceLeft
1340 {
1341 get
1342 {
1343 if (output == null)
1344 {
1345 return limit - position;
1346 }
1347 else
1348 {
1349 throw new InvalidOperationException(
1350 "SpaceLeft can only be called on CodedOutputStreams that are " +
1351 "writing to a flat array.");
1352 }
1353 }
1354 }
1355 }
1356}