1// Protocol Buffers - Google's data interchange format
2// Copyright 2013 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31package com.google.protobuf.nano;
32
33import java.io.IOException;
34import java.io.UnsupportedEncodingException;
35
36/**
37 * Encodes and writes protocol message fields.
38 *
39 * <p>This class contains two kinds of methods:  methods that write specific
40 * protocol message constructs and field types (e.g. {@link #writeTag} and
41 * {@link #writeInt32}) and methods that write low-level values (e.g.
42 * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
43 * writing encoded protocol messages, you should use the former methods, but if
44 * you are writing some other format of your own design, use the latter.
45 *
46 * <p>This class is totally unsynchronized.
47 *
48 * @author kneton@google.com Kenton Varda
49 */
50public final class CodedOutputByteBufferNano {
51  private final byte[] buffer;
52  private final int limit;
53  private int position;
54
55  private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
56                            final int length) {
57    this.buffer = buffer;
58    position = offset;
59    limit = offset + length;
60  }
61
62  /**
63   * Create a new {@code CodedOutputStream} that writes directly to the given
64   * byte array.  If more bytes are written than fit in the array,
65   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
66   * array is faster than writing to an {@code OutputStream}.
67   */
68  public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) {
69    return newInstance(flatArray, 0, flatArray.length);
70  }
71
72  /**
73   * Create a new {@code CodedOutputStream} that writes directly to the given
74   * byte array slice.  If more bytes are written than fit in the slice,
75   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
76   * array is faster than writing to an {@code OutputStream}.
77   */
78  public static CodedOutputByteBufferNano newInstance(final byte[] flatArray,
79                                              final int offset,
80                                              final int length) {
81    return new CodedOutputByteBufferNano(flatArray, offset, length);
82  }
83
84  // -----------------------------------------------------------------
85
86  /** Write a {@code double} field, including tag, to the stream. */
87  public void writeDouble(final int fieldNumber, final double value)
88                          throws IOException {
89    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
90    writeDoubleNoTag(value);
91  }
92
93  /** Write a {@code float} field, including tag, to the stream. */
94  public void writeFloat(final int fieldNumber, final float value)
95                         throws IOException {
96    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
97    writeFloatNoTag(value);
98  }
99
100  /** Write a {@code uint64} field, including tag, to the stream. */
101  public void writeUInt64(final int fieldNumber, final long value)
102                          throws IOException {
103    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
104    writeUInt64NoTag(value);
105  }
106
107  /** Write an {@code int64} field, including tag, to the stream. */
108  public void writeInt64(final int fieldNumber, final long value)
109                         throws IOException {
110    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
111    writeInt64NoTag(value);
112  }
113
114  /** Write an {@code int32} field, including tag, to the stream. */
115  public void writeInt32(final int fieldNumber, final int value)
116                         throws IOException {
117    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
118    writeInt32NoTag(value);
119  }
120
121  /** Write a {@code fixed64} field, including tag, to the stream. */
122  public void writeFixed64(final int fieldNumber, final long value)
123                           throws IOException {
124    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
125    writeFixed64NoTag(value);
126  }
127
128  /** Write a {@code fixed32} field, including tag, to the stream. */
129  public void writeFixed32(final int fieldNumber, final int value)
130                           throws IOException {
131    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
132    writeFixed32NoTag(value);
133  }
134
135  /** Write a {@code bool} field, including tag, to the stream. */
136  public void writeBool(final int fieldNumber, final boolean value)
137                        throws IOException {
138    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
139    writeBoolNoTag(value);
140  }
141
142  /** Write a {@code string} field, including tag, to the stream. */
143  public void writeString(final int fieldNumber, final String value)
144                          throws IOException {
145    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
146    writeStringNoTag(value);
147  }
148
149  /** Write a {@code group} field, including tag, to the stream. */
150  public void writeGroup(final int fieldNumber, final MessageNano value)
151                         throws IOException {
152    writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP);
153    writeGroupNoTag(value);
154    writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
155  }
156
157  /** Write an embedded message field, including tag, to the stream. */
158  public void writeMessage(final int fieldNumber, final MessageNano value)
159                           throws IOException {
160    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
161    writeMessageNoTag(value);
162  }
163
164  /** Write a {@code bytes} field, including tag, to the stream. */
165  public void writeBytes(final int fieldNumber, final byte[] value)
166                         throws IOException {
167    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
168    writeBytesNoTag(value);
169  }
170
171  /** Write a {@code byte} field, including tag, to the stream. */
172  public void writeByteArray(final int fieldNumber, final byte[] value)
173                         throws IOException {
174    writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
175    writeByteArrayNoTag(value);
176  }
177
178
179  /** Write a {@code uint32} field, including tag, to the stream. */
180  public void writeUInt32(final int fieldNumber, final int value)
181                          throws IOException {
182    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
183    writeUInt32NoTag(value);
184  }
185
186  /**
187   * Write an enum field, including tag, to the stream.  Caller is responsible
188   * for converting the enum value to its numeric value.
189   */
190  public void writeEnum(final int fieldNumber, final int value)
191                        throws IOException {
192    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
193    writeEnumNoTag(value);
194  }
195
196  /** Write an {@code sfixed32} field, including tag, to the stream. */
197  public void writeSFixed32(final int fieldNumber, final int value)
198                            throws IOException {
199    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
200    writeSFixed32NoTag(value);
201  }
202
203  /** Write an {@code sfixed64} field, including tag, to the stream. */
204  public void writeSFixed64(final int fieldNumber, final long value)
205                            throws IOException {
206    writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
207    writeSFixed64NoTag(value);
208  }
209
210  /** Write an {@code sint32} field, including tag, to the stream. */
211  public void writeSInt32(final int fieldNumber, final int value)
212                          throws IOException {
213    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
214    writeSInt32NoTag(value);
215  }
216
217  /** Write an {@code sint64} field, including tag, to the stream. */
218  public void writeSInt64(final int fieldNumber, final long value)
219                          throws IOException {
220    writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
221    writeSInt64NoTag(value);
222  }
223
224  /**
225   * Write a MessageSet extension field to the stream.  For historical reasons,
226   * the wire format differs from normal fields.
227   */
228//  public void writeMessageSetExtension(final int fieldNumber,
229//                                       final MessageMicro value)
230//                                       throws IOException {
231//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
232//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
233//    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
234//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
235//  }
236
237  /**
238   * Write an unparsed MessageSet extension field to the stream.  For
239   * historical reasons, the wire format differs from normal fields.
240   */
241//  public void writeRawMessageSetExtension(final int fieldNumber,
242//                                          final ByteStringMicro value)
243//                                          throws IOException {
244//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
245//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
246//    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
247//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
248//  }
249
250  // -----------------------------------------------------------------
251
252  /** Write a {@code double} field to the stream. */
253  public void writeDoubleNoTag(final double value) throws IOException {
254    writeRawLittleEndian64(Double.doubleToLongBits(value));
255  }
256
257  /** Write a {@code float} field to the stream. */
258  public void writeFloatNoTag(final float value) throws IOException {
259    writeRawLittleEndian32(Float.floatToIntBits(value));
260  }
261
262  /** Write a {@code uint64} field to the stream. */
263  public void writeUInt64NoTag(final long value) throws IOException {
264    writeRawVarint64(value);
265  }
266
267  /** Write an {@code int64} field to the stream. */
268  public void writeInt64NoTag(final long value) throws IOException {
269    writeRawVarint64(value);
270  }
271
272  /** Write an {@code int32} field to the stream. */
273  public void writeInt32NoTag(final int value) throws IOException {
274    if (value >= 0) {
275      writeRawVarint32(value);
276    } else {
277      // Must sign-extend.
278      writeRawVarint64(value);
279    }
280  }
281
282  /** Write a {@code fixed64} field to the stream. */
283  public void writeFixed64NoTag(final long value) throws IOException {
284    writeRawLittleEndian64(value);
285  }
286
287  /** Write a {@code fixed32} field to the stream. */
288  public void writeFixed32NoTag(final int value) throws IOException {
289    writeRawLittleEndian32(value);
290  }
291
292  /** Write a {@code bool} field to the stream. */
293  public void writeBoolNoTag(final boolean value) throws IOException {
294    writeRawByte(value ? 1 : 0);
295  }
296
297  /** Write a {@code string} field to the stream. */
298  public void writeStringNoTag(final String value) throws IOException {
299    // Unfortunately there does not appear to be any way to tell Java to encode
300    // UTF-8 directly into our buffer, so we have to let it create its own byte
301    // array and then copy.
302    final byte[] bytes = value.getBytes("UTF-8");
303    writeRawVarint32(bytes.length);
304    writeRawBytes(bytes);
305  }
306
307  /** Write a {@code group} field to the stream. */
308  public void writeGroupNoTag(final MessageNano value) throws IOException {
309    value.writeTo(this);
310  }
311
312  /** Write an embedded message field to the stream. */
313  public void writeMessageNoTag(final MessageNano value) throws IOException {
314    writeRawVarint32(value.getCachedSize());
315    value.writeTo(this);
316  }
317
318  /** Write a {@code bytes} field to the stream. */
319  public void writeBytesNoTag(final byte[] value) throws IOException {
320    writeRawVarint32(value.length);
321    writeRawBytes(value);
322  }
323
324  /** Write a {@code byte[]} field to the stream. */
325  public void writeByteArrayNoTag(final byte [] value) throws IOException {
326    writeRawVarint32(value.length);
327    writeRawBytes(value);
328  }
329
330  /** Write a {@code uint32} field to the stream. */
331  public void writeUInt32NoTag(final int value) throws IOException {
332    writeRawVarint32(value);
333  }
334
335  /**
336   * Write an enum field to the stream.  Caller is responsible
337   * for converting the enum value to its numeric value.
338   */
339  public void writeEnumNoTag(final int value) throws IOException {
340    writeRawVarint32(value);
341  }
342
343  /** Write an {@code sfixed32} field to the stream. */
344  public void writeSFixed32NoTag(final int value) throws IOException {
345    writeRawLittleEndian32(value);
346  }
347
348  /** Write an {@code sfixed64} field to the stream. */
349  public void writeSFixed64NoTag(final long value) throws IOException {
350    writeRawLittleEndian64(value);
351  }
352
353  /** Write an {@code sint32} field to the stream. */
354  public void writeSInt32NoTag(final int value) throws IOException {
355    writeRawVarint32(encodeZigZag32(value));
356  }
357
358  /** Write an {@code sint64} field to the stream. */
359  public void writeSInt64NoTag(final long value) throws IOException {
360    writeRawVarint64(encodeZigZag64(value));
361  }
362
363  // =================================================================
364
365  /**
366   * Compute the number of bytes that would be needed to encode a
367   * {@code double} field, including tag.
368   */
369  public static int computeDoubleSize(final int fieldNumber,
370                                      final double value) {
371    return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
372  }
373
374  /**
375   * Compute the number of bytes that would be needed to encode a
376   * {@code float} field, including tag.
377   */
378  public static int computeFloatSize(final int fieldNumber, final float value) {
379    return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
380  }
381
382  /**
383   * Compute the number of bytes that would be needed to encode a
384   * {@code uint64} field, including tag.
385   */
386  public static int computeUInt64Size(final int fieldNumber, final long value) {
387    return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
388  }
389
390  /**
391   * Compute the number of bytes that would be needed to encode an
392   * {@code int64} field, including tag.
393   */
394  public static int computeInt64Size(final int fieldNumber, final long value) {
395    return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
396  }
397
398  /**
399   * Compute the number of bytes that would be needed to encode an
400   * {@code int32} field, including tag.
401   */
402  public static int computeInt32Size(final int fieldNumber, final int value) {
403    return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
404  }
405
406  /**
407   * Compute the number of bytes that would be needed to encode a
408   * {@code fixed64} field, including tag.
409   */
410  public static int computeFixed64Size(final int fieldNumber,
411                                       final long value) {
412    return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
413  }
414
415  /**
416   * Compute the number of bytes that would be needed to encode a
417   * {@code fixed32} field, including tag.
418   */
419  public static int computeFixed32Size(final int fieldNumber,
420                                       final int value) {
421    return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
422  }
423
424  /**
425   * Compute the number of bytes that would be needed to encode a
426   * {@code bool} field, including tag.
427   */
428  public static int computeBoolSize(final int fieldNumber,
429                                    final boolean value) {
430    return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
431  }
432
433  /**
434   * Compute the number of bytes that would be needed to encode a
435   * {@code string} field, including tag.
436   */
437  public static int computeStringSize(final int fieldNumber,
438                                      final String value) {
439    return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
440  }
441
442  /**
443   * Compute the number of bytes that would be needed to encode a
444   * {@code group} field, including tag.
445   */
446  public static int computeGroupSize(final int fieldNumber,
447                                     final MessageNano value) {
448    return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
449  }
450
451  /**
452   * Compute the number of bytes that would be needed to encode an
453   * embedded message field, including tag.
454   */
455  public static int computeMessageSize(final int fieldNumber,
456                                       final MessageNano value) {
457    return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
458  }
459
460  /**
461   * Compute the number of bytes that would be needed to encode a
462   * {@code bytes} field, including tag.
463   */
464  public static int computeBytesSize(final int fieldNumber,
465                                     final byte[] value) {
466    return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
467  }
468
469  /**
470   * Compute the number of bytes that would be needed to encode a
471   * {@code byte[]} field, including tag.
472   */
473  public static int computeByteArraySize(final int fieldNumber,
474                                     final byte[] value) {
475    return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
476  }
477
478  /**
479   * Compute the number of bytes that would be needed to encode a
480   * {@code uint32} field, including tag.
481   */
482  public static int computeUInt32Size(final int fieldNumber, final int value) {
483    return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
484  }
485
486  /**
487   * Compute the number of bytes that would be needed to encode an
488   * enum field, including tag.  Caller is responsible for converting the
489   * enum value to its numeric value.
490   */
491  public static int computeEnumSize(final int fieldNumber, final int value) {
492    return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
493  }
494
495  /**
496   * Compute the number of bytes that would be needed to encode an
497   * {@code sfixed32} field, including tag.
498   */
499  public static int computeSFixed32Size(final int fieldNumber,
500                                        final int value) {
501    return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
502  }
503
504  /**
505   * Compute the number of bytes that would be needed to encode an
506   * {@code sfixed64} field, including tag.
507   */
508  public static int computeSFixed64Size(final int fieldNumber,
509                                        final long value) {
510    return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
511  }
512
513  /**
514   * Compute the number of bytes that would be needed to encode an
515   * {@code sint32} field, including tag.
516   */
517  public static int computeSInt32Size(final int fieldNumber, final int value) {
518    return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
519  }
520
521  /**
522   * Compute the number of bytes that would be needed to encode an
523   * {@code sint64} field, including tag.
524   */
525  public static int computeSInt64Size(final int fieldNumber, final long value) {
526    return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
527  }
528
529  /**
530   * Compute the number of bytes that would be needed to encode a
531   * MessageSet extension to the stream.  For historical reasons,
532   * the wire format differs from normal fields.
533   */
534//  public static int computeMessageSetExtensionSize(
535//      final int fieldNumber, final MessageMicro value) {
536//    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
537//           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
538//           computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
539//  }
540
541  /**
542   * Compute the number of bytes that would be needed to encode an
543   * unparsed MessageSet extension field to the stream.  For
544   * historical reasons, the wire format differs from normal fields.
545   */
546//  public static int computeRawMessageSetExtensionSize(
547//      final int fieldNumber, final ByteStringMicro value) {
548//    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
549//           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
550//           computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
551//  }
552
553  // -----------------------------------------------------------------
554
555  /**
556   * Compute the number of bytes that would be needed to encode a
557   * {@code double} field, including tag.
558   */
559  public static int computeDoubleSizeNoTag(final double value) {
560    return LITTLE_ENDIAN_64_SIZE;
561  }
562
563  /**
564   * Compute the number of bytes that would be needed to encode a
565   * {@code float} field, including tag.
566   */
567  public static int computeFloatSizeNoTag(final float value) {
568    return LITTLE_ENDIAN_32_SIZE;
569  }
570
571  /**
572   * Compute the number of bytes that would be needed to encode a
573   * {@code uint64} field, including tag.
574   */
575  public static int computeUInt64SizeNoTag(final long value) {
576    return computeRawVarint64Size(value);
577  }
578
579  /**
580   * Compute the number of bytes that would be needed to encode an
581   * {@code int64} field, including tag.
582   */
583  public static int computeInt64SizeNoTag(final long value) {
584    return computeRawVarint64Size(value);
585  }
586
587  /**
588   * Compute the number of bytes that would be needed to encode an
589   * {@code int32} field, including tag.
590   */
591  public static int computeInt32SizeNoTag(final int value) {
592    if (value >= 0) {
593      return computeRawVarint32Size(value);
594    } else {
595      // Must sign-extend.
596      return 10;
597    }
598  }
599
600  /**
601   * Compute the number of bytes that would be needed to encode a
602   * {@code fixed64} field.
603   */
604  public static int computeFixed64SizeNoTag(final long value) {
605    return LITTLE_ENDIAN_64_SIZE;
606  }
607
608  /**
609   * Compute the number of bytes that would be needed to encode a
610   * {@code fixed32} field.
611   */
612  public static int computeFixed32SizeNoTag(final int value) {
613    return LITTLE_ENDIAN_32_SIZE;
614  }
615
616  /**
617   * Compute the number of bytes that would be needed to encode a
618   * {@code bool} field.
619   */
620  public static int computeBoolSizeNoTag(final boolean value) {
621    return 1;
622  }
623
624  /**
625   * Compute the number of bytes that would be needed to encode a
626   * {@code string} field.
627   */
628  public static int computeStringSizeNoTag(final String value) {
629    try {
630      final byte[] bytes = value.getBytes("UTF-8");
631      return computeRawVarint32Size(bytes.length) +
632             bytes.length;
633    } catch (UnsupportedEncodingException e) {
634      throw new RuntimeException("UTF-8 not supported.");
635    }
636  }
637
638  /**
639   * Compute the number of bytes that would be needed to encode a
640   * {@code group} field.
641   */
642  public static int computeGroupSizeNoTag(final MessageNano value) {
643    return value.getSerializedSize();
644  }
645
646  /**
647   * Compute the number of bytes that would be needed to encode an embedded
648   * message field.
649   */
650  public static int computeMessageSizeNoTag(final MessageNano value) {
651    final int size = value.getSerializedSize();
652    return computeRawVarint32Size(size) + size;
653  }
654
655  /**
656   * Compute the number of bytes that would be needed to encode a
657   * {@code bytes} field.
658   */
659  public static int computeBytesSizeNoTag(final byte[] value) {
660    return computeRawVarint32Size(value.length) + value.length;
661  }
662
663  /**
664   * Compute the number of bytes that would be needed to encode a
665   * {@code byte[]} field.
666   */
667  public static int computeByteArraySizeNoTag(final byte[] value) {
668    return computeRawVarint32Size(value.length) + value.length;
669  }
670
671  /**
672   * Compute the number of bytes that would be needed to encode a
673   * {@code uint32} field.
674   */
675  public static int computeUInt32SizeNoTag(final int value) {
676    return computeRawVarint32Size(value);
677  }
678
679  /**
680   * Compute the number of bytes that would be needed to encode an enum field.
681   * Caller is responsible for converting the enum value to its numeric value.
682   */
683  public static int computeEnumSizeNoTag(final int value) {
684    return computeRawVarint32Size(value);
685  }
686
687  /**
688   * Compute the number of bytes that would be needed to encode an
689   * {@code sfixed32} field.
690   */
691  public static int computeSFixed32SizeNoTag(final int value) {
692    return LITTLE_ENDIAN_32_SIZE;
693  }
694
695  /**
696   * Compute the number of bytes that would be needed to encode an
697   * {@code sfixed64} field.
698   */
699  public static int computeSFixed64SizeNoTag(final long value) {
700    return LITTLE_ENDIAN_64_SIZE;
701  }
702
703  /**
704   * Compute the number of bytes that would be needed to encode an
705   * {@code sint32} field.
706   */
707  public static int computeSInt32SizeNoTag(final int value) {
708    return computeRawVarint32Size(encodeZigZag32(value));
709  }
710
711  /**
712   * Compute the number of bytes that would be needed to encode an
713   * {@code sint64} field.
714   */
715  public static int computeSInt64SizeNoTag(final long value) {
716    return computeRawVarint64Size(encodeZigZag64(value));
717  }
718
719  // =================================================================
720
721  /**
722   * If writing to a flat array, return the space left in the array.
723   * Otherwise, throws {@code UnsupportedOperationException}.
724   */
725  public int spaceLeft() {
726    return limit - position;
727  }
728
729  /**
730   * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
731   * a byte array that is exactly big enough to hold a message, then write to
732   * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
733   * after writing verifies that the message was actually as big as expected,
734   * which can help catch bugs.
735   */
736  public void checkNoSpaceLeft() {
737    if (spaceLeft() != 0) {
738      throw new IllegalStateException(
739        "Did not write as much data as expected.");
740    }
741  }
742
743  /**
744   * If you create a CodedOutputStream around a simple flat array, you must
745   * not attempt to write more bytes than the array has space.  Otherwise,
746   * this exception will be thrown.
747   */
748  public static class OutOfSpaceException extends IOException {
749    private static final long serialVersionUID = -6947486886997889499L;
750
751    OutOfSpaceException(int position, int limit) {
752      super("CodedOutputStream was writing to a flat byte array and ran " +
753            "out of space (pos " + position + " limit " + limit + ").");
754    }
755  }
756
757  /** Write a single byte. */
758  public void writeRawByte(final byte value) throws IOException {
759    if (position == limit) {
760      // We're writing to a single buffer.
761      throw new OutOfSpaceException(position, limit);
762    }
763
764    buffer[position++] = value;
765  }
766
767  /** Write a single byte, represented by an integer value. */
768  public void writeRawByte(final int value) throws IOException {
769    writeRawByte((byte) value);
770  }
771
772  /** Write an array of bytes. */
773  public void writeRawBytes(final byte[] value) throws IOException {
774    writeRawBytes(value, 0, value.length);
775  }
776
777  /** Write part of an array of bytes. */
778  public void writeRawBytes(final byte[] value, int offset, int length)
779                            throws IOException {
780    if (limit - position >= length) {
781      // We have room in the current buffer.
782      System.arraycopy(value, offset, buffer, position, length);
783      position += length;
784    } else {
785      // We're writing to a single buffer.
786      throw new OutOfSpaceException(position, limit);
787    }
788  }
789
790  /** Encode and write a tag. */
791  public void writeTag(final int fieldNumber, final int wireType)
792                       throws IOException {
793    writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
794  }
795
796  /** Compute the number of bytes that would be needed to encode a tag. */
797  public static int computeTagSize(final int fieldNumber) {
798    return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
799  }
800
801  /**
802   * Encode and write a varint.  {@code value} is treated as
803   * unsigned, so it won't be sign-extended if negative.
804   */
805  public void writeRawVarint32(int value) throws IOException {
806    while (true) {
807      if ((value & ~0x7F) == 0) {
808        writeRawByte(value);
809        return;
810      } else {
811        writeRawByte((value & 0x7F) | 0x80);
812        value >>>= 7;
813      }
814    }
815  }
816
817  /**
818   * Compute the number of bytes that would be needed to encode a varint.
819   * {@code value} is treated as unsigned, so it won't be sign-extended if
820   * negative.
821   */
822  public static int computeRawVarint32Size(final int value) {
823    if ((value & (0xffffffff <<  7)) == 0) return 1;
824    if ((value & (0xffffffff << 14)) == 0) return 2;
825    if ((value & (0xffffffff << 21)) == 0) return 3;
826    if ((value & (0xffffffff << 28)) == 0) return 4;
827    return 5;
828  }
829
830  /** Encode and write a varint. */
831  public void writeRawVarint64(long value) throws IOException {
832    while (true) {
833      if ((value & ~0x7FL) == 0) {
834        writeRawByte((int)value);
835        return;
836      } else {
837        writeRawByte(((int)value & 0x7F) | 0x80);
838        value >>>= 7;
839      }
840    }
841  }
842
843  /** Compute the number of bytes that would be needed to encode a varint. */
844  public static int computeRawVarint64Size(final long value) {
845    if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
846    if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
847    if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
848    if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
849    if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
850    if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
851    if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
852    if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
853    if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
854    return 10;
855  }
856
857  /** Write a little-endian 32-bit integer. */
858  public void writeRawLittleEndian32(final int value) throws IOException {
859    writeRawByte((value      ) & 0xFF);
860    writeRawByte((value >>  8) & 0xFF);
861    writeRawByte((value >> 16) & 0xFF);
862    writeRawByte((value >> 24) & 0xFF);
863  }
864
865  public static final int LITTLE_ENDIAN_32_SIZE = 4;
866
867  /** Write a little-endian 64-bit integer. */
868  public void writeRawLittleEndian64(final long value) throws IOException {
869    writeRawByte((int)(value      ) & 0xFF);
870    writeRawByte((int)(value >>  8) & 0xFF);
871    writeRawByte((int)(value >> 16) & 0xFF);
872    writeRawByte((int)(value >> 24) & 0xFF);
873    writeRawByte((int)(value >> 32) & 0xFF);
874    writeRawByte((int)(value >> 40) & 0xFF);
875    writeRawByte((int)(value >> 48) & 0xFF);
876    writeRawByte((int)(value >> 56) & 0xFF);
877  }
878
879  public static final int LITTLE_ENDIAN_64_SIZE = 8;
880
881  /**
882   * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
883   * into values that can be efficiently encoded with varint.  (Otherwise,
884   * negative values must be sign-extended to 64 bits to be varint encoded,
885   * thus always taking 10 bytes on the wire.)
886   *
887   * @param n A signed 32-bit integer.
888   * @return An unsigned 32-bit integer, stored in a signed int because
889   *         Java has no explicit unsigned support.
890   */
891  public static int encodeZigZag32(final int n) {
892    // Note:  the right-shift must be arithmetic
893    return (n << 1) ^ (n >> 31);
894  }
895
896  /**
897   * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
898   * into values that can be efficiently encoded with varint.  (Otherwise,
899   * negative values must be sign-extended to 64 bits to be varint encoded,
900   * thus always taking 10 bytes on the wire.)
901   *
902   * @param n A signed 64-bit integer.
903   * @return An unsigned 64-bit integer, stored in a signed int because
904   *         Java has no explicit unsigned support.
905   */
906  public static long encodeZigZag64(final long n) {
907    // Note:  the right-shift must be arithmetic
908    return (n << 1) ^ (n >> 63);
909  }
910}
911