• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 package com.google.protobuf.nano;
32 
33 import java.io.IOException;
34 import 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  */
50 public final class CodedOutputByteBufferNano {
51   private final byte[] buffer;
52   private final int limit;
53   private int position;
54 
CodedOutputByteBufferNano(final byte[] buffer, final int offset, final int length)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    */
newInstance(final byte[] flatArray)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    */
newInstance(final byte[] flatArray, final int offset, final int length)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. */
writeDouble(final int fieldNumber, final double value)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. */
writeFloat(final int fieldNumber, final float value)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. */
writeUInt64(final int fieldNumber, final long value)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. */
writeInt64(final int fieldNumber, final long value)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. */
writeInt32(final int fieldNumber, final int value)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. */
writeFixed64(final int fieldNumber, final long value)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. */
writeFixed32(final int fieldNumber, final int value)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. */
writeBool(final int fieldNumber, final boolean value)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. */
writeString(final int fieldNumber, final String value)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. */
writeGroup(final int fieldNumber, final MessageNano value)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. */
writeMessage(final int fieldNumber, final MessageNano value)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. */
writeBytes(final int fieldNumber, final byte[] value)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 uint32} field, including tag, to the stream. */
writeUInt32(final int fieldNumber, final int value)172   public void writeUInt32(final int fieldNumber, final int value)
173                           throws IOException {
174     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
175     writeUInt32NoTag(value);
176   }
177 
178   /**
179    * Write an enum field, including tag, to the stream.  Caller is responsible
180    * for converting the enum value to its numeric value.
181    */
writeEnum(final int fieldNumber, final int value)182   public void writeEnum(final int fieldNumber, final int value)
183                         throws IOException {
184     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
185     writeEnumNoTag(value);
186   }
187 
188   /** Write an {@code sfixed32} field, including tag, to the stream. */
writeSFixed32(final int fieldNumber, final int value)189   public void writeSFixed32(final int fieldNumber, final int value)
190                             throws IOException {
191     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
192     writeSFixed32NoTag(value);
193   }
194 
195   /** Write an {@code sfixed64} field, including tag, to the stream. */
writeSFixed64(final int fieldNumber, final long value)196   public void writeSFixed64(final int fieldNumber, final long value)
197                             throws IOException {
198     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
199     writeSFixed64NoTag(value);
200   }
201 
202   /** Write an {@code sint32} field, including tag, to the stream. */
writeSInt32(final int fieldNumber, final int value)203   public void writeSInt32(final int fieldNumber, final int value)
204                           throws IOException {
205     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
206     writeSInt32NoTag(value);
207   }
208 
209   /** Write an {@code sint64} field, including tag, to the stream. */
writeSInt64(final int fieldNumber, final long value)210   public void writeSInt64(final int fieldNumber, final long value)
211                           throws IOException {
212     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
213     writeSInt64NoTag(value);
214   }
215 
216   /**
217    * Write a MessageSet extension field to the stream.  For historical reasons,
218    * the wire format differs from normal fields.
219    */
220 //  public void writeMessageSetExtension(final int fieldNumber,
221 //                                       final MessageMicro value)
222 //                                       throws IOException {
223 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
224 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
225 //    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
226 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
227 //  }
228 
229   /**
230    * Write an unparsed MessageSet extension field to the stream.  For
231    * historical reasons, the wire format differs from normal fields.
232    */
233 //  public void writeRawMessageSetExtension(final int fieldNumber,
234 //                                          final ByteStringMicro value)
235 //                                          throws IOException {
236 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
237 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
238 //    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
239 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
240 //  }
241 
242   // -----------------------------------------------------------------
243 
244   /** Write a {@code double} field to the stream. */
writeDoubleNoTag(final double value)245   public void writeDoubleNoTag(final double value) throws IOException {
246     writeRawLittleEndian64(Double.doubleToLongBits(value));
247   }
248 
249   /** Write a {@code float} field to the stream. */
writeFloatNoTag(final float value)250   public void writeFloatNoTag(final float value) throws IOException {
251     writeRawLittleEndian32(Float.floatToIntBits(value));
252   }
253 
254   /** Write a {@code uint64} field to the stream. */
writeUInt64NoTag(final long value)255   public void writeUInt64NoTag(final long value) throws IOException {
256     writeRawVarint64(value);
257   }
258 
259   /** Write an {@code int64} field to the stream. */
writeInt64NoTag(final long value)260   public void writeInt64NoTag(final long value) throws IOException {
261     writeRawVarint64(value);
262   }
263 
264   /** Write an {@code int32} field to the stream. */
writeInt32NoTag(final int value)265   public void writeInt32NoTag(final int value) throws IOException {
266     if (value >= 0) {
267       writeRawVarint32(value);
268     } else {
269       // Must sign-extend.
270       writeRawVarint64(value);
271     }
272   }
273 
274   /** Write a {@code fixed64} field to the stream. */
writeFixed64NoTag(final long value)275   public void writeFixed64NoTag(final long value) throws IOException {
276     writeRawLittleEndian64(value);
277   }
278 
279   /** Write a {@code fixed32} field to the stream. */
writeFixed32NoTag(final int value)280   public void writeFixed32NoTag(final int value) throws IOException {
281     writeRawLittleEndian32(value);
282   }
283 
284   /** Write a {@code bool} field to the stream. */
writeBoolNoTag(final boolean value)285   public void writeBoolNoTag(final boolean value) throws IOException {
286     writeRawByte(value ? 1 : 0);
287   }
288 
289   /** Write a {@code string} field to the stream. */
writeStringNoTag(final String value)290   public void writeStringNoTag(final String value) throws IOException {
291     // Unfortunately there does not appear to be any way to tell Java to encode
292     // UTF-8 directly into our buffer, so we have to let it create its own byte
293     // array and then copy.
294     final byte[] bytes = value.getBytes("UTF-8");
295     writeRawVarint32(bytes.length);
296     writeRawBytes(bytes);
297   }
298 
299   /** Write a {@code group} field to the stream. */
writeGroupNoTag(final MessageNano value)300   public void writeGroupNoTag(final MessageNano value) throws IOException {
301     value.writeTo(this);
302   }
303 
304   /** Write an embedded message field to the stream. */
writeMessageNoTag(final MessageNano value)305   public void writeMessageNoTag(final MessageNano value) throws IOException {
306     writeRawVarint32(value.getCachedSize());
307     value.writeTo(this);
308   }
309 
310   /** Write a {@code bytes} field to the stream. */
writeBytesNoTag(final byte[] value)311   public void writeBytesNoTag(final byte[] value) throws IOException {
312     writeRawVarint32(value.length);
313     writeRawBytes(value);
314   }
315 
316   /** Write a {@code uint32} field to the stream. */
writeUInt32NoTag(final int value)317   public void writeUInt32NoTag(final int value) throws IOException {
318     writeRawVarint32(value);
319   }
320 
321   /**
322    * Write an enum field to the stream.  Caller is responsible
323    * for converting the enum value to its numeric value.
324    */
writeEnumNoTag(final int value)325   public void writeEnumNoTag(final int value) throws IOException {
326     writeRawVarint32(value);
327   }
328 
329   /** Write an {@code sfixed32} field to the stream. */
writeSFixed32NoTag(final int value)330   public void writeSFixed32NoTag(final int value) throws IOException {
331     writeRawLittleEndian32(value);
332   }
333 
334   /** Write an {@code sfixed64} field to the stream. */
writeSFixed64NoTag(final long value)335   public void writeSFixed64NoTag(final long value) throws IOException {
336     writeRawLittleEndian64(value);
337   }
338 
339   /** Write an {@code sint32} field to the stream. */
writeSInt32NoTag(final int value)340   public void writeSInt32NoTag(final int value) throws IOException {
341     writeRawVarint32(encodeZigZag32(value));
342   }
343 
344   /** Write an {@code sint64} field to the stream. */
writeSInt64NoTag(final long value)345   public void writeSInt64NoTag(final long value) throws IOException {
346     writeRawVarint64(encodeZigZag64(value));
347   }
348 
349   // =================================================================
350 
351   /**
352    * Compute the number of bytes that would be needed to encode a
353    * {@code double} field, including tag.
354    */
computeDoubleSize(final int fieldNumber, final double value)355   public static int computeDoubleSize(final int fieldNumber,
356                                       final double value) {
357     return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
358   }
359 
360   /**
361    * Compute the number of bytes that would be needed to encode a
362    * {@code float} field, including tag.
363    */
computeFloatSize(final int fieldNumber, final float value)364   public static int computeFloatSize(final int fieldNumber, final float value) {
365     return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
366   }
367 
368   /**
369    * Compute the number of bytes that would be needed to encode a
370    * {@code uint64} field, including tag.
371    */
computeUInt64Size(final int fieldNumber, final long value)372   public static int computeUInt64Size(final int fieldNumber, final long value) {
373     return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
374   }
375 
376   /**
377    * Compute the number of bytes that would be needed to encode an
378    * {@code int64} field, including tag.
379    */
computeInt64Size(final int fieldNumber, final long value)380   public static int computeInt64Size(final int fieldNumber, final long value) {
381     return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
382   }
383 
384   /**
385    * Compute the number of bytes that would be needed to encode an
386    * {@code int32} field, including tag.
387    */
computeInt32Size(final int fieldNumber, final int value)388   public static int computeInt32Size(final int fieldNumber, final int value) {
389     return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
390   }
391 
392   /**
393    * Compute the number of bytes that would be needed to encode a
394    * {@code fixed64} field, including tag.
395    */
computeFixed64Size(final int fieldNumber, final long value)396   public static int computeFixed64Size(final int fieldNumber,
397                                        final long value) {
398     return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
399   }
400 
401   /**
402    * Compute the number of bytes that would be needed to encode a
403    * {@code fixed32} field, including tag.
404    */
computeFixed32Size(final int fieldNumber, final int value)405   public static int computeFixed32Size(final int fieldNumber,
406                                        final int value) {
407     return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
408   }
409 
410   /**
411    * Compute the number of bytes that would be needed to encode a
412    * {@code bool} field, including tag.
413    */
computeBoolSize(final int fieldNumber, final boolean value)414   public static int computeBoolSize(final int fieldNumber,
415                                     final boolean value) {
416     return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
417   }
418 
419   /**
420    * Compute the number of bytes that would be needed to encode a
421    * {@code string} field, including tag.
422    */
computeStringSize(final int fieldNumber, final String value)423   public static int computeStringSize(final int fieldNumber,
424                                       final String value) {
425     return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
426   }
427 
428   /**
429    * Compute the number of bytes that would be needed to encode a
430    * {@code group} field, including tag.
431    */
computeGroupSize(final int fieldNumber, final MessageNano value)432   public static int computeGroupSize(final int fieldNumber,
433                                      final MessageNano value) {
434     return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
435   }
436 
437   /**
438    * Compute the number of bytes that would be needed to encode an
439    * embedded message field, including tag.
440    */
computeMessageSize(final int fieldNumber, final MessageNano value)441   public static int computeMessageSize(final int fieldNumber,
442                                        final MessageNano value) {
443     return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
444   }
445 
446   /**
447    * Compute the number of bytes that would be needed to encode a
448    * {@code bytes} field, including tag.
449    */
computeBytesSize(final int fieldNumber, final byte[] value)450   public static int computeBytesSize(final int fieldNumber,
451                                      final byte[] value) {
452     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
453   }
454 
455   /**
456    * Compute the number of bytes that would be needed to encode a
457    * {@code uint32} field, including tag.
458    */
computeUInt32Size(final int fieldNumber, final int value)459   public static int computeUInt32Size(final int fieldNumber, final int value) {
460     return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
461   }
462 
463   /**
464    * Compute the number of bytes that would be needed to encode an
465    * enum field, including tag.  Caller is responsible for converting the
466    * enum value to its numeric value.
467    */
computeEnumSize(final int fieldNumber, final int value)468   public static int computeEnumSize(final int fieldNumber, final int value) {
469     return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
470   }
471 
472   /**
473    * Compute the number of bytes that would be needed to encode an
474    * {@code sfixed32} field, including tag.
475    */
computeSFixed32Size(final int fieldNumber, final int value)476   public static int computeSFixed32Size(final int fieldNumber,
477                                         final int value) {
478     return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
479   }
480 
481   /**
482    * Compute the number of bytes that would be needed to encode an
483    * {@code sfixed64} field, including tag.
484    */
computeSFixed64Size(final int fieldNumber, final long value)485   public static int computeSFixed64Size(final int fieldNumber,
486                                         final long value) {
487     return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
488   }
489 
490   /**
491    * Compute the number of bytes that would be needed to encode an
492    * {@code sint32} field, including tag.
493    */
computeSInt32Size(final int fieldNumber, final int value)494   public static int computeSInt32Size(final int fieldNumber, final int value) {
495     return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
496   }
497 
498   /**
499    * Compute the number of bytes that would be needed to encode an
500    * {@code sint64} field, including tag.
501    */
computeSInt64Size(final int fieldNumber, final long value)502   public static int computeSInt64Size(final int fieldNumber, final long value) {
503     return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
504   }
505 
506   /**
507    * Compute the number of bytes that would be needed to encode a
508    * MessageSet extension to the stream.  For historical reasons,
509    * the wire format differs from normal fields.
510    */
511 //  public static int computeMessageSetExtensionSize(
512 //      final int fieldNumber, final MessageMicro value) {
513 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
514 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
515 //           computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
516 //  }
517 
518   /**
519    * Compute the number of bytes that would be needed to encode an
520    * unparsed MessageSet extension field to the stream.  For
521    * historical reasons, the wire format differs from normal fields.
522    */
523 //  public static int computeRawMessageSetExtensionSize(
524 //      final int fieldNumber, final ByteStringMicro value) {
525 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
526 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
527 //           computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
528 //  }
529 
530   // -----------------------------------------------------------------
531 
532   /**
533    * Compute the number of bytes that would be needed to encode a
534    * {@code double} field, including tag.
535    */
computeDoubleSizeNoTag(final double value)536   public static int computeDoubleSizeNoTag(final double value) {
537     return LITTLE_ENDIAN_64_SIZE;
538   }
539 
540   /**
541    * Compute the number of bytes that would be needed to encode a
542    * {@code float} field, including tag.
543    */
computeFloatSizeNoTag(final float value)544   public static int computeFloatSizeNoTag(final float value) {
545     return LITTLE_ENDIAN_32_SIZE;
546   }
547 
548   /**
549    * Compute the number of bytes that would be needed to encode a
550    * {@code uint64} field, including tag.
551    */
computeUInt64SizeNoTag(final long value)552   public static int computeUInt64SizeNoTag(final long value) {
553     return computeRawVarint64Size(value);
554   }
555 
556   /**
557    * Compute the number of bytes that would be needed to encode an
558    * {@code int64} field, including tag.
559    */
computeInt64SizeNoTag(final long value)560   public static int computeInt64SizeNoTag(final long value) {
561     return computeRawVarint64Size(value);
562   }
563 
564   /**
565    * Compute the number of bytes that would be needed to encode an
566    * {@code int32} field, including tag.
567    */
computeInt32SizeNoTag(final int value)568   public static int computeInt32SizeNoTag(final int value) {
569     if (value >= 0) {
570       return computeRawVarint32Size(value);
571     } else {
572       // Must sign-extend.
573       return 10;
574     }
575   }
576 
577   /**
578    * Compute the number of bytes that would be needed to encode a
579    * {@code fixed64} field.
580    */
computeFixed64SizeNoTag(final long value)581   public static int computeFixed64SizeNoTag(final long value) {
582     return LITTLE_ENDIAN_64_SIZE;
583   }
584 
585   /**
586    * Compute the number of bytes that would be needed to encode a
587    * {@code fixed32} field.
588    */
computeFixed32SizeNoTag(final int value)589   public static int computeFixed32SizeNoTag(final int value) {
590     return LITTLE_ENDIAN_32_SIZE;
591   }
592 
593   /**
594    * Compute the number of bytes that would be needed to encode a
595    * {@code bool} field.
596    */
computeBoolSizeNoTag(final boolean value)597   public static int computeBoolSizeNoTag(final boolean value) {
598     return 1;
599   }
600 
601   /**
602    * Compute the number of bytes that would be needed to encode a
603    * {@code string} field.
604    */
computeStringSizeNoTag(final String value)605   public static int computeStringSizeNoTag(final String value) {
606     try {
607       final byte[] bytes = value.getBytes("UTF-8");
608       return computeRawVarint32Size(bytes.length) +
609              bytes.length;
610     } catch (UnsupportedEncodingException e) {
611       throw new RuntimeException("UTF-8 not supported.");
612     }
613   }
614 
615   /**
616    * Compute the number of bytes that would be needed to encode a
617    * {@code group} field.
618    */
computeGroupSizeNoTag(final MessageNano value)619   public static int computeGroupSizeNoTag(final MessageNano value) {
620     return value.getSerializedSize();
621   }
622 
623   /**
624    * Compute the number of bytes that would be needed to encode an embedded
625    * message field.
626    */
computeMessageSizeNoTag(final MessageNano value)627   public static int computeMessageSizeNoTag(final MessageNano value) {
628     final int size = value.getSerializedSize();
629     return computeRawVarint32Size(size) + size;
630   }
631 
632   /**
633    * Compute the number of bytes that would be needed to encode a
634    * {@code bytes} field.
635    */
computeBytesSizeNoTag(final byte[] value)636   public static int computeBytesSizeNoTag(final byte[] value) {
637     return computeRawVarint32Size(value.length) + value.length;
638   }
639 
640   /**
641    * Compute the number of bytes that would be needed to encode a
642    * {@code uint32} field.
643    */
computeUInt32SizeNoTag(final int value)644   public static int computeUInt32SizeNoTag(final int value) {
645     return computeRawVarint32Size(value);
646   }
647 
648   /**
649    * Compute the number of bytes that would be needed to encode an enum field.
650    * Caller is responsible for converting the enum value to its numeric value.
651    */
computeEnumSizeNoTag(final int value)652   public static int computeEnumSizeNoTag(final int value) {
653     return computeRawVarint32Size(value);
654   }
655 
656   /**
657    * Compute the number of bytes that would be needed to encode an
658    * {@code sfixed32} field.
659    */
computeSFixed32SizeNoTag(final int value)660   public static int computeSFixed32SizeNoTag(final int value) {
661     return LITTLE_ENDIAN_32_SIZE;
662   }
663 
664   /**
665    * Compute the number of bytes that would be needed to encode an
666    * {@code sfixed64} field.
667    */
computeSFixed64SizeNoTag(final long value)668   public static int computeSFixed64SizeNoTag(final long value) {
669     return LITTLE_ENDIAN_64_SIZE;
670   }
671 
672   /**
673    * Compute the number of bytes that would be needed to encode an
674    * {@code sint32} field.
675    */
computeSInt32SizeNoTag(final int value)676   public static int computeSInt32SizeNoTag(final int value) {
677     return computeRawVarint32Size(encodeZigZag32(value));
678   }
679 
680   /**
681    * Compute the number of bytes that would be needed to encode an
682    * {@code sint64} field.
683    */
computeSInt64SizeNoTag(final long value)684   public static int computeSInt64SizeNoTag(final long value) {
685     return computeRawVarint64Size(encodeZigZag64(value));
686   }
687 
688   // =================================================================
689 
690   /**
691    * If writing to a flat array, return the space left in the array.
692    * Otherwise, throws {@code UnsupportedOperationException}.
693    */
spaceLeft()694   public int spaceLeft() {
695     return limit - position;
696   }
697 
698   /**
699    * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
700    * a byte array that is exactly big enough to hold a message, then write to
701    * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
702    * after writing verifies that the message was actually as big as expected,
703    * which can help catch bugs.
704    */
checkNoSpaceLeft()705   public void checkNoSpaceLeft() {
706     if (spaceLeft() != 0) {
707       throw new IllegalStateException(
708         "Did not write as much data as expected.");
709     }
710   }
711 
712   /**
713    * If you create a CodedOutputStream around a simple flat array, you must
714    * not attempt to write more bytes than the array has space.  Otherwise,
715    * this exception will be thrown.
716    */
717   public static class OutOfSpaceException extends IOException {
718     private static final long serialVersionUID = -6947486886997889499L;
719 
OutOfSpaceException(int position, int limit)720     OutOfSpaceException(int position, int limit) {
721       super("CodedOutputStream was writing to a flat byte array and ran " +
722             "out of space (pos " + position + " limit " + limit + ").");
723     }
724   }
725 
726   /** Write a single byte. */
writeRawByte(final byte value)727   public void writeRawByte(final byte value) throws IOException {
728     if (position == limit) {
729       // We're writing to a single buffer.
730       throw new OutOfSpaceException(position, limit);
731     }
732 
733     buffer[position++] = value;
734   }
735 
736   /** Write a single byte, represented by an integer value. */
writeRawByte(final int value)737   public void writeRawByte(final int value) throws IOException {
738     writeRawByte((byte) value);
739   }
740 
741   /** Write an array of bytes. */
writeRawBytes(final byte[] value)742   public void writeRawBytes(final byte[] value) throws IOException {
743     writeRawBytes(value, 0, value.length);
744   }
745 
746   /** Write part of an array of bytes. */
writeRawBytes(final byte[] value, int offset, int length)747   public void writeRawBytes(final byte[] value, int offset, int length)
748                             throws IOException {
749     if (limit - position >= length) {
750       // We have room in the current buffer.
751       System.arraycopy(value, offset, buffer, position, length);
752       position += length;
753     } else {
754       // We're writing to a single buffer.
755       throw new OutOfSpaceException(position, limit);
756     }
757   }
758 
759   /** Encode and write a tag. */
writeTag(final int fieldNumber, final int wireType)760   public void writeTag(final int fieldNumber, final int wireType)
761                        throws IOException {
762     writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
763   }
764 
765   /** Compute the number of bytes that would be needed to encode a tag. */
computeTagSize(final int fieldNumber)766   public static int computeTagSize(final int fieldNumber) {
767     return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
768   }
769 
770   /**
771    * Encode and write a varint.  {@code value} is treated as
772    * unsigned, so it won't be sign-extended if negative.
773    */
writeRawVarint32(int value)774   public void writeRawVarint32(int value) throws IOException {
775     while (true) {
776       if ((value & ~0x7F) == 0) {
777         writeRawByte(value);
778         return;
779       } else {
780         writeRawByte((value & 0x7F) | 0x80);
781         value >>>= 7;
782       }
783     }
784   }
785 
786   /**
787    * Compute the number of bytes that would be needed to encode a varint.
788    * {@code value} is treated as unsigned, so it won't be sign-extended if
789    * negative.
790    */
computeRawVarint32Size(final int value)791   public static int computeRawVarint32Size(final int value) {
792     if ((value & (0xffffffff <<  7)) == 0) return 1;
793     if ((value & (0xffffffff << 14)) == 0) return 2;
794     if ((value & (0xffffffff << 21)) == 0) return 3;
795     if ((value & (0xffffffff << 28)) == 0) return 4;
796     return 5;
797   }
798 
799   /** Encode and write a varint. */
writeRawVarint64(long value)800   public void writeRawVarint64(long value) throws IOException {
801     while (true) {
802       if ((value & ~0x7FL) == 0) {
803         writeRawByte((int)value);
804         return;
805       } else {
806         writeRawByte(((int)value & 0x7F) | 0x80);
807         value >>>= 7;
808       }
809     }
810   }
811 
812   /** Compute the number of bytes that would be needed to encode a varint. */
computeRawVarint64Size(final long value)813   public static int computeRawVarint64Size(final long value) {
814     if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
815     if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
816     if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
817     if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
818     if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
819     if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
820     if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
821     if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
822     if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
823     return 10;
824   }
825 
826   /** Write a little-endian 32-bit integer. */
writeRawLittleEndian32(final int value)827   public void writeRawLittleEndian32(final int value) throws IOException {
828     writeRawByte((value      ) & 0xFF);
829     writeRawByte((value >>  8) & 0xFF);
830     writeRawByte((value >> 16) & 0xFF);
831     writeRawByte((value >> 24) & 0xFF);
832   }
833 
834   public static final int LITTLE_ENDIAN_32_SIZE = 4;
835 
836   /** Write a little-endian 64-bit integer. */
writeRawLittleEndian64(final long value)837   public void writeRawLittleEndian64(final long value) throws IOException {
838     writeRawByte((int)(value      ) & 0xFF);
839     writeRawByte((int)(value >>  8) & 0xFF);
840     writeRawByte((int)(value >> 16) & 0xFF);
841     writeRawByte((int)(value >> 24) & 0xFF);
842     writeRawByte((int)(value >> 32) & 0xFF);
843     writeRawByte((int)(value >> 40) & 0xFF);
844     writeRawByte((int)(value >> 48) & 0xFF);
845     writeRawByte((int)(value >> 56) & 0xFF);
846   }
847 
848   public static final int LITTLE_ENDIAN_64_SIZE = 8;
849 
850   /**
851    * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
852    * into values that can be efficiently encoded with varint.  (Otherwise,
853    * negative values must be sign-extended to 64 bits to be varint encoded,
854    * thus always taking 10 bytes on the wire.)
855    *
856    * @param n A signed 32-bit integer.
857    * @return An unsigned 32-bit integer, stored in a signed int because
858    *         Java has no explicit unsigned support.
859    */
encodeZigZag32(final int n)860   public static int encodeZigZag32(final int n) {
861     // Note:  the right-shift must be arithmetic
862     return (n << 1) ^ (n >> 31);
863   }
864 
865   /**
866    * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
867    * into values that can be efficiently encoded with varint.  (Otherwise,
868    * negative values must be sign-extended to 64 bits to be varint encoded,
869    * thus always taking 10 bytes on the wire.)
870    *
871    * @param n A signed 64-bit integer.
872    * @return An unsigned 64-bit integer, stored in a signed int because
873    *         Java has no explicit unsigned support.
874    */
encodeZigZag64(final long n)875   public static long encodeZigZag64(final long n) {
876     // Note:  the right-shift must be arithmetic
877     return (n << 1) ^ (n >> 63);
878   }
879 }
880