blob: ef197d8f9b90126baddf7e4af824dbce303ffb1d [file] [log] [blame]
csharptestcc8d2aa2011-06-03 12:15:42 -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;
38using System.Globalization;
csharptestcc8d2aa2011-06-03 12:15:42 -050039using System.Text;
40using Google.ProtocolBuffers.Descriptors;
41
42namespace Google.ProtocolBuffers
43{
44 /// <summary>
45 /// Encodes and writes protocol message fields.
46 /// </summary>
47 /// <remarks>
48 /// This class contains two kinds of methods: methods that write specific
49 /// protocol message constructs and field types (e.g. WriteTag and
50 /// WriteInt32) and methods that write low-level values (e.g.
51 /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
52 /// messages, you should use the former methods, but if you are writing some
53 /// other format of your own design, use the latter. The names of the former
54 /// methods are taken from the protocol buffer type names, not .NET types.
55 /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
56 /// </remarks>
57 public sealed partial class CodedOutputStream
58 {
59 private const int LittleEndian64Size = 8;
60 private const int LittleEndian32Size = 4;
61
62 /// <summary>
63 /// Compute the number of bytes that would be needed to encode a
64 /// double field, including the tag.
65 /// </summary>
66 public static int ComputeDoubleSize(int fieldNumber, double value)
67 {
68 return ComputeTagSize(fieldNumber) + LittleEndian64Size;
69 }
70
71 /// <summary>
72 /// Compute the number of bytes that would be needed to encode a
73 /// float field, including the tag.
74 /// </summary>
75 public static int ComputeFloatSize(int fieldNumber, float value)
76 {
77 return ComputeTagSize(fieldNumber) + LittleEndian32Size;
78 }
79
80 /// <summary>
81 /// Compute the number of bytes that would be needed to encode a
82 /// uint64 field, including the tag.
83 /// </summary>
84 [CLSCompliant(false)]
85 public static int ComputeUInt64Size(int fieldNumber, ulong value)
86 {
87 return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(value);
88 }
89
90 /// <summary>
91 /// Compute the number of bytes that would be needed to encode an
92 /// int64 field, including the tag.
93 /// </summary>
94 public static int ComputeInt64Size(int fieldNumber, long value)
95 {
96 return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size((ulong) value);
97 }
98
99 /// <summary>
100 /// Compute the number of bytes that would be needed to encode an
101 /// int32 field, including the tag.
102 /// </summary>
103 public static int ComputeInt32Size(int fieldNumber, int value)
104 {
105 if (value >= 0)
106 {
107 return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint) value);
108 }
109 else
110 {
111 // Must sign-extend.
112 return ComputeTagSize(fieldNumber) + 10;
113 }
114 }
115
116 /// <summary>
117 /// Compute the number of bytes that would be needed to encode a
118 /// fixed64 field, including the tag.
119 /// </summary>
120 [CLSCompliant(false)]
121 public static int ComputeFixed64Size(int fieldNumber, ulong value)
122 {
123 return ComputeTagSize(fieldNumber) + LittleEndian64Size;
124 }
125
126 /// <summary>
127 /// Compute the number of bytes that would be needed to encode a
128 /// fixed32 field, including the tag.
129 /// </summary>
130 [CLSCompliant(false)]
131 public static int ComputeFixed32Size(int fieldNumber, uint value)
132 {
133 return ComputeTagSize(fieldNumber) + LittleEndian32Size;
134 }
135
136 /// <summary>
137 /// Compute the number of bytes that would be needed to encode a
138 /// bool field, including the tag.
139 /// </summary>
140 public static int ComputeBoolSize(int fieldNumber, bool value)
141 {
142 return ComputeTagSize(fieldNumber) + 1;
143 }
144
145 /// <summary>
146 /// Compute the number of bytes that would be needed to encode a
147 /// string field, including the tag.
148 /// </summary>
149 public static int ComputeStringSize(int fieldNumber, String value)
150 {
151 int byteArraySize = Encoding.UTF8.GetByteCount(value);
152 return ComputeTagSize(fieldNumber) +
153 ComputeRawVarint32Size((uint) byteArraySize) +
154 byteArraySize;
155 }
156
157 /// <summary>
158 /// Compute the number of bytes that would be needed to encode a
159 /// group field, including the tag.
160 /// </summary>
161 public static int ComputeGroupSize(int fieldNumber, IMessageLite value)
162 {
163 return ComputeTagSize(fieldNumber)*2 + value.SerializedSize;
164 }
165
166 /// <summary>
167 /// Compute the number of bytes that would be needed to encode a
168 /// group field represented by an UnknownFieldSet, including the tag.
169 /// </summary>
170 [Obsolete]
171 public static int ComputeUnknownGroupSize(int fieldNumber,
172 IMessageLite value)
173 {
174 return ComputeTagSize(fieldNumber)*2 + value.SerializedSize;
175 }
176
177 /// <summary>
178 /// Compute the number of bytes that would be needed to encode an
179 /// embedded message field, including the tag.
180 /// </summary>
181 public static int ComputeMessageSize(int fieldNumber, IMessageLite value)
182 {
183 int size = value.SerializedSize;
184 return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint) size) + size;
185 }
186
187 /// <summary>
188 /// Compute the number of bytes that would be needed to encode a
189 /// bytes field, including the tag.
190 /// </summary>
191 public static int ComputeBytesSize(int fieldNumber, ByteString value)
192 {
193 return ComputeTagSize(fieldNumber) +
194 ComputeRawVarint32Size((uint) value.Length) +
195 value.Length;
196 }
197
198 /// <summary>
199 /// Compute the number of bytes that would be needed to encode a
200 /// uint32 field, including the tag.
201 /// </summary>
202 [CLSCompliant(false)]
203 public static int ComputeUInt32Size(int fieldNumber, uint value)
204 {
205 return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(value);
206 }
207
208 /// <summary>
209 /// Compute the number of bytes that would be needed to encode a
210 /// enum field, including the tag. The caller is responsible for
211 /// converting the enum value to its numeric value.
212 /// </summary>
213 public static int ComputeEnumSize(int fieldNumber, int value)
214 {
215 return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint) value);
216 }
217
218 /// <summary>
219 /// Compute the number of bytes that would be needed to encode an
220 /// sfixed32 field, including the tag.
221 /// </summary>
222 public static int ComputeSFixed32Size(int fieldNumber, int value)
223 {
224 return ComputeTagSize(fieldNumber) + LittleEndian32Size;
225 }
226
227 /// <summary>
228 /// Compute the number of bytes that would be needed to encode an
229 /// sfixed64 field, including the tag.
230 /// </summary>
231 public static int ComputeSFixed64Size(int fieldNumber, long value)
232 {
233 return ComputeTagSize(fieldNumber) + LittleEndian64Size;
234 }
235
236 /// <summary>
237 /// Compute the number of bytes that would be needed to encode an
238 /// sint32 field, including the tag.
239 /// </summary>
240 public static int ComputeSInt32Size(int fieldNumber, int value)
241 {
242 return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size(EncodeZigZag32(value));
243 }
244
245 /// <summary>
246 /// Compute the number of bytes that would be needed to encode an
247 /// sint64 field, including the tag.
248 /// </summary>
249 public static int ComputeSInt64Size(int fieldNumber, long value)
250 {
251 return ComputeTagSize(fieldNumber) + ComputeRawVarint64Size(EncodeZigZag64(value));
252 }
253
254 /// <summary>
255 /// Compute the number of bytes that would be needed to encode a
256 /// double field, including the tag.
257 /// </summary>
258 public static int ComputeDoubleSizeNoTag(double value)
259 {
260 return LittleEndian64Size;
261 }
262
263 /// <summary>
264 /// Compute the number of bytes that would be needed to encode a
265 /// float field, including the tag.
266 /// </summary>
267 public static int ComputeFloatSizeNoTag(float value)
268 {
269 return LittleEndian32Size;
270 }
271
272 /// <summary>
273 /// Compute the number of bytes that would be needed to encode a
274 /// uint64 field, including the tag.
275 /// </summary>
276 [CLSCompliant(false)]
277 public static int ComputeUInt64SizeNoTag(ulong value)
278 {
279 return ComputeRawVarint64Size(value);
280 }
281
282 /// <summary>
283 /// Compute the number of bytes that would be needed to encode an
284 /// int64 field, including the tag.
285 /// </summary>
286 public static int ComputeInt64SizeNoTag(long value)
287 {
288 return ComputeRawVarint64Size((ulong) value);
289 }
290
291 /// <summary>
292 /// Compute the number of bytes that would be needed to encode an
293 /// int32 field, including the tag.
294 /// </summary>
295 public static int ComputeInt32SizeNoTag(int value)
296 {
297 if (value >= 0)
298 {
299 return ComputeRawVarint32Size((uint) value);
300 }
301 else
302 {
303 // Must sign-extend.
304 return 10;
305 }
306 }
307
308 /// <summary>
309 /// Compute the number of bytes that would be needed to encode a
310 /// fixed64 field, including the tag.
311 /// </summary>
312 [CLSCompliant(false)]
313 public static int ComputeFixed64SizeNoTag(ulong value)
314 {
315 return LittleEndian64Size;
316 }
317
318 /// <summary>
319 /// Compute the number of bytes that would be needed to encode a
320 /// fixed32 field, including the tag.
321 /// </summary>
322 [CLSCompliant(false)]
323 public static int ComputeFixed32SizeNoTag(uint value)
324 {
325 return LittleEndian32Size;
326 }
327
328 /// <summary>
329 /// Compute the number of bytes that would be needed to encode a
330 /// bool field, including the tag.
331 /// </summary>
332 public static int ComputeBoolSizeNoTag(bool value)
333 {
334 return 1;
335 }
336
337 /// <summary>
338 /// Compute the number of bytes that would be needed to encode a
339 /// string field, including the tag.
340 /// </summary>
341 public static int ComputeStringSizeNoTag(String value)
342 {
343 int byteArraySize = Encoding.UTF8.GetByteCount(value);
344 return ComputeRawVarint32Size((uint) byteArraySize) +
345 byteArraySize;
346 }
347
348 /// <summary>
349 /// Compute the number of bytes that would be needed to encode a
350 /// group field, including the tag.
351 /// </summary>
352 public static int ComputeGroupSizeNoTag(IMessageLite value)
353 {
354 return value.SerializedSize;
355 }
356
357 /// <summary>
358 /// Compute the number of bytes that would be needed to encode a
359 /// group field represented by an UnknownFieldSet, including the tag.
360 /// </summary>
361 [Obsolete]
362 public static int ComputeUnknownGroupSizeNoTag(IMessageLite value)
363 {
364 return value.SerializedSize;
365 }
366
367 /// <summary>
368 /// Compute the number of bytes that would be needed to encode an
369 /// embedded message field, including the tag.
370 /// </summary>
371 public static int ComputeMessageSizeNoTag(IMessageLite value)
372 {
373 int size = value.SerializedSize;
374 return ComputeRawVarint32Size((uint) size) + size;
375 }
376
377 /// <summary>
378 /// Compute the number of bytes that would be needed to encode a
379 /// bytes field, including the tag.
380 /// </summary>
381 public static int ComputeBytesSizeNoTag(ByteString value)
382 {
383 return ComputeRawVarint32Size((uint) value.Length) +
384 value.Length;
385 }
386
387 /// <summary>
388 /// Compute the number of bytes that would be needed to encode a
389 /// uint32 field, including the tag.
390 /// </summary>
391 [CLSCompliant(false)]
392 public static int ComputeUInt32SizeNoTag(uint value)
393 {
394 return ComputeRawVarint32Size(value);
395 }
396
397 /// <summary>
398 /// Compute the number of bytes that would be needed to encode a
399 /// enum field, including the tag. The caller is responsible for
400 /// converting the enum value to its numeric value.
401 /// </summary>
402 public static int ComputeEnumSizeNoTag(int value)
403 {
404 return ComputeRawVarint32Size((uint) value);
405 }
406
407 /// <summary>
408 /// Compute the number of bytes that would be needed to encode an
409 /// sfixed32 field, including the tag.
410 /// </summary>
411 public static int ComputeSFixed32SizeNoTag(int value)
412 {
413 return LittleEndian32Size;
414 }
415
416 /// <summary>
417 /// Compute the number of bytes that would be needed to encode an
418 /// sfixed64 field, including the tag.
419 /// </summary>
420 public static int ComputeSFixed64SizeNoTag(long value)
421 {
422 return LittleEndian64Size;
423 }
424
425 /// <summary>
426 /// Compute the number of bytes that would be needed to encode an
427 /// sint32 field, including the tag.
428 /// </summary>
429 public static int ComputeSInt32SizeNoTag(int value)
430 {
431 return ComputeRawVarint32Size(EncodeZigZag32(value));
432 }
433
434 /// <summary>
435 /// Compute the number of bytes that would be needed to encode an
436 /// sint64 field, including the tag.
437 /// </summary>
438 public static int ComputeSInt64SizeNoTag(long value)
439 {
440 return ComputeRawVarint64Size(EncodeZigZag64(value));
441 }
442
443 /*
444 * Compute the number of bytes that would be needed to encode a
445 * MessageSet extension to the stream. For historical reasons,
446 * the wire format differs from normal fields.
447 */
448
449 /// <summary>
450 /// Compute the number of bytes that would be needed to encode a
451 /// MessageSet extension to the stream. For historical reasons,
452 /// the wire format differs from normal fields.
453 /// </summary>
454 public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessageLite value)
455 {
456 return ComputeTagSize(WireFormat.MessageSetField.Item)*2 +
457 ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
458 ComputeMessageSize(WireFormat.MessageSetField.Message, value);
459 }
460
461 /// <summary>
462 /// Compute the number of bytes that would be needed to encode an
463 /// unparsed MessageSet extension field to the stream. For
464 /// historical reasons, the wire format differs from normal fields.
465 /// </summary>
466 public static int ComputeRawMessageSetExtensionSize(int fieldNumber, ByteString value)
467 {
468 return ComputeTagSize(WireFormat.MessageSetField.Item)*2 +
469 ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
470 ComputeBytesSize(WireFormat.MessageSetField.Message, value);
471 }
472
473 /// <summary>
474 /// Compute the number of bytes that would be needed to encode a varint.
475 /// </summary>
476 [CLSCompliant(false)]
477 public static int ComputeRawVarint32Size(uint value)
478 {
csharptest74c5e0c2011-07-14 13:06:22 -0500479 if ((value & (0xffffffff << 7)) == 0)
480 {
481 return 1;
482 }
483 if ((value & (0xffffffff << 14)) == 0)
484 {
485 return 2;
486 }
487 if ((value & (0xffffffff << 21)) == 0)
488 {
489 return 3;
490 }
491 if ((value & (0xffffffff << 28)) == 0)
492 {
493 return 4;
494 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500495 return 5;
496 }
497
498 /// <summary>
499 /// Compute the number of bytes that would be needed to encode a varint.
500 /// </summary>
501 [CLSCompliant(false)]
502 public static int ComputeRawVarint64Size(ulong value)
503 {
csharptest74c5e0c2011-07-14 13:06:22 -0500504 if ((value & (0xffffffffffffffffL << 7)) == 0)
505 {
506 return 1;
507 }
508 if ((value & (0xffffffffffffffffL << 14)) == 0)
509 {
510 return 2;
511 }
512 if ((value & (0xffffffffffffffffL << 21)) == 0)
513 {
514 return 3;
515 }
516 if ((value & (0xffffffffffffffffL << 28)) == 0)
517 {
518 return 4;
519 }
520 if ((value & (0xffffffffffffffffL << 35)) == 0)
521 {
522 return 5;
523 }
524 if ((value & (0xffffffffffffffffL << 42)) == 0)
525 {
526 return 6;
527 }
528 if ((value & (0xffffffffffffffffL << 49)) == 0)
529 {
530 return 7;
531 }
532 if ((value & (0xffffffffffffffffL << 56)) == 0)
533 {
534 return 8;
535 }
536 if ((value & (0xffffffffffffffffL << 63)) == 0)
537 {
538 return 9;
539 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500540 return 10;
541 }
542
543 /// <summary>
544 /// Compute the number of bytes that would be needed to encode a
545 /// field of arbitrary type, including the tag, to the stream.
546 /// </summary>
547 public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value)
548 {
549 switch (fieldType)
550 {
551 case FieldType.Double:
552 return ComputeDoubleSize(fieldNumber, (double) value);
553 case FieldType.Float:
554 return ComputeFloatSize(fieldNumber, (float) value);
555 case FieldType.Int64:
556 return ComputeInt64Size(fieldNumber, (long) value);
557 case FieldType.UInt64:
558 return ComputeUInt64Size(fieldNumber, (ulong) value);
559 case FieldType.Int32:
560 return ComputeInt32Size(fieldNumber, (int) value);
561 case FieldType.Fixed64:
562 return ComputeFixed64Size(fieldNumber, (ulong) value);
563 case FieldType.Fixed32:
564 return ComputeFixed32Size(fieldNumber, (uint) value);
565 case FieldType.Bool:
566 return ComputeBoolSize(fieldNumber, (bool) value);
567 case FieldType.String:
568 return ComputeStringSize(fieldNumber, (string) value);
569 case FieldType.Group:
570 return ComputeGroupSize(fieldNumber, (IMessageLite) value);
571 case FieldType.Message:
572 return ComputeMessageSize(fieldNumber, (IMessageLite) value);
573 case FieldType.Bytes:
574 return ComputeBytesSize(fieldNumber, (ByteString) value);
575 case FieldType.UInt32:
576 return ComputeUInt32Size(fieldNumber, (uint) value);
577 case FieldType.SFixed32:
578 return ComputeSFixed32Size(fieldNumber, (int) value);
579 case FieldType.SFixed64:
580 return ComputeSFixed64Size(fieldNumber, (long) value);
581 case FieldType.SInt32:
582 return ComputeSInt32Size(fieldNumber, (int) value);
583 case FieldType.SInt64:
584 return ComputeSInt64Size(fieldNumber, (long) value);
585 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500586 if (value is Enum)
587 {
588 return ComputeEnumSize(fieldNumber, ((IConvertible) value).ToInt32(CultureInfo.InvariantCulture));
589 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500590 else
csharptest74c5e0c2011-07-14 13:06:22 -0500591 {
csharptestcc8d2aa2011-06-03 12:15:42 -0500592 return ComputeEnumSize(fieldNumber, ((IEnumLite) value).Number);
csharptest74c5e0c2011-07-14 13:06:22 -0500593 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500594 default:
595 throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
596 }
597 }
598
599 /// <summary>
600 /// Compute the number of bytes that would be needed to encode a
601 /// field of arbitrary type, excluding the tag, to the stream.
602 /// </summary>
603 public static int ComputeFieldSizeNoTag(FieldType fieldType, Object value)
604 {
605 switch (fieldType)
606 {
607 case FieldType.Double:
608 return ComputeDoubleSizeNoTag((double) value);
609 case FieldType.Float:
610 return ComputeFloatSizeNoTag((float) value);
611 case FieldType.Int64:
612 return ComputeInt64SizeNoTag((long) value);
613 case FieldType.UInt64:
614 return ComputeUInt64SizeNoTag((ulong) value);
615 case FieldType.Int32:
616 return ComputeInt32SizeNoTag((int) value);
617 case FieldType.Fixed64:
618 return ComputeFixed64SizeNoTag((ulong) value);
619 case FieldType.Fixed32:
620 return ComputeFixed32SizeNoTag((uint) value);
621 case FieldType.Bool:
622 return ComputeBoolSizeNoTag((bool) value);
623 case FieldType.String:
624 return ComputeStringSizeNoTag((string) value);
625 case FieldType.Group:
626 return ComputeGroupSizeNoTag((IMessageLite) value);
627 case FieldType.Message:
628 return ComputeMessageSizeNoTag((IMessageLite) value);
629 case FieldType.Bytes:
630 return ComputeBytesSizeNoTag((ByteString) value);
631 case FieldType.UInt32:
632 return ComputeUInt32SizeNoTag((uint) value);
633 case FieldType.SFixed32:
634 return ComputeSFixed32SizeNoTag((int) value);
635 case FieldType.SFixed64:
636 return ComputeSFixed64SizeNoTag((long) value);
637 case FieldType.SInt32:
638 return ComputeSInt32SizeNoTag((int) value);
639 case FieldType.SInt64:
640 return ComputeSInt64SizeNoTag((long) value);
641 case FieldType.Enum:
csharptest74c5e0c2011-07-14 13:06:22 -0500642 if (value is Enum)
643 {
644 return ComputeEnumSizeNoTag(((IConvertible) value).ToInt32(CultureInfo.InvariantCulture));
645 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500646 else
csharptest74c5e0c2011-07-14 13:06:22 -0500647 {
csharptestcc8d2aa2011-06-03 12:15:42 -0500648 return ComputeEnumSizeNoTag(((IEnumLite) value).Number);
csharptest74c5e0c2011-07-14 13:06:22 -0500649 }
csharptestcc8d2aa2011-06-03 12:15:42 -0500650 default:
651 throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
652 }
653 }
654
655 /// <summary>
656 /// Compute the number of bytes that would be needed to encode a tag.
657 /// </summary>
658 public static int ComputeTagSize(int fieldNumber)
659 {
660 return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0));
661 }
662 }
663}