1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2013 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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.nio.BufferOverflowException;
35 import java.nio.ByteBuffer;
36 import java.nio.ByteOrder;
37 import java.nio.ReadOnlyBufferException;
38 
39 /**
40  * Encodes and writes protocol message fields.
41  *
42  * <p>This class contains two kinds of methods:  methods that write specific
43  * protocol message constructs and field types (e.g. {@link #writeTag} and
44  * {@link #writeInt32}) and methods that write low-level values (e.g.
45  * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
46  * writing encoded protocol messages, you should use the former methods, but if
47  * you are writing some other format of your own design, use the latter.
48  *
49  * <p>This class is totally unsynchronized.
50  *
51  * @author kneton@google.com Kenton Varda
52  */
53 public final class CodedOutputByteBufferNano {
54   /* max bytes per java UTF-16 char in UTF-8 */
55   private static final int MAX_UTF8_EXPANSION = 3;
56   private final ByteBuffer buffer;
57 
CodedOutputByteBufferNano(final byte[] buffer, final int offset, final int length)58   private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
59                             final int length) {
60     this(ByteBuffer.wrap(buffer, offset, length));
61   }
62 
CodedOutputByteBufferNano(final ByteBuffer buffer)63   private CodedOutputByteBufferNano(final ByteBuffer buffer) {
64     this.buffer = buffer;
65     this.buffer.order(ByteOrder.LITTLE_ENDIAN);
66   }
67 
68   /**
69    * Create a new {@code CodedOutputStream} that writes directly to the given
70    * byte array.  If more bytes are written than fit in the array,
71    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
72    * array is faster than writing to an {@code OutputStream}.
73    */
newInstance(final byte[] flatArray)74   public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) {
75     return newInstance(flatArray, 0, flatArray.length);
76   }
77 
78   /**
79    * Create a new {@code CodedOutputStream} that writes directly to the given
80    * byte array slice.  If more bytes are written than fit in the slice,
81    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
82    * array is faster than writing to an {@code OutputStream}.
83    */
newInstance(final byte[] flatArray, final int offset, final int length)84   public static CodedOutputByteBufferNano newInstance(final byte[] flatArray,
85                                               final int offset,
86                                               final int length) {
87     return new CodedOutputByteBufferNano(flatArray, offset, length);
88   }
89 
90   // -----------------------------------------------------------------
91 
92   /** Write a {@code double} field, including tag, to the stream. */
writeDouble(final int fieldNumber, final double value)93   public void writeDouble(final int fieldNumber, final double value)
94                           throws IOException {
95     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
96     writeDoubleNoTag(value);
97   }
98 
99   /** Write a {@code float} field, including tag, to the stream. */
writeFloat(final int fieldNumber, final float value)100   public void writeFloat(final int fieldNumber, final float value)
101                          throws IOException {
102     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
103     writeFloatNoTag(value);
104   }
105 
106   /** Write a {@code uint64} field, including tag, to the stream. */
writeUInt64(final int fieldNumber, final long value)107   public void writeUInt64(final int fieldNumber, final long value)
108                           throws IOException {
109     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
110     writeUInt64NoTag(value);
111   }
112 
113   /** Write an {@code int64} field, including tag, to the stream. */
writeInt64(final int fieldNumber, final long value)114   public void writeInt64(final int fieldNumber, final long value)
115                          throws IOException {
116     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
117     writeInt64NoTag(value);
118   }
119 
120   /** Write an {@code int32} field, including tag, to the stream. */
writeInt32(final int fieldNumber, final int value)121   public void writeInt32(final int fieldNumber, final int value)
122                          throws IOException {
123     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
124     writeInt32NoTag(value);
125   }
126 
127   /** Write a {@code fixed64} field, including tag, to the stream. */
writeFixed64(final int fieldNumber, final long value)128   public void writeFixed64(final int fieldNumber, final long value)
129                            throws IOException {
130     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
131     writeFixed64NoTag(value);
132   }
133 
134   /** Write a {@code fixed32} field, including tag, to the stream. */
writeFixed32(final int fieldNumber, final int value)135   public void writeFixed32(final int fieldNumber, final int value)
136                            throws IOException {
137     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
138     writeFixed32NoTag(value);
139   }
140 
141   /** Write a {@code bool} field, including tag, to the stream. */
writeBool(final int fieldNumber, final boolean value)142   public void writeBool(final int fieldNumber, final boolean value)
143                         throws IOException {
144     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
145     writeBoolNoTag(value);
146   }
147 
148   /** Write a {@code string} field, including tag, to the stream. */
writeString(final int fieldNumber, final String value)149   public void writeString(final int fieldNumber, final String value)
150                           throws IOException {
151     writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
152     writeStringNoTag(value);
153   }
154 
155   /** Write a {@code group} field, including tag, to the stream. */
writeGroup(final int fieldNumber, final MessageNano value)156   public void writeGroup(final int fieldNumber, final MessageNano value)
157                          throws IOException {
158     writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP);
159     writeGroupNoTag(value);
160     writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
161   }
162 
163   /** Write an embedded message field, including tag, to the stream. */
writeMessage(final int fieldNumber, final MessageNano value)164   public void writeMessage(final int fieldNumber, final MessageNano value)
165                            throws IOException {
166     writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
167     writeMessageNoTag(value);
168   }
169 
170   /** Write a {@code bytes} field, including tag, to the stream. */
writeBytes(final int fieldNumber, final byte[] value)171   public void writeBytes(final int fieldNumber, final byte[] value)
172                          throws IOException {
173     writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
174     writeBytesNoTag(value);
175   }
176 
177   /** Write a {@code bytes} field, including tag, to the stream. */
writeBytes(final int fieldNumber, final byte[] value, final int offset, final int length)178   public void writeBytes(final int fieldNumber, final byte[] value,
179                          final int offset, final int length)
180                          throws IOException {
181     writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
182     writeBytesNoTag(value, offset, length);
183   }
184 
185   /** Write a {@code uint32} field, including tag, to the stream. */
writeUInt32(final int fieldNumber, final int value)186   public void writeUInt32(final int fieldNumber, final int value)
187                           throws IOException {
188     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
189     writeUInt32NoTag(value);
190   }
191 
192   /**
193    * Write an enum field, including tag, to the stream.  Caller is responsible
194    * for converting the enum value to its numeric value.
195    */
writeEnum(final int fieldNumber, final int value)196   public void writeEnum(final int fieldNumber, final int value)
197                         throws IOException {
198     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
199     writeEnumNoTag(value);
200   }
201 
202   /** Write an {@code sfixed32} field, including tag, to the stream. */
writeSFixed32(final int fieldNumber, final int value)203   public void writeSFixed32(final int fieldNumber, final int value)
204                             throws IOException {
205     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32);
206     writeSFixed32NoTag(value);
207   }
208 
209   /** Write an {@code sfixed64} field, including tag, to the stream. */
writeSFixed64(final int fieldNumber, final long value)210   public void writeSFixed64(final int fieldNumber, final long value)
211                             throws IOException {
212     writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64);
213     writeSFixed64NoTag(value);
214   }
215 
216   /** Write an {@code sint32} field, including tag, to the stream. */
writeSInt32(final int fieldNumber, final int value)217   public void writeSInt32(final int fieldNumber, final int value)
218                           throws IOException {
219     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
220     writeSInt32NoTag(value);
221   }
222 
223   /** Write an {@code sint64} field, including tag, to the stream. */
writeSInt64(final int fieldNumber, final long value)224   public void writeSInt64(final int fieldNumber, final long value)
225                           throws IOException {
226     writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT);
227     writeSInt64NoTag(value);
228   }
229 
230   /**
231    * Write a MessageSet extension field to the stream.  For historical reasons,
232    * the wire format differs from normal fields.
233    */
234 //  public void writeMessageSetExtension(final int fieldNumber,
235 //                                       final MessageMicro value)
236 //                                       throws IOException {
237 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
238 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
239 //    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
240 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
241 //  }
242 
243   /**
244    * Write an unparsed MessageSet extension field to the stream.  For
245    * historical reasons, the wire format differs from normal fields.
246    */
247 //  public void writeRawMessageSetExtension(final int fieldNumber,
248 //                                          final ByteStringMicro value)
249 //                                          throws IOException {
250 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
251 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
252 //    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
253 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
254 //  }
255 
256   // -----------------------------------------------------------------
257 
258   /** Write a {@code double} field to the stream. */
writeDoubleNoTag(final double value)259   public void writeDoubleNoTag(final double value) throws IOException {
260     writeRawLittleEndian64(Double.doubleToLongBits(value));
261   }
262 
263   /** Write a {@code float} field to the stream. */
writeFloatNoTag(final float value)264   public void writeFloatNoTag(final float value) throws IOException {
265     writeRawLittleEndian32(Float.floatToIntBits(value));
266   }
267 
268   /** Write a {@code uint64} field to the stream. */
writeUInt64NoTag(final long value)269   public void writeUInt64NoTag(final long value) throws IOException {
270     writeRawVarint64(value);
271   }
272 
273   /** Write an {@code int64} field to the stream. */
writeInt64NoTag(final long value)274   public void writeInt64NoTag(final long value) throws IOException {
275     writeRawVarint64(value);
276   }
277 
278   /** Write an {@code int32} field to the stream. */
writeInt32NoTag(final int value)279   public void writeInt32NoTag(final int value) throws IOException {
280     if (value >= 0) {
281       writeRawVarint32(value);
282     } else {
283       // Must sign-extend.
284       writeRawVarint64(value);
285     }
286   }
287 
288   /** Write a {@code fixed64} field to the stream. */
writeFixed64NoTag(final long value)289   public void writeFixed64NoTag(final long value) throws IOException {
290     writeRawLittleEndian64(value);
291   }
292 
293   /** Write a {@code fixed32} field to the stream. */
writeFixed32NoTag(final int value)294   public void writeFixed32NoTag(final int value) throws IOException {
295     writeRawLittleEndian32(value);
296   }
297 
298   /** Write a {@code bool} field to the stream. */
writeBoolNoTag(final boolean value)299   public void writeBoolNoTag(final boolean value) throws IOException {
300     writeRawByte(value ? 1 : 0);
301   }
302 
303   /** Write a {@code string} field to the stream. */
writeStringNoTag(final String value)304   public void writeStringNoTag(final String value) throws IOException {
305     // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
306     // and at most 3 times of it. Optimize for the case where we know this length results in a
307     // constant varint length - saves measuring length of the string.
308     try {
309       final int minLengthVarIntSize = computeRawVarint32Size(value.length());
310       final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION);
311       if (minLengthVarIntSize == maxLengthVarIntSize) {
312         int oldPosition = buffer.position();
313         // Buffer.position, when passed a position that is past its limit, throws
314         // IllegalArgumentException, and this class is documented to throw
315         // OutOfSpaceException instead.
316         if (buffer.remaining() < minLengthVarIntSize) {
317           throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit());
318         }
319         buffer.position(oldPosition + minLengthVarIntSize);
320         encode(value, buffer);
321         int newPosition = buffer.position();
322         buffer.position(oldPosition);
323         writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize);
324         buffer.position(newPosition);
325       } else {
326         writeRawVarint32(encodedLength(value));
327         encode(value, buffer);
328       }
329     } catch (BufferOverflowException e) {
330       final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(),
331           buffer.limit());
332       outOfSpaceException.initCause(e);
333       throw outOfSpaceException;
334     }
335   }
336 
337   // These UTF-8 handling methods are copied from Guava's Utf8 class.
338   /**
339    * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
340    * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
341    * both time and space.
342    *
343    * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
344    *     surrogates)
345    */
encodedLength(CharSequence sequence)346   private static int encodedLength(CharSequence sequence) {
347     // Warning to maintainers: this implementation is highly optimized.
348     int utf16Length = sequence.length();
349     int utf8Length = utf16Length;
350     int i = 0;
351 
352     // This loop optimizes for pure ASCII.
353     while (i < utf16Length && sequence.charAt(i) < 0x80) {
354       i++;
355     }
356 
357     // This loop optimizes for chars less than 0x800.
358     for (; i < utf16Length; i++) {
359       char c = sequence.charAt(i);
360       if (c < 0x800) {
361         utf8Length += ((0x7f - c) >>> 31);  // branch free!
362       } else {
363         utf8Length += encodedLengthGeneral(sequence, i);
364         break;
365       }
366     }
367 
368     if (utf8Length < utf16Length) {
369       // Necessary and sufficient condition for overflow because of maximum 3x expansion
370       throw new IllegalArgumentException("UTF-8 length does not fit in int: "
371               + (utf8Length + (1L << 32)));
372     }
373     return utf8Length;
374   }
375 
encodedLengthGeneral(CharSequence sequence, int start)376   private static int encodedLengthGeneral(CharSequence sequence, int start) {
377     int utf16Length = sequence.length();
378     int utf8Length = 0;
379     for (int i = start; i < utf16Length; i++) {
380       char c = sequence.charAt(i);
381       if (c < 0x800) {
382         utf8Length += (0x7f - c) >>> 31; // branch free!
383       } else {
384         utf8Length += 2;
385         // jdk7+: if (Character.isSurrogate(c)) {
386         if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
387           // Check that we have a well-formed surrogate pair.
388           int cp = Character.codePointAt(sequence, i);
389           if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
390             throw new IllegalArgumentException("Unpaired surrogate at index " + i);
391           }
392           i++;
393         }
394       }
395     }
396     return utf8Length;
397   }
398 
399   /**
400    * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is
401    * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time
402    * and space. Bytes are written starting at the current position. This method requires paired
403    * surrogates, and therefore does not support chunking.
404    *
405    * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
406    * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the
407    * largest possible number of bytes that any input can be encoded to.
408    *
409    * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
410    *     surrogates)
411    * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in
412    *     {@code byteBuffer}'s remaining space.
413    * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer.
414    */
encode(CharSequence sequence, ByteBuffer byteBuffer)415   private static void encode(CharSequence sequence, ByteBuffer byteBuffer) {
416     if (byteBuffer.isReadOnly()) {
417       throw new ReadOnlyBufferException();
418     } else if (byteBuffer.hasArray()) {
419       try {
420         int encoded = encode(sequence,
421                 byteBuffer.array(),
422                 byteBuffer.arrayOffset() + byteBuffer.position(),
423                 byteBuffer.remaining());
424         byteBuffer.position(encoded - byteBuffer.arrayOffset());
425       } catch (ArrayIndexOutOfBoundsException e) {
426         BufferOverflowException boe = new BufferOverflowException();
427         boe.initCause(e);
428         throw boe;
429       }
430     } else {
431       encodeDirect(sequence, byteBuffer);
432     }
433   }
434 
encodeDirect(CharSequence sequence, ByteBuffer byteBuffer)435   private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) {
436     int utf16Length = sequence.length();
437     for (int i = 0; i < utf16Length; i++) {
438       final char c = sequence.charAt(i);
439       if (c < 0x80) { // ASCII
440         byteBuffer.put((byte) c);
441       } else if (c < 0x800) { // 11 bits, two UTF-8 bytes
442         byteBuffer.put((byte) ((0xF << 6) | (c >>> 6)));
443         byteBuffer.put((byte) (0x80 | (0x3F & c)));
444       } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) {
445         // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
446         byteBuffer.put((byte) ((0xF << 5) | (c >>> 12)));
447         byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6))));
448         byteBuffer.put((byte) (0x80 | (0x3F & c)));
449       } else {
450         final char low;
451         if (i + 1 == sequence.length()
452                 || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
453           throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
454         }
455         int codePoint = Character.toCodePoint(c, low);
456         byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18)));
457         byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12))));
458         byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6))));
459         byteBuffer.put((byte) (0x80 | (0x3F & codePoint)));
460       }
461     }
462   }
463 
encode(CharSequence sequence, byte[] bytes, int offset, int length)464   private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
465     int utf16Length = sequence.length();
466     int j = offset;
467     int i = 0;
468     int limit = offset + length;
469     // Designed to take advantage of
470     // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
471     for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
472       bytes[j + i] = (byte) c;
473     }
474     if (i == utf16Length) {
475       return j + utf16Length;
476     }
477     j += i;
478     for (char c; i < utf16Length; i++) {
479       c = sequence.charAt(i);
480       if (c < 0x80 && j < limit) {
481         bytes[j++] = (byte) c;
482       } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
483         bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
484         bytes[j++] = (byte) (0x80 | (0x3F & c));
485       } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
486         // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
487         bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
488         bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
489         bytes[j++] = (byte) (0x80 | (0x3F & c));
490       } else if (j <= limit - 4) {
491         // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
492         final char low;
493         if (i + 1 == sequence.length()
494                 || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
495           throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
496         }
497         int codePoint = Character.toCodePoint(c, low);
498         bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
499         bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
500         bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
501         bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
502       } else {
503         throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
504       }
505     }
506     return j;
507   }
508 
509   // End guava UTF-8 methods
510 
511 
512   /** Write a {@code group} field to the stream. */
writeGroupNoTag(final MessageNano value)513   public void writeGroupNoTag(final MessageNano value) throws IOException {
514     value.writeTo(this);
515   }
516 
517   /** Write an embedded message field to the stream. */
writeMessageNoTag(final MessageNano value)518   public void writeMessageNoTag(final MessageNano value) throws IOException {
519     writeRawVarint32(value.getCachedSize());
520     value.writeTo(this);
521   }
522 
523   /** Write a {@code bytes} field to the stream. */
writeBytesNoTag(final byte[] value)524   public void writeBytesNoTag(final byte[] value) throws IOException {
525     writeRawVarint32(value.length);
526     writeRawBytes(value);
527   }
528 
529   /** Write a {@code bytes} field to the stream. */
writeBytesNoTag(final byte[] value, final int offset, final int length)530   public void writeBytesNoTag(final byte[] value, final int offset, final int length)
531                               throws IOException {
532     writeRawVarint32(length);
533     writeRawBytes(value, offset, length);
534   }
535 
536   /** Write a {@code uint32} field to the stream. */
writeUInt32NoTag(final int value)537   public void writeUInt32NoTag(final int value) throws IOException {
538     writeRawVarint32(value);
539   }
540 
541   /**
542    * Write an enum field to the stream.  Caller is responsible
543    * for converting the enum value to its numeric value.
544    */
writeEnumNoTag(final int value)545   public void writeEnumNoTag(final int value) throws IOException {
546     writeRawVarint32(value);
547   }
548 
549   /** Write an {@code sfixed32} field to the stream. */
writeSFixed32NoTag(final int value)550   public void writeSFixed32NoTag(final int value) throws IOException {
551     writeRawLittleEndian32(value);
552   }
553 
554   /** Write an {@code sfixed64} field to the stream. */
writeSFixed64NoTag(final long value)555   public void writeSFixed64NoTag(final long value) throws IOException {
556     writeRawLittleEndian64(value);
557   }
558 
559   /** Write an {@code sint32} field to the stream. */
writeSInt32NoTag(final int value)560   public void writeSInt32NoTag(final int value) throws IOException {
561     writeRawVarint32(encodeZigZag32(value));
562   }
563 
564   /** Write an {@code sint64} field to the stream. */
writeSInt64NoTag(final long value)565   public void writeSInt64NoTag(final long value) throws IOException {
566     writeRawVarint64(encodeZigZag64(value));
567   }
568 
569   // =================================================================
570 
571   /**
572    * Compute the number of bytes that would be needed to encode a
573    * {@code double} field, including tag.
574    */
computeDoubleSize(final int fieldNumber, final double value)575   public static int computeDoubleSize(final int fieldNumber,
576                                       final double value) {
577     return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
578   }
579 
580   /**
581    * Compute the number of bytes that would be needed to encode a
582    * {@code float} field, including tag.
583    */
computeFloatSize(final int fieldNumber, final float value)584   public static int computeFloatSize(final int fieldNumber, final float value) {
585     return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
586   }
587 
588   /**
589    * Compute the number of bytes that would be needed to encode a
590    * {@code uint64} field, including tag.
591    */
computeUInt64Size(final int fieldNumber, final long value)592   public static int computeUInt64Size(final int fieldNumber, final long value) {
593     return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
594   }
595 
596   /**
597    * Compute the number of bytes that would be needed to encode an
598    * {@code int64} field, including tag.
599    */
computeInt64Size(final int fieldNumber, final long value)600   public static int computeInt64Size(final int fieldNumber, final long value) {
601     return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
602   }
603 
604   /**
605    * Compute the number of bytes that would be needed to encode an
606    * {@code int32} field, including tag.
607    */
computeInt32Size(final int fieldNumber, final int value)608   public static int computeInt32Size(final int fieldNumber, final int value) {
609     return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
610   }
611 
612   /**
613    * Compute the number of bytes that would be needed to encode a
614    * {@code fixed64} field, including tag.
615    */
computeFixed64Size(final int fieldNumber, final long value)616   public static int computeFixed64Size(final int fieldNumber,
617                                        final long value) {
618     return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
619   }
620 
621   /**
622    * Compute the number of bytes that would be needed to encode a
623    * {@code fixed32} field, including tag.
624    */
computeFixed32Size(final int fieldNumber, final int value)625   public static int computeFixed32Size(final int fieldNumber,
626                                        final int value) {
627     return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
628   }
629 
630   /**
631    * Compute the number of bytes that would be needed to encode a
632    * {@code bool} field, including tag.
633    */
computeBoolSize(final int fieldNumber, final boolean value)634   public static int computeBoolSize(final int fieldNumber,
635                                     final boolean value) {
636     return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
637   }
638 
639   /**
640    * Compute the number of bytes that would be needed to encode a
641    * {@code string} field, including tag.
642    */
computeStringSize(final int fieldNumber, final String value)643   public static int computeStringSize(final int fieldNumber,
644                                       final String value) {
645     return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
646   }
647 
648   /**
649    * Compute the number of bytes that would be needed to encode a
650    * {@code group} field, including tag.
651    */
computeGroupSize(final int fieldNumber, final MessageNano value)652   public static int computeGroupSize(final int fieldNumber,
653                                      final MessageNano value) {
654     return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
655   }
656 
657   /**
658    * Compute the number of bytes that would be needed to encode an
659    * embedded message field, including tag.
660    */
computeMessageSize(final int fieldNumber, final MessageNano value)661   public static int computeMessageSize(final int fieldNumber,
662                                        final MessageNano value) {
663     return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
664   }
665 
666   /**
667    * Compute the number of bytes that would be needed to encode a
668    * {@code bytes} field, including tag.
669    */
computeBytesSize(final int fieldNumber, final byte[] value)670   public static int computeBytesSize(final int fieldNumber,
671                                      final byte[] value) {
672     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
673   }
674 
675   /**
676    * Compute the number of bytes that would be needed to encode a
677    * {@code bytes} field of the given length, including tag.
678    */
computeBytesSize(final int fieldNumber, final int length)679   public static int computeBytesSize(final int fieldNumber,
680                                      final int length) {
681     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(length);
682   }
683 
684   /**
685    * Compute the number of bytes that would be needed to encode a
686    * {@code uint32} field, including tag.
687    */
computeUInt32Size(final int fieldNumber, final int value)688   public static int computeUInt32Size(final int fieldNumber, final int value) {
689     return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
690   }
691 
692   /**
693    * Compute the number of bytes that would be needed to encode an
694    * enum field, including tag.  Caller is responsible for converting the
695    * enum value to its numeric value.
696    */
computeEnumSize(final int fieldNumber, final int value)697   public static int computeEnumSize(final int fieldNumber, final int value) {
698     return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
699   }
700 
701   /**
702    * Compute the number of bytes that would be needed to encode an
703    * {@code sfixed32} field, including tag.
704    */
computeSFixed32Size(final int fieldNumber, final int value)705   public static int computeSFixed32Size(final int fieldNumber,
706                                         final int value) {
707     return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
708   }
709 
710   /**
711    * Compute the number of bytes that would be needed to encode an
712    * {@code sfixed64} field, including tag.
713    */
computeSFixed64Size(final int fieldNumber, final long value)714   public static int computeSFixed64Size(final int fieldNumber,
715                                         final long value) {
716     return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
717   }
718 
719   /**
720    * Compute the number of bytes that would be needed to encode an
721    * {@code sint32} field, including tag.
722    */
computeSInt32Size(final int fieldNumber, final int value)723   public static int computeSInt32Size(final int fieldNumber, final int value) {
724     return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
725   }
726 
727   /**
728    * Compute the number of bytes that would be needed to encode an
729    * {@code sint64} field, including tag.
730    */
computeSInt64Size(final int fieldNumber, final long value)731   public static int computeSInt64Size(final int fieldNumber, final long value) {
732     return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
733   }
734 
735   /**
736    * Compute the number of bytes that would be needed to encode a
737    * MessageSet extension to the stream.  For historical reasons,
738    * the wire format differs from normal fields.
739    */
740 //  public static int computeMessageSetExtensionSize(
741 //      final int fieldNumber, final MessageMicro value) {
742 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
743 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
744 //           computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
745 //  }
746 
747   /**
748    * Compute the number of bytes that would be needed to encode an
749    * unparsed MessageSet extension field to the stream.  For
750    * historical reasons, the wire format differs from normal fields.
751    */
752 //  public static int computeRawMessageSetExtensionSize(
753 //      final int fieldNumber, final ByteStringMicro value) {
754 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
755 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
756 //           computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
757 //  }
758 
759   // -----------------------------------------------------------------
760 
761   /**
762    * Compute the number of bytes that would be needed to encode a
763    * {@code double} field, including tag.
764    */
computeDoubleSizeNoTag(final double value)765   public static int computeDoubleSizeNoTag(final double value) {
766     return LITTLE_ENDIAN_64_SIZE;
767   }
768 
769   /**
770    * Compute the number of bytes that would be needed to encode a
771    * {@code float} field, including tag.
772    */
computeFloatSizeNoTag(final float value)773   public static int computeFloatSizeNoTag(final float value) {
774     return LITTLE_ENDIAN_32_SIZE;
775   }
776 
777   /**
778    * Compute the number of bytes that would be needed to encode a
779    * {@code uint64} field, including tag.
780    */
computeUInt64SizeNoTag(final long value)781   public static int computeUInt64SizeNoTag(final long value) {
782     return computeRawVarint64Size(value);
783   }
784 
785   /**
786    * Compute the number of bytes that would be needed to encode an
787    * {@code int64} field, including tag.
788    */
computeInt64SizeNoTag(final long value)789   public static int computeInt64SizeNoTag(final long value) {
790     return computeRawVarint64Size(value);
791   }
792 
793   /**
794    * Compute the number of bytes that would be needed to encode an
795    * {@code int32} field, including tag.
796    */
computeInt32SizeNoTag(final int value)797   public static int computeInt32SizeNoTag(final int value) {
798     if (value >= 0) {
799       return computeRawVarint32Size(value);
800     } else {
801       // Must sign-extend.
802       return 10;
803     }
804   }
805 
806   /**
807    * Compute the number of bytes that would be needed to encode a
808    * {@code fixed64} field.
809    */
computeFixed64SizeNoTag(final long value)810   public static int computeFixed64SizeNoTag(final long value) {
811     return LITTLE_ENDIAN_64_SIZE;
812   }
813 
814   /**
815    * Compute the number of bytes that would be needed to encode a
816    * {@code fixed32} field.
817    */
computeFixed32SizeNoTag(final int value)818   public static int computeFixed32SizeNoTag(final int value) {
819     return LITTLE_ENDIAN_32_SIZE;
820   }
821 
822   /**
823    * Compute the number of bytes that would be needed to encode a
824    * {@code bool} field.
825    */
computeBoolSizeNoTag(final boolean value)826   public static int computeBoolSizeNoTag(final boolean value) {
827     return 1;
828   }
829 
830   /**
831    * Compute the number of bytes that would be needed to encode a
832    * {@code string} field.
833    */
computeStringSizeNoTag(final String value)834   public static int computeStringSizeNoTag(final String value) {
835     final int length = encodedLength(value);
836     return computeRawVarint32Size(length) + length;
837   }
838 
839   /**
840    * Compute the number of bytes that would be needed to encode a
841    * {@code group} field.
842    */
computeGroupSizeNoTag(final MessageNano value)843   public static int computeGroupSizeNoTag(final MessageNano value) {
844     return value.getSerializedSize();
845   }
846 
847   /**
848    * Compute the number of bytes that would be needed to encode an embedded
849    * message field.
850    */
computeMessageSizeNoTag(final MessageNano value)851   public static int computeMessageSizeNoTag(final MessageNano value) {
852     final int size = value.getSerializedSize();
853     return computeRawVarint32Size(size) + size;
854   }
855 
856   /**
857    * Compute the number of bytes that would be needed to encode a
858    * {@code bytes} field.
859    */
computeBytesSizeNoTag(final byte[] value)860   public static int computeBytesSizeNoTag(final byte[] value) {
861     return computeRawVarint32Size(value.length) + value.length;
862   }
863 
864   /**
865    * Compute the number of bytes that would be needed to encode a
866    * {@code bytes} field of the given length.
867    */
computeBytesSizeNoTag(final int length)868   public static int computeBytesSizeNoTag(final int length) {
869     return computeRawVarint32Size(length) + length;
870   }
871 
872   /**
873    * Compute the number of bytes that would be needed to encode a
874    * {@code uint32} field.
875    */
computeUInt32SizeNoTag(final int value)876   public static int computeUInt32SizeNoTag(final int value) {
877     return computeRawVarint32Size(value);
878   }
879 
880   /**
881    * Compute the number of bytes that would be needed to encode an enum field.
882    * Caller is responsible for converting the enum value to its numeric value.
883    */
computeEnumSizeNoTag(final int value)884   public static int computeEnumSizeNoTag(final int value) {
885     return computeRawVarint32Size(value);
886   }
887 
888   /**
889    * Compute the number of bytes that would be needed to encode an
890    * {@code sfixed32} field.
891    */
computeSFixed32SizeNoTag(final int value)892   public static int computeSFixed32SizeNoTag(final int value) {
893     return LITTLE_ENDIAN_32_SIZE;
894   }
895 
896   /**
897    * Compute the number of bytes that would be needed to encode an
898    * {@code sfixed64} field.
899    */
computeSFixed64SizeNoTag(final long value)900   public static int computeSFixed64SizeNoTag(final long value) {
901     return LITTLE_ENDIAN_64_SIZE;
902   }
903 
904   /**
905    * Compute the number of bytes that would be needed to encode an
906    * {@code sint32} field.
907    */
computeSInt32SizeNoTag(final int value)908   public static int computeSInt32SizeNoTag(final int value) {
909     return computeRawVarint32Size(encodeZigZag32(value));
910   }
911 
912   /**
913    * Compute the number of bytes that would be needed to encode an
914    * {@code sint64} field.
915    */
computeSInt64SizeNoTag(final long value)916   public static int computeSInt64SizeNoTag(final long value) {
917     return computeRawVarint64Size(encodeZigZag64(value));
918   }
919 
920   // =================================================================
921 
922   /**
923    * If writing to a flat array, return the space left in the array.
924    * Otherwise, throws {@code UnsupportedOperationException}.
925    */
spaceLeft()926   public int spaceLeft() {
927     return buffer.remaining();
928   }
929 
930   /**
931    * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
932    * a byte array that is exactly big enough to hold a message, then write to
933    * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
934    * after writing verifies that the message was actually as big as expected,
935    * which can help catch bugs.
936    */
checkNoSpaceLeft()937   public void checkNoSpaceLeft() {
938     if (spaceLeft() != 0) {
939       throw new IllegalStateException(
940         "Did not write as much data as expected.");
941     }
942   }
943 
944   /**
945    * Returns the position within the internal buffer.
946    */
position()947   public int position() {
948     return buffer.position();
949   }
950 
951   /**
952    * Resets the position within the internal buffer to zero.
953    *
954    * @see #position
955    * @see #spaceLeft
956    */
reset()957   public void reset() {
958     buffer.clear();
959   }
960 
961   /**
962    * If you create a CodedOutputStream around a simple flat array, you must
963    * not attempt to write more bytes than the array has space.  Otherwise,
964    * this exception will be thrown.
965    */
966   public static class OutOfSpaceException extends IOException {
967     private static final long serialVersionUID = -6947486886997889499L;
968 
OutOfSpaceException(int position, int limit)969     OutOfSpaceException(int position, int limit) {
970       super("CodedOutputStream was writing to a flat byte array and ran " +
971             "out of space (pos " + position + " limit " + limit + ").");
972     }
973   }
974 
975   /** Write a single byte. */
writeRawByte(final byte value)976   public void writeRawByte(final byte value) throws IOException {
977     if (!buffer.hasRemaining()) {
978       // We're writing to a single buffer.
979       throw new OutOfSpaceException(buffer.position(), buffer.limit());
980     }
981 
982     buffer.put(value);
983   }
984 
985   /** Write a single byte, represented by an integer value. */
writeRawByte(final int value)986   public void writeRawByte(final int value) throws IOException {
987     writeRawByte((byte) value);
988   }
989 
990   /** Write an array of bytes. */
writeRawBytes(final byte[] value)991   public void writeRawBytes(final byte[] value) throws IOException {
992     writeRawBytes(value, 0, value.length);
993   }
994 
995   /** Write part of an array of bytes. */
writeRawBytes(final byte[] value, int offset, int length)996   public void writeRawBytes(final byte[] value, int offset, int length)
997                             throws IOException {
998     if (buffer.remaining() >= length) {
999       buffer.put(value, offset, length);
1000     } else {
1001       // We're writing to a single buffer.
1002       throw new OutOfSpaceException(buffer.position(), buffer.limit());
1003     }
1004   }
1005 
1006   /** Encode and write a tag. */
writeTag(final int fieldNumber, final int wireType)1007   public void writeTag(final int fieldNumber, final int wireType)
1008                        throws IOException {
1009     writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType));
1010   }
1011 
1012   /** Compute the number of bytes that would be needed to encode a tag. */
computeTagSize(final int fieldNumber)1013   public static int computeTagSize(final int fieldNumber) {
1014     return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0));
1015   }
1016 
1017   /**
1018    * Encode and write a varint.  {@code value} is treated as
1019    * unsigned, so it won't be sign-extended if negative.
1020    */
writeRawVarint32(int value)1021   public void writeRawVarint32(int value) throws IOException {
1022     while (true) {
1023       if ((value & ~0x7F) == 0) {
1024         writeRawByte(value);
1025         return;
1026       } else {
1027         writeRawByte((value & 0x7F) | 0x80);
1028         value >>>= 7;
1029       }
1030     }
1031   }
1032 
1033   /**
1034    * Compute the number of bytes that would be needed to encode a varint.
1035    * {@code value} is treated as unsigned, so it won't be sign-extended if
1036    * negative.
1037    */
computeRawVarint32Size(final int value)1038   public static int computeRawVarint32Size(final int value) {
1039     if ((value & (0xffffffff <<  7)) == 0) return 1;
1040     if ((value & (0xffffffff << 14)) == 0) return 2;
1041     if ((value & (0xffffffff << 21)) == 0) return 3;
1042     if ((value & (0xffffffff << 28)) == 0) return 4;
1043     return 5;
1044   }
1045 
1046   /** Encode and write a varint. */
writeRawVarint64(long value)1047   public void writeRawVarint64(long value) throws IOException {
1048     while (true) {
1049       if ((value & ~0x7FL) == 0) {
1050         writeRawByte((int)value);
1051         return;
1052       } else {
1053         writeRawByte(((int)value & 0x7F) | 0x80);
1054         value >>>= 7;
1055       }
1056     }
1057   }
1058 
1059   /** Compute the number of bytes that would be needed to encode a varint. */
computeRawVarint64Size(final long value)1060   public static int computeRawVarint64Size(final long value) {
1061     if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
1062     if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
1063     if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
1064     if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
1065     if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
1066     if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
1067     if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
1068     if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
1069     if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
1070     return 10;
1071   }
1072 
1073   /** Write a little-endian 32-bit integer. */
writeRawLittleEndian32(final int value)1074   public void writeRawLittleEndian32(final int value) throws IOException {
1075     if (buffer.remaining() < 4) {
1076       throw new OutOfSpaceException(buffer.position(), buffer.limit());
1077     }
1078     buffer.putInt(value);
1079   }
1080 
1081   public static final int LITTLE_ENDIAN_32_SIZE = 4;
1082 
1083   /** Write a little-endian 64-bit integer. */
writeRawLittleEndian64(final long value)1084   public void writeRawLittleEndian64(final long value) throws IOException {
1085     if (buffer.remaining() < 8) {
1086       throw new OutOfSpaceException(buffer.position(), buffer.limit());
1087     }
1088     buffer.putLong(value);
1089   }
1090 
1091   public static final int LITTLE_ENDIAN_64_SIZE = 8;
1092 
1093   /**
1094    * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
1095    * into values that can be efficiently encoded with varint.  (Otherwise,
1096    * negative values must be sign-extended to 64 bits to be varint encoded,
1097    * thus always taking 10 bytes on the wire.)
1098    *
1099    * @param n A signed 32-bit integer.
1100    * @return An unsigned 32-bit integer, stored in a signed int because
1101    *         Java has no explicit unsigned support.
1102    */
encodeZigZag32(final int n)1103   public static int encodeZigZag32(final int n) {
1104     // Note:  the right-shift must be arithmetic
1105     return (n << 1) ^ (n >> 31);
1106   }
1107 
1108   /**
1109    * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
1110    * into values that can be efficiently encoded with varint.  (Otherwise,
1111    * negative values must be sign-extended to 64 bits to be varint encoded,
1112    * thus always taking 10 bytes on the wire.)
1113    *
1114    * @param n A signed 64-bit integer.
1115    * @return An unsigned 64-bit integer, stored in a signed int because
1116    *         Java has no explicit unsigned support.
1117    */
encodeZigZag64(final long n)1118   public static long encodeZigZag64(final long n) {
1119     // Note:  the right-shift must be arithmetic
1120     return (n << 1) ^ (n >> 63);
1121   }
1122 
computeFieldSize(int number, int type, Object object)1123   static int computeFieldSize(int number, int type, Object object) {
1124     switch (type) {
1125       case InternalNano.TYPE_BOOL:
1126         return computeBoolSize(number, (Boolean) object);
1127       case InternalNano.TYPE_BYTES:
1128         return computeBytesSize(number, (byte[]) object);
1129       case InternalNano.TYPE_STRING:
1130         return computeStringSize(number, (String) object);
1131       case InternalNano.TYPE_FLOAT:
1132         return computeFloatSize(number, (Float) object);
1133       case InternalNano.TYPE_DOUBLE:
1134         return computeDoubleSize(number, (Double) object);
1135       case InternalNano.TYPE_ENUM:
1136         return computeEnumSize(number, (Integer) object);
1137       case InternalNano.TYPE_FIXED32:
1138         return computeFixed32Size(number, (Integer) object);
1139       case InternalNano.TYPE_INT32:
1140         return computeInt32Size(number, (Integer) object);
1141       case InternalNano.TYPE_UINT32:
1142         return computeUInt32Size(number, (Integer) object);
1143       case InternalNano.TYPE_SINT32:
1144         return computeSInt32Size(number, (Integer) object);
1145       case InternalNano.TYPE_SFIXED32:
1146         return computeSFixed32Size(number, (Integer) object);
1147       case InternalNano.TYPE_INT64:
1148         return computeInt64Size(number, (Long) object);
1149       case InternalNano.TYPE_UINT64:
1150         return computeUInt64Size(number, (Long) object);
1151       case InternalNano.TYPE_SINT64:
1152         return computeSInt64Size(number, (Long) object);
1153       case InternalNano.TYPE_FIXED64:
1154         return computeFixed64Size(number, (Long) object);
1155       case InternalNano.TYPE_SFIXED64:
1156         return computeSFixed64Size(number, (Long) object);
1157       case InternalNano.TYPE_MESSAGE:
1158         return computeMessageSize(number, (MessageNano) object);
1159       case InternalNano.TYPE_GROUP:
1160         return computeGroupSize(number, (MessageNano) object);
1161       default:
1162         throw new IllegalArgumentException("Unknown type: " + type);
1163     }
1164   }
1165 
writeField(int number, int type, Object value)1166   void writeField(int number, int type, Object value)
1167       throws IOException {
1168     switch (type) {
1169       case InternalNano.TYPE_DOUBLE:
1170         Double doubleValue = (Double) value;
1171         writeDouble(number, doubleValue);
1172         break;
1173       case InternalNano.TYPE_FLOAT:
1174         Float floatValue = (Float) value;
1175         writeFloat(number, floatValue);
1176         break;
1177       case InternalNano.TYPE_INT64:
1178         Long int64Value = (Long) value;
1179         writeInt64(number, int64Value);
1180         break;
1181       case InternalNano.TYPE_UINT64:
1182         Long uint64Value = (Long) value;
1183         writeUInt64(number, uint64Value);
1184         break;
1185       case InternalNano.TYPE_INT32:
1186         Integer int32Value = (Integer) value;
1187         writeInt32(number, int32Value);
1188         break;
1189       case InternalNano.TYPE_FIXED64:
1190         Long fixed64Value = (Long) value;
1191         writeFixed64(number, fixed64Value);
1192         break;
1193       case InternalNano.TYPE_FIXED32:
1194         Integer fixed32Value = (Integer) value;
1195         writeFixed32(number, fixed32Value);
1196         break;
1197       case InternalNano.TYPE_BOOL:
1198         Boolean boolValue = (Boolean) value;
1199         writeBool(number, boolValue);
1200         break;
1201       case InternalNano.TYPE_STRING:
1202         String stringValue = (String) value;
1203         writeString(number, stringValue);
1204         break;
1205       case InternalNano.TYPE_BYTES:
1206         byte[] bytesValue = (byte[]) value;
1207         writeBytes(number, bytesValue);
1208         break;
1209       case InternalNano.TYPE_UINT32:
1210         Integer uint32Value = (Integer) value;
1211         writeUInt32(number, uint32Value);
1212         break;
1213       case InternalNano.TYPE_ENUM:
1214         Integer enumValue = (Integer) value;
1215         writeEnum(number, enumValue);
1216         break;
1217       case InternalNano.TYPE_SFIXED32:
1218         Integer sfixed32Value = (Integer) value;
1219         writeSFixed32(number, sfixed32Value);
1220         break;
1221       case InternalNano.TYPE_SFIXED64:
1222         Long sfixed64Value = (Long) value;
1223         writeSFixed64(number, sfixed64Value);
1224         break;
1225       case InternalNano.TYPE_SINT32:
1226         Integer sint32Value = (Integer) value;
1227         writeSInt32(number, sint32Value);
1228         break;
1229       case InternalNano.TYPE_SINT64:
1230         Long sint64Value = (Long) value;
1231         writeSInt64(number, sint64Value);
1232         break;
1233       case InternalNano.TYPE_MESSAGE:
1234         MessageNano messageValue = (MessageNano) value;
1235         writeMessage(number, messageValue);
1236         break;
1237       case InternalNano.TYPE_GROUP:
1238         MessageNano groupValue = (MessageNano) value;
1239         writeGroup(number, groupValue);
1240         break;
1241       default:
1242         throw new IOException("Unknown type: " + type);
1243     }
1244   }
1245 
1246 }
1247