Home | History | Annotate | Download | only in protobuf
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 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;
     32 
     33 import static java.lang.Math.max;
     34 
     35 import com.google.protobuf.Utf8.UnpairedSurrogateException;
     36 
     37 import java.io.IOException;
     38 import java.io.OutputStream;
     39 import java.lang.reflect.Field;
     40 import java.nio.BufferOverflowException;
     41 import java.nio.ByteBuffer;
     42 import java.nio.ByteOrder;
     43 import java.security.AccessController;
     44 import java.security.PrivilegedExceptionAction;
     45 import java.util.logging.Level;
     46 import java.util.logging.Logger;
     47 
     48 /**
     49  * Encodes and writes protocol message fields.
     50  *
     51  * <p>This class contains two kinds of methods:  methods that write specific
     52  * protocol message constructs and field types (e.g. {@link #writeTag} and
     53  * {@link #writeInt32}) and methods that write low-level values (e.g.
     54  * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
     55  * writing encoded protocol messages, you should use the former methods, but if
     56  * you are writing some other format of your own design, use the latter.
     57  *
     58  * <p>This class is totally unsynchronized.
     59  */
     60 public abstract class CodedOutputStream extends ByteOutput {
     61   private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
     62   private static final sun.misc.Unsafe UNSAFE = getUnsafe();
     63   private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
     64   private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
     65 
     66   private static final int FIXED_32_SIZE = 4;
     67   private static final int FIXED_64_SIZE = 8;
     68   private static final int MAX_VARINT_SIZE = 10;
     69 
     70   /**
     71    * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
     72    */
     73   @Deprecated
     74   public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
     75 
     76   /**
     77    * The buffer size used in {@link #newInstance(OutputStream)}.
     78    */
     79   public static final int DEFAULT_BUFFER_SIZE = 4096;
     80 
     81   /**
     82    * Returns the buffer size to efficiently write dataLength bytes to this
     83    * CodedOutputStream. Used by AbstractMessageLite.
     84    *
     85    * @return the buffer size to efficiently write dataLength bytes to this
     86    *         CodedOutputStream.
     87    */
     88   static int computePreferredBufferSize(int dataLength) {
     89     if (dataLength > DEFAULT_BUFFER_SIZE) {
     90       return DEFAULT_BUFFER_SIZE;
     91     }
     92     return dataLength;
     93   }
     94 
     95   /**
     96    * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}.
     97    *
     98    * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
     99    * modify the provided byte arrays. Doing so may result in corrupted data, which would be
    100    * difficult to debug.
    101    */
    102   public static CodedOutputStream newInstance(final OutputStream output) {
    103     return newInstance(output, DEFAULT_BUFFER_SIZE);
    104   }
    105 
    106   /**
    107    * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given
    108    * buffer size.
    109    *
    110    * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
    111    * modify the provided byte arrays. Doing so may result in corrupted data, which would be
    112    * difficult to debug.
    113    */
    114   public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) {
    115     return new OutputStreamEncoder(output, bufferSize);
    116   }
    117 
    118   /**
    119    * Create a new {@code CodedOutputStream} that writes directly to the given
    120    * byte array.  If more bytes are written than fit in the array,
    121    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
    122    * array is faster than writing to an {@code OutputStream}.  See also
    123    * {@link ByteString#newCodedBuilder}.
    124    */
    125   public static CodedOutputStream newInstance(final byte[] flatArray) {
    126     return newInstance(flatArray, 0, flatArray.length);
    127   }
    128 
    129   /**
    130    * Create a new {@code CodedOutputStream} that writes directly to the given
    131    * byte array slice.  If more bytes are written than fit in the slice,
    132    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
    133    * array is faster than writing to an {@code OutputStream}.  See also
    134    * {@link ByteString#newCodedBuilder}.
    135    */
    136   public static CodedOutputStream newInstance(
    137       final byte[] flatArray, final int offset, final int length) {
    138     return new ArrayEncoder(flatArray, offset, length);
    139   }
    140 
    141   /**
    142    * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
    143    */
    144   public static CodedOutputStream newInstance(ByteBuffer byteBuffer) {
    145     if (byteBuffer.hasArray()) {
    146       return new NioHeapEncoder(byteBuffer);
    147     }
    148     return new NioEncoder(byteBuffer);
    149   }
    150 
    151   /**
    152    * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
    153    *
    154    * @deprecated the size parameter is no longer used since use of an internal buffer is useless
    155    * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)}
    156    * instead.
    157    */
    158   @Deprecated
    159   public static CodedOutputStream newInstance(ByteBuffer byteBuffer,
    160       @SuppressWarnings("unused") int unused) {
    161     return newInstance(byteBuffer);
    162   }
    163 
    164   /**
    165    * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}.
    166    *
    167    * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
    168    * so may result in corrupted data, which would be difficult to debug.
    169    *
    170    * @param byteOutput the output target for encoded bytes.
    171    * @param bufferSize the size of the internal scratch buffer to be used for string encoding.
    172    * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded
    173    * string.
    174    */
    175   static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) {
    176     if (bufferSize < 0) {
    177       throw new IllegalArgumentException("bufferSize must be positive");
    178     }
    179 
    180     return new ByteOutputEncoder(byteOutput, bufferSize);
    181   }
    182 
    183   // Disallow construction outside of this class.
    184   private CodedOutputStream() {
    185   }
    186 
    187   // -----------------------------------------------------------------
    188 
    189   /** Encode and write a tag. */
    190   // Abstract to avoid overhead of additional virtual method calls.
    191   public abstract void writeTag(int fieldNumber, int wireType) throws IOException;
    192 
    193   /** Write an {@code int32} field, including tag, to the stream. */
    194   // Abstract to avoid overhead of additional virtual method calls.
    195   public abstract void writeInt32(int fieldNumber, int value) throws IOException;
    196 
    197   /** Write a {@code uint32} field, including tag, to the stream. */
    198   // Abstract to avoid overhead of additional virtual method calls.
    199   public abstract void writeUInt32(int fieldNumber, int value) throws IOException;
    200 
    201   /** Write a {@code sint32} field, including tag, to the stream. */
    202   public final void writeSInt32(final int fieldNumber, final int value) throws IOException {
    203     writeUInt32(fieldNumber, encodeZigZag32(value));
    204   }
    205 
    206   /** Write a {@code fixed32} field, including tag, to the stream. */
    207   // Abstract to avoid overhead of additional virtual method calls.
    208   public abstract void writeFixed32(int fieldNumber, int value) throws IOException;
    209 
    210   /** Write an {@code sfixed32} field, including tag, to the stream. */
    211   public final void writeSFixed32(final int fieldNumber, final int value) throws IOException {
    212     writeFixed32(fieldNumber, value);
    213   }
    214 
    215   /** Write an {@code int64} field, including tag, to the stream. */
    216   public final void writeInt64(final int fieldNumber, final long value) throws IOException {
    217     writeUInt64(fieldNumber, value);
    218   }
    219 
    220   /** Write a {@code uint64} field, including tag, to the stream. */
    221   // Abstract to avoid overhead of additional virtual method calls.
    222   public abstract void writeUInt64(int fieldNumber, long value) throws IOException;
    223 
    224   /** Write an {@code sint64} field, including tag, to the stream. */
    225   public final void writeSInt64(final int fieldNumber, final long value) throws IOException {
    226     writeUInt64(fieldNumber, encodeZigZag64(value));
    227   }
    228 
    229   /** Write a {@code fixed64} field, including tag, to the stream. */
    230   // Abstract to avoid overhead of additional virtual method calls.
    231   public abstract void writeFixed64(int fieldNumber, long value) throws IOException;
    232 
    233   /** Write an {@code sfixed64} field, including tag, to the stream. */
    234   public final void writeSFixed64(final int fieldNumber, final long value) throws IOException {
    235     writeFixed64(fieldNumber, value);
    236   }
    237 
    238   /** Write a {@code float} field, including tag, to the stream. */
    239   public final void writeFloat(final int fieldNumber, final float value) throws IOException {
    240     writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
    241   }
    242 
    243   /** Write a {@code double} field, including tag, to the stream. */
    244   public final void writeDouble(final int fieldNumber, final double value) throws IOException {
    245     writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
    246   }
    247 
    248   /** Write a {@code bool} field, including tag, to the stream. */
    249   // Abstract to avoid overhead of additional virtual method calls.
    250   public abstract void writeBool(int fieldNumber, boolean value) throws IOException;
    251 
    252   /**
    253    * Write an enum field, including tag, to the stream. The provided value is the numeric
    254    * value used to represent the enum value on the wire (not the enum ordinal value).
    255    */
    256   public final void writeEnum(final int fieldNumber, final int value) throws IOException {
    257     writeInt32(fieldNumber, value);
    258   }
    259 
    260   /** Write a {@code string} field, including tag, to the stream. */
    261   // Abstract to avoid overhead of additional virtual method calls.
    262   public abstract void writeString(int fieldNumber, String value) throws IOException;
    263 
    264   /** Write a {@code bytes} field, including tag, to the stream. */
    265   // Abstract to avoid overhead of additional virtual method calls.
    266   public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException;
    267 
    268   /** Write a {@code bytes} field, including tag, to the stream. */
    269   // Abstract to avoid overhead of additional virtual method calls.
    270   public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException;
    271 
    272   /** Write a {@code bytes} field, including tag, to the stream. */
    273   // Abstract to avoid overhead of additional virtual method calls.
    274   public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
    275       throws IOException;
    276 
    277   /**
    278    * Write a {@code bytes} field, including tag, to the stream.
    279    * This method will write all content of the ByteBuffer regardless of the
    280    * current position and limit (i.e., the number of bytes to be written is
    281    * value.capacity(), not value.remaining()). Furthermore, this method doesn't
    282    * alter the state of the passed-in ByteBuffer. Its position, limit, mark,
    283    * etc. will remain unchanged. If you only want to write the remaining bytes
    284    * of a ByteBuffer, you can call
    285    * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}.
    286    */
    287   // Abstract to avoid overhead of additional virtual method calls.
    288   public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException;
    289 
    290   /**
    291    * Write a single byte.
    292    */
    293   public final void writeRawByte(final byte value) throws IOException {
    294     write(value);
    295   }
    296 
    297   /** Write a single byte, represented by an integer value. */
    298   public final void writeRawByte(final int value) throws IOException {
    299     write((byte) value);
    300   }
    301 
    302   /** Write an array of bytes. */
    303   public final void writeRawBytes(final byte[] value) throws IOException {
    304     write(value, 0, value.length);
    305   }
    306 
    307   /**
    308    * Write part of an array of bytes.
    309    */
    310   public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
    311     write(value, offset, length);
    312   }
    313 
    314   /** Write a byte string. */
    315   public final void writeRawBytes(final ByteString value) throws IOException {
    316     value.writeTo(this);
    317   }
    318 
    319   /**
    320    * Write a ByteBuffer. This method will write all content of the ByteBuffer
    321    * regardless of the current position and limit (i.e., the number of bytes
    322    * to be written is value.capacity(), not value.remaining()). Furthermore,
    323    * this method doesn't alter the state of the passed-in ByteBuffer. Its
    324    * position, limit, mark, etc. will remain unchanged. If you only want to
    325    * write the remaining bytes of a ByteBuffer, you can call
    326    * {@code writeRawBytes(byteBuffer.slice())}.
    327    */
    328   // Abstract to avoid overhead of additional virtual method calls.
    329   public abstract void writeRawBytes(final ByteBuffer value) throws IOException;
    330 
    331   /** Write an embedded message field, including tag, to the stream. */
    332   // Abstract to avoid overhead of additional virtual method calls.
    333   public abstract void writeMessage(final int fieldNumber, final MessageLite value)
    334       throws IOException;
    335 
    336   /**
    337    * Write a MessageSet extension field to the stream.  For historical reasons,
    338    * the wire format differs from normal fields.
    339    */
    340   // Abstract to avoid overhead of additional virtual method calls.
    341   public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
    342       throws IOException;
    343 
    344   /**
    345    * Write an unparsed MessageSet extension field to the stream.  For
    346    * historical reasons, the wire format differs from normal fields.
    347    */
    348   // Abstract to avoid overhead of additional virtual method calls.
    349   public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
    350       throws IOException;
    351 
    352   // -----------------------------------------------------------------
    353 
    354   /** Write an {@code int32} field to the stream. */
    355   // Abstract to avoid overhead of additional virtual method calls.
    356   public abstract void writeInt32NoTag(final int value) throws IOException;
    357 
    358   /** Write a {@code uint32} field to the stream. */
    359   // Abstract to avoid overhead of additional virtual method calls.
    360   public abstract void writeUInt32NoTag(int value) throws IOException;
    361 
    362   /** Write a {@code sint32} field to the stream. */
    363   public final void writeSInt32NoTag(final int value) throws IOException {
    364     writeUInt32NoTag(encodeZigZag32(value));
    365   }
    366 
    367   /** Write a {@code fixed32} field to the stream. */
    368   // Abstract to avoid overhead of additional virtual method calls.
    369   public abstract void writeFixed32NoTag(int value) throws IOException;
    370 
    371   /** Write a {@code sfixed32} field to the stream. */
    372   public final void writeSFixed32NoTag(final int value) throws IOException {
    373     writeFixed32NoTag(value);
    374   }
    375 
    376   /** Write an {@code int64} field to the stream. */
    377   public final void writeInt64NoTag(final long value) throws IOException {
    378     writeUInt64NoTag(value);
    379   }
    380 
    381   /** Write a {@code uint64} field to the stream. */
    382   // Abstract to avoid overhead of additional virtual method calls.
    383   public abstract void writeUInt64NoTag(long value) throws IOException;
    384 
    385   /** Write a {@code sint64} field to the stream. */
    386   public final void writeSInt64NoTag(final long value) throws IOException {
    387     writeUInt64NoTag(encodeZigZag64(value));
    388   }
    389 
    390   /** Write a {@code fixed64} field to the stream. */
    391   // Abstract to avoid overhead of additional virtual method calls.
    392   public abstract void writeFixed64NoTag(long value) throws IOException;
    393 
    394   /** Write a {@code sfixed64} field to the stream. */
    395   public final void writeSFixed64NoTag(final long value) throws IOException {
    396     writeFixed64NoTag(value);
    397   }
    398 
    399   /** Write a {@code float} field to the stream. */
    400   public final void writeFloatNoTag(final float value) throws IOException {
    401     writeFixed32NoTag(Float.floatToRawIntBits(value));
    402   }
    403 
    404   /** Write a {@code double} field to the stream. */
    405   public final void writeDoubleNoTag(final double value) throws IOException {
    406     writeFixed64NoTag(Double.doubleToRawLongBits(value));
    407   }
    408 
    409   /** Write a {@code bool} field to the stream. */
    410   public final void writeBoolNoTag(final boolean value) throws IOException {
    411     write((byte) (value ? 1 : 0));
    412   }
    413 
    414   /**
    415    * Write an enum field to the stream. The provided value is the numeric
    416    * value used to represent the enum value on the wire (not the enum ordinal value).
    417    */
    418   public final void writeEnumNoTag(final int value) throws IOException {
    419     writeInt32NoTag(value);
    420   }
    421 
    422   /** Write a {@code string} field to the stream. */
    423   // TODO(dweis): Document behavior on ill-formed UTF-16 input.
    424   // Abstract to avoid overhead of additional virtual method calls.
    425   public abstract void writeStringNoTag(String value) throws IOException;
    426 
    427   /** Write a {@code bytes} field to the stream. */
    428   // Abstract to avoid overhead of additional virtual method calls.
    429   public abstract void writeBytesNoTag(final ByteString value) throws IOException;
    430 
    431   /** Write a {@code bytes} field to the stream. */
    432   public final void writeByteArrayNoTag(final byte[] value) throws IOException {
    433     writeByteArrayNoTag(value, 0, value.length);
    434   }
    435 
    436   /** Write an embedded message field to the stream. */
    437   // Abstract to avoid overhead of additional virtual method calls.
    438   public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
    439 
    440   //=================================================================
    441 
    442   @ExperimentalApi
    443   @Override
    444   public abstract void write(byte value) throws IOException;
    445 
    446   @ExperimentalApi
    447   @Override
    448   public abstract void write(byte[] value, int offset, int length) throws IOException;
    449 
    450   @ExperimentalApi
    451   @Override
    452   public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
    453 
    454   @Override
    455   public abstract void write(ByteBuffer value) throws IOException;
    456 
    457   @ExperimentalApi
    458   @Override
    459   public abstract void writeLazy(ByteBuffer value) throws IOException;
    460 
    461   // =================================================================
    462   // =================================================================
    463 
    464   /**
    465    * Compute the number of bytes that would be needed to encode an
    466    * {@code int32} field, including tag.
    467    */
    468   public static int computeInt32Size(final int fieldNumber, final int value) {
    469     return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
    470   }
    471 
    472   /**
    473    * Compute the number of bytes that would be needed to encode a
    474    * {@code uint32} field, including tag.
    475    */
    476   public static int computeUInt32Size(final int fieldNumber, final int value) {
    477     return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
    478   }
    479 
    480   /**
    481    * Compute the number of bytes that would be needed to encode an
    482    * {@code sint32} field, including tag.
    483    */
    484   public static int computeSInt32Size(final int fieldNumber, final int value) {
    485     return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
    486   }
    487 
    488   /**
    489    * Compute the number of bytes that would be needed to encode a
    490    * {@code fixed32} field, including tag.
    491    */
    492   public static int computeFixed32Size(final int fieldNumber, final int value) {
    493     return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
    494   }
    495 
    496   /**
    497    * Compute the number of bytes that would be needed to encode an
    498    * {@code sfixed32} field, including tag.
    499    */
    500   public static int computeSFixed32Size(final int fieldNumber, final int value) {
    501     return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
    502   }
    503 
    504   /**
    505    * Compute the number of bytes that would be needed to encode an
    506    * {@code int64} field, including tag.
    507    */
    508   public static int computeInt64Size(final int fieldNumber, final long value) {
    509     return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
    510   }
    511 
    512   /**
    513    * Compute the number of bytes that would be needed to encode a
    514    * {@code uint64} field, including tag.
    515    */
    516   public static int computeUInt64Size(final int fieldNumber, final long value) {
    517     return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
    518   }
    519 
    520   /**
    521    * Compute the number of bytes that would be needed to encode an
    522    * {@code sint64} field, including tag.
    523    */
    524   public static int computeSInt64Size(final int fieldNumber, final long value) {
    525     return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
    526   }
    527 
    528   /**
    529    * Compute the number of bytes that would be needed to encode a
    530    * {@code fixed64} field, including tag.
    531    */
    532   public static int computeFixed64Size(final int fieldNumber, final long value) {
    533     return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
    534   }
    535 
    536   /**
    537    * Compute the number of bytes that would be needed to encode an
    538    * {@code sfixed64} field, including tag.
    539    */
    540   public static int computeSFixed64Size(final int fieldNumber, final long value) {
    541     return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
    542   }
    543 
    544   /**
    545    * Compute the number of bytes that would be needed to encode a
    546    * {@code float} field, including tag.
    547    */
    548   public static int computeFloatSize(final int fieldNumber, final float value) {
    549     return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
    550   }
    551 
    552   /**
    553    * Compute the number of bytes that would be needed to encode a
    554    * {@code double} field, including tag.
    555    */
    556   public static int computeDoubleSize(final int fieldNumber, final double value) {
    557     return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
    558   }
    559 
    560   /**
    561    * Compute the number of bytes that would be needed to encode a
    562    * {@code bool} field, including tag.
    563    */
    564   public static int computeBoolSize(final int fieldNumber, final boolean value) {
    565     return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
    566   }
    567 
    568   /**
    569    * Compute the number of bytes that would be needed to encode an
    570    * enum field, including tag. The provided value is the numeric
    571    * value used to represent the enum value on the wire (not the enum ordinal value).
    572    */
    573   public static int computeEnumSize(final int fieldNumber, final int value) {
    574     return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
    575   }
    576 
    577   /**
    578    * Compute the number of bytes that would be needed to encode a
    579    * {@code string} field, including tag.
    580    */
    581   public static int computeStringSize(final int fieldNumber, final String value) {
    582     return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
    583   }
    584 
    585   /**
    586    * Compute the number of bytes that would be needed to encode a
    587    * {@code bytes} field, including tag.
    588    */
    589   public static int computeBytesSize(final int fieldNumber, final ByteString value) {
    590     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
    591   }
    592 
    593   /**
    594    * Compute the number of bytes that would be needed to encode a
    595    * {@code bytes} field, including tag.
    596    */
    597   public static int computeByteArraySize(final int fieldNumber, final byte[] value) {
    598     return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
    599   }
    600 
    601   /**
    602    * Compute the number of bytes that would be needed to encode a
    603    * {@code bytes} field, including tag.
    604    */
    605   public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) {
    606     return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value);
    607   }
    608 
    609   /**
    610    * Compute the number of bytes that would be needed to encode an
    611    * embedded message in lazy field, including tag.
    612    */
    613   public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) {
    614     return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
    615   }
    616 
    617   /**
    618    * Compute the number of bytes that would be needed to encode an
    619    * embedded message field, including tag.
    620    */
    621   public static int computeMessageSize(final int fieldNumber, final MessageLite value) {
    622     return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
    623   }
    624 
    625   /**
    626    * Compute the number of bytes that would be needed to encode a
    627    * MessageSet extension to the stream.  For historical reasons,
    628    * the wire format differs from normal fields.
    629    */
    630   public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) {
    631     return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
    632         + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
    633         + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
    634   }
    635 
    636   /**
    637    * Compute the number of bytes that would be needed to encode an
    638    * unparsed MessageSet extension field to the stream.  For
    639    * historical reasons, the wire format differs from normal fields.
    640    */
    641   public static int computeRawMessageSetExtensionSize(
    642       final int fieldNumber, final ByteString value) {
    643     return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
    644         + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
    645         + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
    646   }
    647 
    648   /**
    649    * Compute the number of bytes that would be needed to encode an
    650    * lazily parsed MessageSet extension field to the stream.  For
    651    * historical reasons, the wire format differs from normal fields.
    652    */
    653   public static int computeLazyFieldMessageSetExtensionSize(
    654       final int fieldNumber, final LazyFieldLite value) {
    655     return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
    656         + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
    657         + computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
    658   }
    659 
    660   // -----------------------------------------------------------------
    661 
    662   /** Compute the number of bytes that would be needed to encode a tag. */
    663   public static int computeTagSize(final int fieldNumber) {
    664     return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0));
    665   }
    666 
    667   /**
    668    * Compute the number of bytes that would be needed to encode an
    669    * {@code int32} field, including tag.
    670    */
    671   public static int computeInt32SizeNoTag(final int value) {
    672     if (value >= 0) {
    673       return computeUInt32SizeNoTag(value);
    674     } else {
    675       // Must sign-extend.
    676       return MAX_VARINT_SIZE;
    677     }
    678   }
    679 
    680   /**
    681    * Compute the number of bytes that would be needed to encode a
    682    * {@code uint32} field.
    683    */
    684   public static int computeUInt32SizeNoTag(final int value) {
    685     if ((value & (~0 <<  7)) == 0) {
    686       return 1;
    687     }
    688     if ((value & (~0 << 14)) == 0) {
    689       return 2;
    690     }
    691     if ((value & (~0 << 21)) == 0) {
    692       return 3;
    693     }
    694     if ((value & (~0 << 28)) == 0) {
    695       return 4;
    696     }
    697     return 5;
    698   }
    699 
    700   /**
    701    * Compute the number of bytes that would be needed to encode an
    702    * {@code sint32} field.
    703    */
    704   public static int computeSInt32SizeNoTag(final int value) {
    705     return computeUInt32SizeNoTag(encodeZigZag32(value));
    706   }
    707 
    708   /**
    709    * Compute the number of bytes that would be needed to encode a
    710    * {@code fixed32} field.
    711    */
    712   public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
    713     return FIXED_32_SIZE;
    714   }
    715 
    716   /**
    717    * Compute the number of bytes that would be needed to encode an
    718    * {@code sfixed32} field.
    719    */
    720   public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
    721     return FIXED_32_SIZE;
    722   }
    723 
    724   /**
    725    * Compute the number of bytes that would be needed to encode an
    726    * {@code int64} field, including tag.
    727    */
    728   public static int computeInt64SizeNoTag(final long value) {
    729     return computeUInt64SizeNoTag(value);
    730   }
    731 
    732   /**
    733    * Compute the number of bytes that would be needed to encode a
    734    * {@code uint64} field, including tag.
    735    */
    736   public static int computeUInt64SizeNoTag(long value) {
    737     // handle two popular special cases up front ...
    738     if ((value & (~0L << 7)) == 0L) {
    739       return 1;
    740     }
    741     if (value < 0L) {
    742       return 10;
    743     }
    744     // ... leaving us with 8 remaining, which we can divide and conquer
    745     int n = 2;
    746     if ((value & (~0L << 35)) != 0L) {
    747       n += 4; value >>>= 28;
    748     }
    749     if ((value & (~0L << 21)) != 0L) {
    750       n += 2; value >>>= 14;
    751     }
    752     if ((value & (~0L << 14)) != 0L) {
    753       n += 1;
    754     }
    755     return n;
    756   }
    757 
    758   /**
    759    * Compute the number of bytes that would be needed to encode an
    760    * {@code sint64} field.
    761    */
    762   public static int computeSInt64SizeNoTag(final long value) {
    763     return computeUInt64SizeNoTag(encodeZigZag64(value));
    764   }
    765 
    766   /**
    767    * Compute the number of bytes that would be needed to encode a
    768    * {@code fixed64} field.
    769    */
    770   public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
    771     return FIXED_64_SIZE;
    772   }
    773 
    774   /**
    775    * Compute the number of bytes that would be needed to encode an
    776    * {@code sfixed64} field.
    777    */
    778   public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
    779     return FIXED_64_SIZE;
    780   }
    781 
    782   /**
    783    * Compute the number of bytes that would be needed to encode a
    784    * {@code float} field, including tag.
    785    */
    786   public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
    787     return FIXED_32_SIZE;
    788   }
    789 
    790   /**
    791    * Compute the number of bytes that would be needed to encode a
    792    * {@code double} field, including tag.
    793    */
    794   public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
    795     return FIXED_64_SIZE;
    796   }
    797 
    798   /**
    799    * Compute the number of bytes that would be needed to encode a
    800    * {@code bool} field.
    801    */
    802   public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) {
    803     return 1;
    804   }
    805 
    806   /**
    807    * Compute the number of bytes that would be needed to encode an enum field.
    808    * The provided value is the numeric value used to represent the enum value on the wire
    809    * (not the enum ordinal value).
    810    */
    811   public static int computeEnumSizeNoTag(final int value) {
    812     return computeInt32SizeNoTag(value);
    813   }
    814 
    815   /**
    816    * Compute the number of bytes that would be needed to encode a
    817    * {@code string} field.
    818    */
    819   public static int computeStringSizeNoTag(final String value) {
    820     int length;
    821     try {
    822       length = Utf8.encodedLength(value);
    823     } catch (UnpairedSurrogateException e) {
    824       // TODO(dweis): Consider using nio Charset methods instead.
    825       final byte[] bytes = value.getBytes(Internal.UTF_8);
    826       length = bytes.length;
    827     }
    828 
    829     return computeLengthDelimitedFieldSize(length);
    830   }
    831 
    832   /**
    833    * Compute the number of bytes that would be needed to encode an embedded
    834    * message stored in lazy field.
    835    */
    836   public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
    837     return computeLengthDelimitedFieldSize(value.getSerializedSize());
    838   }
    839 
    840   /**
    841    * Compute the number of bytes that would be needed to encode a
    842    * {@code bytes} field.
    843    */
    844   public static int computeBytesSizeNoTag(final ByteString value) {
    845     return computeLengthDelimitedFieldSize(value.size());
    846   }
    847 
    848   /**
    849    * Compute the number of bytes that would be needed to encode a
    850    * {@code bytes} field.
    851    */
    852   public static int computeByteArraySizeNoTag(final byte[] value) {
    853     return computeLengthDelimitedFieldSize(value.length);
    854   }
    855 
    856   /**
    857    * Compute the number of bytes that would be needed to encode a
    858    * {@code bytes} field.
    859    */
    860   public static int computeByteBufferSizeNoTag(final ByteBuffer value) {
    861     return computeLengthDelimitedFieldSize(value.capacity());
    862   }
    863 
    864   /**
    865    * Compute the number of bytes that would be needed to encode an embedded
    866    * message field.
    867    */
    868   public static int computeMessageSizeNoTag(final MessageLite value) {
    869     return computeLengthDelimitedFieldSize(value.getSerializedSize());
    870   }
    871 
    872   private static int computeLengthDelimitedFieldSize(int fieldLength) {
    873     return computeUInt32SizeNoTag(fieldLength) + fieldLength;
    874   }
    875 
    876   /**
    877    * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
    878    * into values that can be efficiently encoded with varint.  (Otherwise,
    879    * negative values must be sign-extended to 64 bits to be varint encoded,
    880    * thus always taking 10 bytes on the wire.)
    881    *
    882    * @param n A signed 32-bit integer.
    883    * @return An unsigned 32-bit integer, stored in a signed int because
    884    *         Java has no explicit unsigned support.
    885    */
    886   public static int encodeZigZag32(final int n) {
    887     // Note:  the right-shift must be arithmetic
    888     return (n << 1) ^ (n >> 31);
    889   }
    890 
    891   /**
    892    * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
    893    * into values that can be efficiently encoded with varint.  (Otherwise,
    894    * negative values must be sign-extended to 64 bits to be varint encoded,
    895    * thus always taking 10 bytes on the wire.)
    896    *
    897    * @param n A signed 64-bit integer.
    898    * @return An unsigned 64-bit integer, stored in a signed int because
    899    *         Java has no explicit unsigned support.
    900    */
    901   public static long encodeZigZag64(final long n) {
    902     // Note:  the right-shift must be arithmetic
    903     return (n << 1) ^ (n >> 63);
    904   }
    905 
    906   // =================================================================
    907 
    908   /**
    909    * Flushes the stream and forces any buffered bytes to be written.  This
    910    * does not flush the underlying OutputStream.
    911    */
    912   public abstract void flush() throws IOException;
    913 
    914   /**
    915    * If writing to a flat array, return the space left in the array.
    916    * Otherwise, throws {@code UnsupportedOperationException}.
    917    */
    918   public abstract int spaceLeft();
    919 
    920   /**
    921    * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
    922    * a byte array that is exactly big enough to hold a message, then write to
    923    * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
    924    * after writing verifies that the message was actually as big as expected,
    925    * which can help catch bugs.
    926    */
    927   public final void checkNoSpaceLeft() {
    928     if (spaceLeft() != 0) {
    929       throw new IllegalStateException("Did not write as much data as expected.");
    930     }
    931   }
    932 
    933   /**
    934    * If you create a CodedOutputStream around a simple flat array, you must
    935    * not attempt to write more bytes than the array has space.  Otherwise,
    936    * this exception will be thrown.
    937    */
    938   public static class OutOfSpaceException extends IOException {
    939     private static final long serialVersionUID = -6947486886997889499L;
    940 
    941     private static final String MESSAGE =
    942         "CodedOutputStream was writing to a flat byte array and ran out of space.";
    943 
    944     OutOfSpaceException() {
    945       super(MESSAGE);
    946     }
    947 
    948     OutOfSpaceException(Throwable cause) {
    949       super(MESSAGE, cause);
    950     }
    951   }
    952 
    953   /**
    954    * Get the total number of bytes successfully written to this stream.  The
    955    * returned value is not guaranteed to be accurate if exceptions have been
    956    * found in the middle of writing.
    957    */
    958   public abstract int getTotalBytesWritten();
    959 
    960   // =================================================================
    961 
    962   /** Write a {@code bytes} field to the stream. Visible for testing. */
    963   abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
    964       throws IOException;
    965 
    966   final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause)
    967       throws IOException {
    968     logger.log(Level.WARNING,
    969         "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause);
    970 
    971     // Unfortunately there does not appear to be any way to tell Java to encode
    972     // UTF-8 directly into our buffer, so we have to let it create its own byte
    973     // array and then copy.
    974     // TODO(dweis): Consider using nio Charset methods instead.
    975     final byte[] bytes = value.getBytes(Internal.UTF_8);
    976     try {
    977       writeUInt32NoTag(bytes.length);
    978       writeLazy(bytes, 0, bytes.length);
    979     } catch (IndexOutOfBoundsException e) {
    980       throw new OutOfSpaceException(e);
    981     } catch (OutOfSpaceException e) {
    982       throw e;
    983     }
    984   }
    985 
    986   // =================================================================
    987 
    988   /**
    989    * Write a {@code group} field, including tag, to the stream.
    990    *
    991    * @deprecated groups are deprecated.
    992    */
    993   @Deprecated
    994   public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
    995     writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
    996     writeGroupNoTag(value);
    997     writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
    998   }
    999 
   1000   /**
   1001    * Write a {@code group} field to the stream.
   1002    *
   1003    * @deprecated groups are deprecated.
   1004    */
   1005   @Deprecated
   1006   public final void writeGroupNoTag(final MessageLite value) throws IOException {
   1007     value.writeTo(this);
   1008   }
   1009 
   1010   /**
   1011    * Compute the number of bytes that would be needed to encode a
   1012    * {@code group} field, including tag.
   1013    *
   1014    * @deprecated groups are deprecated.
   1015    */
   1016   @Deprecated
   1017   public static int computeGroupSize(final int fieldNumber, final MessageLite value) {
   1018     return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
   1019   }
   1020 
   1021   /**
   1022    * Compute the number of bytes that would be needed to encode a
   1023    * {@code group} field.
   1024    */
   1025   @Deprecated
   1026   public static int computeGroupSizeNoTag(final MessageLite value) {
   1027     return value.getSerializedSize();
   1028   }
   1029 
   1030   /**
   1031    * Encode and write a varint.  {@code value} is treated as
   1032    * unsigned, so it won't be sign-extended if negative.
   1033    *
   1034    * @deprecated use {@link #writeUInt32NoTag} instead.
   1035    */
   1036   @Deprecated
   1037   public final void writeRawVarint32(int value) throws IOException {
   1038     writeUInt32NoTag(value);
   1039   }
   1040 
   1041   /**
   1042    * Encode and write a varint.
   1043    *
   1044    * @deprecated use {@link #writeUInt64NoTag} instead.
   1045    */
   1046   @Deprecated
   1047   public final void writeRawVarint64(long value) throws IOException {
   1048     writeUInt64NoTag(value);
   1049   }
   1050 
   1051   /**
   1052    * Compute the number of bytes that would be needed to encode a varint.
   1053    * {@code value} is treated as unsigned, so it won't be sign-extended if
   1054    * negative.
   1055    *
   1056    * @deprecated use {@link #computeUInt32SizeNoTag(int)} instead.
   1057    */
   1058   @Deprecated
   1059   public static int computeRawVarint32Size(final int value) {
   1060     return computeUInt32SizeNoTag(value);
   1061   }
   1062 
   1063   /**
   1064    * Compute the number of bytes that would be needed to encode a varint.
   1065    *
   1066    * @deprecated use {@link #computeUInt64SizeNoTag(long)} instead.
   1067    */
   1068   @Deprecated
   1069   public static int computeRawVarint64Size(long value) {
   1070     return computeUInt64SizeNoTag(value);
   1071   }
   1072 
   1073   /**
   1074    * Write a little-endian 32-bit integer.
   1075    *
   1076    * @deprecated Use {@link #writeFixed32NoTag} instead.
   1077    */
   1078   @Deprecated
   1079   public final void writeRawLittleEndian32(final int value) throws IOException {
   1080     writeFixed32NoTag(value);
   1081   }
   1082 
   1083   /**
   1084    * Write a little-endian 64-bit integer.
   1085    *
   1086    * @deprecated Use {@link #writeFixed64NoTag} instead.
   1087    */
   1088   @Deprecated
   1089   public final void writeRawLittleEndian64(final long value) throws IOException {
   1090     writeFixed64NoTag(value);
   1091   }
   1092 
   1093   // =================================================================
   1094 
   1095   /**
   1096    * A {@link CodedOutputStream} that writes directly to a byte array.
   1097    */
   1098   private static class ArrayEncoder extends CodedOutputStream {
   1099     private final byte[] buffer;
   1100     private final int offset;
   1101     private final int limit;
   1102     private int position;
   1103 
   1104     ArrayEncoder(byte[] buffer, int offset, int length) {
   1105       if (buffer == null) {
   1106         throw new NullPointerException("buffer");
   1107       }
   1108       if ((offset | length | (buffer.length - (offset + length))) < 0) {
   1109         throw new IllegalArgumentException(String.format(
   1110             "Array range is invalid. Buffer.length=%d, offset=%d, length=%d",
   1111             buffer.length, offset, length));
   1112       }
   1113       this.buffer = buffer;
   1114       this.offset = offset;
   1115       position = offset;
   1116       limit = offset + length;
   1117     }
   1118 
   1119     @Override
   1120     public final void writeTag(final int fieldNumber, final int wireType) throws IOException {
   1121       writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
   1122     }
   1123 
   1124     @Override
   1125     public final void writeInt32(final int fieldNumber, final int value) throws IOException {
   1126       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1127       writeInt32NoTag(value);
   1128     }
   1129 
   1130     @Override
   1131     public final void writeUInt32(final int fieldNumber, final int value) throws IOException {
   1132       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1133       writeUInt32NoTag(value);
   1134     }
   1135 
   1136     @Override
   1137     public final void writeFixed32(final int fieldNumber, final int value) throws IOException {
   1138       writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
   1139       writeFixed32NoTag(value);
   1140     }
   1141 
   1142     @Override
   1143     public final void writeUInt64(final int fieldNumber, final long value) throws IOException {
   1144       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1145       writeUInt64NoTag(value);
   1146     }
   1147 
   1148     @Override
   1149     public final void writeFixed64(final int fieldNumber, final long value) throws IOException {
   1150       writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
   1151       writeFixed64NoTag(value);
   1152     }
   1153 
   1154     @Override
   1155     public final void writeBool(final int fieldNumber, final boolean value) throws IOException {
   1156       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1157       write((byte) (value ? 1 : 0));
   1158     }
   1159 
   1160     @Override
   1161     public final void writeString(final int fieldNumber, final String value) throws IOException {
   1162       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1163       writeStringNoTag(value);
   1164     }
   1165 
   1166     @Override
   1167     public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
   1168       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1169       writeBytesNoTag(value);
   1170     }
   1171 
   1172     @Override
   1173     public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
   1174       writeByteArray(fieldNumber, value, 0, value.length);
   1175     }
   1176 
   1177     @Override
   1178     public final void writeByteArray(
   1179         final int fieldNumber, final byte[] value, final int offset, final int length)
   1180         throws IOException {
   1181       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1182       writeByteArrayNoTag(value, offset, length);
   1183     }
   1184 
   1185     @Override
   1186     public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
   1187         throws IOException {
   1188       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1189       writeUInt32NoTag(value.capacity());
   1190       writeRawBytes(value);
   1191     }
   1192 
   1193     @Override
   1194     public final void writeBytesNoTag(final ByteString value) throws IOException {
   1195       writeUInt32NoTag(value.size());
   1196       value.writeTo(this);
   1197     }
   1198 
   1199     @Override
   1200     public final void writeByteArrayNoTag(final byte[] value, int offset, int length)
   1201         throws IOException {
   1202       writeUInt32NoTag(length);
   1203       write(value, offset, length);
   1204     }
   1205 
   1206     @Override
   1207     public final void writeRawBytes(final ByteBuffer value) throws IOException {
   1208       if (value.hasArray()) {
   1209         write(value.array(), value.arrayOffset(), value.capacity());
   1210       } else {
   1211         ByteBuffer duplicated = value.duplicate();
   1212         duplicated.clear();
   1213         write(duplicated);
   1214       }
   1215     }
   1216 
   1217     @Override
   1218     public final void writeMessage(final int fieldNumber, final MessageLite value)
   1219         throws IOException {
   1220       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1221       writeMessageNoTag(value);
   1222     }
   1223 
   1224     @Override
   1225     public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
   1226         throws IOException {
   1227       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   1228       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   1229       writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
   1230       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   1231     }
   1232 
   1233     @Override
   1234     public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
   1235         throws IOException {
   1236       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   1237       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   1238       writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
   1239       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   1240     }
   1241 
   1242     @Override
   1243     public final void writeMessageNoTag(final MessageLite value) throws IOException {
   1244       writeUInt32NoTag(value.getSerializedSize());
   1245       value.writeTo(this);
   1246     }
   1247 
   1248     @Override
   1249     public final void write(byte value) throws IOException {
   1250       try {
   1251         buffer[position++] = value;
   1252       } catch (IndexOutOfBoundsException e) {
   1253         throw new OutOfSpaceException(new IndexOutOfBoundsException(
   1254             String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
   1255       }
   1256     }
   1257 
   1258     @Override
   1259     public final void writeInt32NoTag(int value) throws IOException {
   1260       if (value >= 0) {
   1261         writeUInt32NoTag(value);
   1262       } else {
   1263         // Must sign-extend.
   1264         writeUInt64NoTag(value);
   1265       }
   1266     }
   1267 
   1268     @Override
   1269     public final void writeUInt32NoTag(int value) throws IOException {
   1270       if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
   1271         long pos = ARRAY_BASE_OFFSET + position;
   1272         while (true) {
   1273           if ((value & ~0x7F) == 0) {
   1274             UNSAFE.putByte(buffer, pos++, (byte) value);
   1275             position++;
   1276             return;
   1277           } else {
   1278             UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
   1279             position++;
   1280             value >>>= 7;
   1281           }
   1282         }
   1283       } else {
   1284         try {
   1285           while (true) {
   1286             if ((value & ~0x7F) == 0) {
   1287               buffer[position++] = (byte) value;
   1288               return;
   1289             } else {
   1290               buffer[position++] = (byte) ((value & 0x7F) | 0x80);
   1291               value >>>= 7;
   1292             }
   1293           }
   1294         } catch (IndexOutOfBoundsException e) {
   1295           throw new OutOfSpaceException(
   1296               new IndexOutOfBoundsException(
   1297                   String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
   1298         }
   1299       }
   1300     }
   1301 
   1302     @Override
   1303     public final void writeFixed32NoTag(int value) throws IOException {
   1304       try {
   1305         buffer[position++] = (byte) (value & 0xFF);
   1306         buffer[position++] = (byte) ((value >> 8) & 0xFF);
   1307         buffer[position++] = (byte) ((value >> 16) & 0xFF);
   1308         buffer[position++] = (byte) ((value >> 24) & 0xFF);
   1309       } catch (IndexOutOfBoundsException e) {
   1310         throw new OutOfSpaceException(
   1311             new IndexOutOfBoundsException(
   1312                 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
   1313       }
   1314     }
   1315 
   1316     @Override
   1317     public final void writeUInt64NoTag(long value) throws IOException {
   1318       if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
   1319         long pos = ARRAY_BASE_OFFSET + position;
   1320         while (true) {
   1321           if ((value & ~0x7FL) == 0) {
   1322             UNSAFE.putByte(buffer, pos++, (byte) value);
   1323             position++;
   1324             return;
   1325           } else {
   1326             UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
   1327             position++;
   1328             value >>>= 7;
   1329           }
   1330         }
   1331       } else {
   1332         try {
   1333           while (true) {
   1334             if ((value & ~0x7FL) == 0) {
   1335               buffer[position++] = (byte) value;
   1336               return;
   1337             } else {
   1338               buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
   1339               value >>>= 7;
   1340             }
   1341           }
   1342         } catch (IndexOutOfBoundsException e) {
   1343           throw new OutOfSpaceException(
   1344               new IndexOutOfBoundsException(
   1345                   String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
   1346         }
   1347       }
   1348     }
   1349 
   1350     @Override
   1351     public final void writeFixed64NoTag(long value) throws IOException {
   1352       try {
   1353         buffer[position++] = (byte) ((int) (value) & 0xFF);
   1354         buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
   1355         buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
   1356         buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
   1357         buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
   1358         buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
   1359         buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
   1360         buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
   1361       } catch (IndexOutOfBoundsException e) {
   1362         throw new OutOfSpaceException(
   1363             new IndexOutOfBoundsException(
   1364                 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
   1365       }
   1366     }
   1367 
   1368     @Override
   1369     public final void write(byte[] value, int offset, int length) throws IOException {
   1370       try {
   1371         System.arraycopy(value, offset, buffer, position, length);
   1372         position += length;
   1373       } catch (IndexOutOfBoundsException e) {
   1374         throw new OutOfSpaceException(
   1375             new IndexOutOfBoundsException(
   1376                 String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
   1377       }
   1378     }
   1379 
   1380     @Override
   1381     public final void writeLazy(byte[] value, int offset, int length) throws IOException {
   1382       write(value, offset, length);
   1383     }
   1384 
   1385     @Override
   1386     public final void write(ByteBuffer value) throws IOException {
   1387       final int length = value.remaining();
   1388       try {
   1389         value.get(buffer, position, length);
   1390         position += length;
   1391       } catch (IndexOutOfBoundsException e) {
   1392         throw new OutOfSpaceException(
   1393             new IndexOutOfBoundsException(
   1394                 String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
   1395       }
   1396     }
   1397 
   1398     @Override
   1399     public final void writeLazy(ByteBuffer value) throws IOException {
   1400       write(value);
   1401     }
   1402 
   1403     @Override
   1404     public final void writeStringNoTag(String value) throws IOException {
   1405       final int oldPosition = position;
   1406       try {
   1407         // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
   1408         // and at most 3 times of it. We take advantage of this in both branches below.
   1409         final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
   1410         final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
   1411         final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
   1412         if (minLengthVarIntSize == maxLengthVarIntSize) {
   1413           position = oldPosition + minLengthVarIntSize;
   1414           int newPosition = Utf8.encode(value, buffer, position, spaceLeft());
   1415           // Since this class is stateful and tracks the position, we rewind and store the state,
   1416           // prepend the length, then reset it back to the end of the string.
   1417           position = oldPosition;
   1418           int length = newPosition - oldPosition - minLengthVarIntSize;
   1419           writeUInt32NoTag(length);
   1420           position = newPosition;
   1421         } else {
   1422           int length = Utf8.encodedLength(value);
   1423           writeUInt32NoTag(length);
   1424           position = Utf8.encode(value, buffer, position, spaceLeft());
   1425         }
   1426       } catch (UnpairedSurrogateException e) {
   1427         // Roll back the change - we fall back to inefficient path.
   1428         position = oldPosition;
   1429 
   1430         // TODO(nathanmittler): We should throw an IOException here instead.
   1431         inefficientWriteStringNoTag(value, e);
   1432       } catch (IndexOutOfBoundsException e) {
   1433         throw new OutOfSpaceException(e);
   1434       }
   1435     }
   1436 
   1437     @Override
   1438     public void flush() {
   1439       // Do nothing.
   1440     }
   1441 
   1442     @Override
   1443     public final int spaceLeft() {
   1444       return limit - position;
   1445     }
   1446 
   1447     @Override
   1448     public final int getTotalBytesWritten() {
   1449       return position - offset;
   1450     }
   1451   }
   1452 
   1453   /**
   1454    * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are
   1455    * done directly to the underlying array. The buffer position is only updated after a flush.
   1456    */
   1457   private static final class NioHeapEncoder extends ArrayEncoder {
   1458     private final ByteBuffer byteBuffer;
   1459     private int initialPosition;
   1460 
   1461     NioHeapEncoder(ByteBuffer byteBuffer) {
   1462       super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(),
   1463           byteBuffer.remaining());
   1464       this.byteBuffer = byteBuffer;
   1465       this.initialPosition = byteBuffer.position();
   1466     }
   1467 
   1468     @Override
   1469     public void flush() {
   1470       // Update the position on the buffer.
   1471       byteBuffer.position(initialPosition + getTotalBytesWritten());
   1472     }
   1473   }
   1474 
   1475   /**
   1476    * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}.
   1477    */
   1478   private static final class NioEncoder extends CodedOutputStream {
   1479     private final ByteBuffer originalBuffer;
   1480     private final ByteBuffer buffer;
   1481     private final int initialPosition;
   1482 
   1483     NioEncoder(ByteBuffer buffer) {
   1484       this.originalBuffer = buffer;
   1485       this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
   1486       initialPosition = buffer.position();
   1487     }
   1488 
   1489     @Override
   1490     public void writeTag(final int fieldNumber, final int wireType) throws IOException {
   1491       writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
   1492     }
   1493 
   1494     @Override
   1495     public void writeInt32(final int fieldNumber, final int value) throws IOException {
   1496       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1497       writeInt32NoTag(value);
   1498     }
   1499 
   1500     @Override
   1501     public void writeUInt32(final int fieldNumber, final int value) throws IOException {
   1502       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1503       writeUInt32NoTag(value);
   1504     }
   1505 
   1506     @Override
   1507     public void writeFixed32(final int fieldNumber, final int value) throws IOException {
   1508       writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
   1509       writeFixed32NoTag(value);
   1510     }
   1511 
   1512     @Override
   1513     public void writeUInt64(final int fieldNumber, final long value) throws IOException {
   1514       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1515       writeUInt64NoTag(value);
   1516     }
   1517 
   1518     @Override
   1519     public void writeFixed64(final int fieldNumber, final long value) throws IOException {
   1520       writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
   1521       writeFixed64NoTag(value);
   1522     }
   1523 
   1524     @Override
   1525     public void writeBool(final int fieldNumber, final boolean value) throws IOException {
   1526       writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1527       write((byte) (value ? 1 : 0));
   1528     }
   1529 
   1530     @Override
   1531     public void writeString(final int fieldNumber, final String value) throws IOException {
   1532       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1533       writeStringNoTag(value);
   1534     }
   1535 
   1536     @Override
   1537     public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
   1538       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1539       writeBytesNoTag(value);
   1540     }
   1541 
   1542     @Override
   1543     public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
   1544       writeByteArray(fieldNumber, value, 0, value.length);
   1545     }
   1546 
   1547     @Override
   1548     public void writeByteArray(
   1549         final int fieldNumber, final byte[] value, final int offset, final int length)
   1550         throws IOException {
   1551       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1552       writeByteArrayNoTag(value, offset, length);
   1553     }
   1554 
   1555     @Override
   1556     public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
   1557         throws IOException {
   1558       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1559       writeUInt32NoTag(value.capacity());
   1560       writeRawBytes(value);
   1561     }
   1562 
   1563     @Override
   1564     public void writeMessage(final int fieldNumber, final MessageLite value)
   1565         throws IOException {
   1566       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   1567       writeMessageNoTag(value);
   1568     }
   1569 
   1570     @Override
   1571     public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
   1572         throws IOException {
   1573       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   1574       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   1575       writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
   1576       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   1577     }
   1578 
   1579     @Override
   1580     public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
   1581         throws IOException {
   1582       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   1583       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   1584       writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
   1585       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   1586     }
   1587 
   1588     @Override
   1589     public void writeMessageNoTag(final MessageLite value) throws IOException {
   1590       writeUInt32NoTag(value.getSerializedSize());
   1591       value.writeTo(this);
   1592     }
   1593 
   1594     @Override
   1595     public void write(byte value) throws IOException {
   1596       try {
   1597         buffer.put(value);
   1598       } catch (BufferOverflowException e) {
   1599         throw new OutOfSpaceException(e);
   1600       }
   1601     }
   1602 
   1603     @Override
   1604     public void writeBytesNoTag(final ByteString value) throws IOException {
   1605       writeUInt32NoTag(value.size());
   1606       value.writeTo(this);
   1607     }
   1608 
   1609     @Override
   1610     public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
   1611       writeUInt32NoTag(length);
   1612       write(value, offset, length);
   1613     }
   1614 
   1615     @Override
   1616     public void writeRawBytes(final ByteBuffer value) throws IOException {
   1617       if (value.hasArray()) {
   1618         write(value.array(), value.arrayOffset(), value.capacity());
   1619       } else {
   1620         ByteBuffer duplicated = value.duplicate();
   1621         duplicated.clear();
   1622         write(duplicated);
   1623       }
   1624     }
   1625 
   1626     @Override
   1627     public void writeInt32NoTag(int value) throws IOException {
   1628       if (value >= 0) {
   1629         writeUInt32NoTag(value);
   1630       } else {
   1631         // Must sign-extend.
   1632         writeUInt64NoTag(value);
   1633       }
   1634     }
   1635 
   1636     @Override
   1637     public void writeUInt32NoTag(int value) throws IOException {
   1638       try {
   1639         while (true) {
   1640           if ((value & ~0x7F) == 0) {
   1641             buffer.put((byte) value);
   1642             return;
   1643           } else {
   1644             buffer.put((byte) ((value & 0x7F) | 0x80));
   1645             value >>>= 7;
   1646           }
   1647         }
   1648       } catch (BufferOverflowException e) {
   1649         throw new OutOfSpaceException(e);
   1650       }
   1651     }
   1652 
   1653     @Override
   1654     public void writeFixed32NoTag(int value) throws IOException {
   1655       try {
   1656         buffer.putInt(value);
   1657       } catch (BufferOverflowException e) {
   1658         throw new OutOfSpaceException(e);
   1659       }
   1660     }
   1661 
   1662     @Override
   1663     public void writeUInt64NoTag(long value) throws IOException {
   1664       try {
   1665         while (true) {
   1666           if ((value & ~0x7FL) == 0) {
   1667             buffer.put((byte) value);
   1668             return;
   1669           } else {
   1670             buffer.put((byte) (((int) value & 0x7F) | 0x80));
   1671             value >>>= 7;
   1672           }
   1673         }
   1674       } catch (BufferOverflowException e) {
   1675         throw new OutOfSpaceException(e);
   1676       }
   1677     }
   1678 
   1679     @Override
   1680     public void writeFixed64NoTag(long value) throws IOException {
   1681       try {
   1682         buffer.putLong(value);
   1683       } catch (BufferOverflowException e) {
   1684         throw new OutOfSpaceException(e);
   1685       }
   1686     }
   1687 
   1688     @Override
   1689     public void write(byte[] value, int offset, int length) throws IOException {
   1690       try {
   1691         buffer.put(value, offset, length);
   1692       } catch (IndexOutOfBoundsException e) {
   1693         throw new OutOfSpaceException(e);
   1694       } catch (BufferOverflowException e) {
   1695         throw new OutOfSpaceException(e);
   1696       }
   1697     }
   1698 
   1699     @Override
   1700     public void writeLazy(byte[] value, int offset, int length) throws IOException {
   1701       write(value, offset, length);
   1702     }
   1703 
   1704     @Override
   1705     public void write(ByteBuffer value) throws IOException {
   1706       try {
   1707         buffer.put(value);
   1708       } catch (BufferOverflowException e) {
   1709         throw new OutOfSpaceException(e);
   1710       }
   1711     }
   1712 
   1713     @Override
   1714     public void writeLazy(ByteBuffer value) throws IOException {
   1715       write(value);
   1716     }
   1717 
   1718     @Override
   1719     public void writeStringNoTag(String value) throws IOException {
   1720       final int startPos = buffer.position();
   1721       try {
   1722         // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
   1723         // and at most 3 times of it. We take advantage of this in both branches below.
   1724         final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
   1725         final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
   1726         final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
   1727         if (minLengthVarIntSize == maxLengthVarIntSize) {
   1728           // Save the current position and increment past the length field. We'll come back
   1729           // and write the length field after the encoding is complete.
   1730           final int startOfBytes = buffer.position() + minLengthVarIntSize;
   1731           buffer.position(startOfBytes);
   1732 
   1733           // Encode the string.
   1734           encode(value);
   1735 
   1736           // Now go back to the beginning and write the length.
   1737           int endOfBytes = buffer.position();
   1738           buffer.position(startPos);
   1739           writeUInt32NoTag(endOfBytes - startOfBytes);
   1740 
   1741           // Reposition the buffer past the written data.
   1742           buffer.position(endOfBytes);
   1743         } else {
   1744           final int length = Utf8.encodedLength(value);
   1745           writeUInt32NoTag(length);
   1746           encode(value);
   1747         }
   1748       } catch (UnpairedSurrogateException e) {
   1749         // Roll back the change and convert to an IOException.
   1750         buffer.position(startPos);
   1751 
   1752         // TODO(nathanmittler): We should throw an IOException here instead.
   1753         inefficientWriteStringNoTag(value, e);
   1754       } catch (IllegalArgumentException e) {
   1755         // Thrown by buffer.position() if out of range.
   1756         throw new OutOfSpaceException(e);
   1757       }
   1758     }
   1759 
   1760     @Override
   1761     public void flush() {
   1762       // Update the position of the original buffer.
   1763       originalBuffer.position(buffer.position());
   1764     }
   1765 
   1766     @Override
   1767     public int spaceLeft() {
   1768       return buffer.remaining();
   1769     }
   1770 
   1771     @Override
   1772     public int getTotalBytesWritten() {
   1773       return buffer.position() - initialPosition;
   1774     }
   1775 
   1776     private void encode(String value) throws IOException {
   1777       try {
   1778         Utf8.encodeUtf8(value, buffer);
   1779       } catch (IndexOutOfBoundsException e) {
   1780         throw new OutOfSpaceException(e);
   1781       }
   1782     }
   1783   }
   1784 
   1785   /**
   1786    * Abstract base class for buffered encoders.
   1787    */
   1788   private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
   1789     final byte[] buffer;
   1790     final int limit;
   1791     int position;
   1792     int totalBytesWritten;
   1793 
   1794     AbstractBufferedEncoder(int bufferSize) {
   1795       if (bufferSize < 0) {
   1796         throw new IllegalArgumentException("bufferSize must be >= 0");
   1797       }
   1798       // As an optimization, we require that the buffer be able to store at least 2
   1799       // varints so that we can buffer any integer write (tag + value). This reduces the
   1800       // number of range checks for a single write to 1 (i.e. if there is not enough space
   1801       // to buffer the tag+value, flush and then buffer it).
   1802       this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)];
   1803       this.limit = buffer.length;
   1804     }
   1805 
   1806     @Override
   1807     public final int spaceLeft() {
   1808       throw new UnsupportedOperationException(
   1809           "spaceLeft() can only be called on CodedOutputStreams that are "
   1810               + "writing to a flat array or ByteBuffer.");
   1811     }
   1812 
   1813     @Override
   1814     public final int getTotalBytesWritten() {
   1815       return totalBytesWritten;
   1816     }
   1817 
   1818     /**
   1819      * This method does not perform bounds checking on the array. Checking array bounds is the
   1820      * responsibility of the caller.
   1821      */
   1822     final void buffer(byte value) {
   1823       buffer[position++] = value;
   1824       totalBytesWritten++;
   1825     }
   1826 
   1827     /**
   1828      * This method does not perform bounds checking on the array. Checking array bounds is the
   1829      * responsibility of the caller.
   1830      */
   1831     final void bufferTag(final int fieldNumber, final int wireType) {
   1832       bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
   1833     }
   1834 
   1835     /**
   1836      * This method does not perform bounds checking on the array. Checking array bounds is the
   1837      * responsibility of the caller.
   1838      */
   1839     final void bufferInt32NoTag(final int value) {
   1840       if (value >= 0) {
   1841         bufferUInt32NoTag(value);
   1842       } else {
   1843         // Must sign-extend.
   1844         bufferUInt64NoTag(value);
   1845       }
   1846     }
   1847 
   1848     /**
   1849      * This method does not perform bounds checking on the array. Checking array bounds is the
   1850      * responsibility of the caller.
   1851      */
   1852     final void bufferUInt32NoTag(int value) {
   1853       if (HAS_UNSAFE_ARRAY_OPERATIONS) {
   1854         final long originalPos = ARRAY_BASE_OFFSET + position;
   1855         long pos = originalPos;
   1856         while (true) {
   1857           if ((value & ~0x7F) == 0) {
   1858             UNSAFE.putByte(buffer, pos++, (byte) value);
   1859             break;
   1860           } else {
   1861             UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
   1862             value >>>= 7;
   1863           }
   1864         }
   1865         int delta = (int) (pos - originalPos);
   1866         position += delta;
   1867         totalBytesWritten += delta;
   1868       } else {
   1869         while (true) {
   1870           if ((value & ~0x7F) == 0) {
   1871             buffer[position++] = (byte) value;
   1872             totalBytesWritten++;
   1873             return;
   1874           } else {
   1875             buffer[position++] = (byte) ((value & 0x7F) | 0x80);
   1876             totalBytesWritten++;
   1877             value >>>= 7;
   1878           }
   1879         }
   1880       }
   1881     }
   1882 
   1883     /**
   1884      * This method does not perform bounds checking on the array. Checking array bounds is the
   1885      * responsibility of the caller.
   1886      */
   1887     final void bufferUInt64NoTag(long value) {
   1888       if (HAS_UNSAFE_ARRAY_OPERATIONS) {
   1889         final long originalPos = ARRAY_BASE_OFFSET + position;
   1890         long pos = originalPos;
   1891         while (true) {
   1892           if ((value & ~0x7FL) == 0) {
   1893             UNSAFE.putByte(buffer, pos++, (byte) value);
   1894             break;
   1895           } else {
   1896             UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
   1897             value >>>= 7;
   1898           }
   1899         }
   1900         int delta = (int) (pos - originalPos);
   1901         position += delta;
   1902         totalBytesWritten += delta;
   1903       } else {
   1904         while (true) {
   1905           if ((value & ~0x7FL) == 0) {
   1906             buffer[position++] = (byte) value;
   1907             totalBytesWritten++;
   1908             return;
   1909           } else {
   1910             buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
   1911             totalBytesWritten++;
   1912             value >>>= 7;
   1913           }
   1914         }
   1915       }
   1916     }
   1917 
   1918     /**
   1919      * This method does not perform bounds checking on the array. Checking array bounds is the
   1920      * responsibility of the caller.
   1921      */
   1922     final void bufferFixed32NoTag(int value) {
   1923       buffer[position++] = (byte) (value & 0xFF);
   1924       buffer[position++] = (byte) ((value >> 8) & 0xFF);
   1925       buffer[position++] = (byte) ((value >> 16) & 0xFF);
   1926       buffer[position++] = (byte) ((value >> 24) & 0xFF);
   1927       totalBytesWritten += FIXED_32_SIZE;
   1928     }
   1929 
   1930     /**
   1931      * This method does not perform bounds checking on the array. Checking array bounds is the
   1932      * responsibility of the caller.
   1933      */
   1934     final void bufferFixed64NoTag(long value) {
   1935       buffer[position++] = (byte) (value & 0xFF);
   1936       buffer[position++] = (byte) ((value >> 8) & 0xFF);
   1937       buffer[position++] = (byte) ((value >> 16) & 0xFF);
   1938       buffer[position++] = (byte) ((value >> 24) & 0xFF);
   1939       buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
   1940       buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
   1941       buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
   1942       buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
   1943       totalBytesWritten += FIXED_64_SIZE;
   1944     }
   1945   }
   1946 
   1947   /**
   1948    * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to
   1949    * support string encoding operations. All other writes are just passed through to the
   1950    * {@link ByteOutput}.
   1951    */
   1952   private static final class ByteOutputEncoder extends AbstractBufferedEncoder {
   1953     private final ByteOutput out;
   1954 
   1955     ByteOutputEncoder(ByteOutput out, int bufferSize) {
   1956       super(bufferSize);
   1957       if (out == null) {
   1958         throw new NullPointerException("out");
   1959       }
   1960       this.out = out;
   1961     }
   1962 
   1963     @Override
   1964     public void writeTag(final int fieldNumber, final int wireType) throws IOException {
   1965       writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
   1966     }
   1967 
   1968     @Override
   1969     public void writeInt32(final int fieldNumber, final int value) throws IOException {
   1970       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   1971       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1972       bufferInt32NoTag(value);
   1973     }
   1974 
   1975     @Override
   1976     public void writeUInt32(final int fieldNumber, final int value) throws IOException {
   1977       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   1978       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1979       bufferUInt32NoTag(value);
   1980     }
   1981 
   1982     @Override
   1983     public void writeFixed32(final int fieldNumber, final int value) throws IOException {
   1984       flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
   1985       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
   1986       bufferFixed32NoTag(value);
   1987     }
   1988 
   1989     @Override
   1990     public void writeUInt64(final int fieldNumber, final long value) throws IOException {
   1991       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   1992       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   1993       bufferUInt64NoTag(value);
   1994     }
   1995 
   1996     @Override
   1997     public void writeFixed64(final int fieldNumber, final long value) throws IOException {
   1998       flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
   1999       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
   2000       bufferFixed64NoTag(value);
   2001     }
   2002 
   2003     @Override
   2004     public void writeBool(final int fieldNumber, final boolean value) throws IOException {
   2005       flushIfNotAvailable(MAX_VARINT_SIZE + 1);
   2006       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   2007       buffer((byte) (value ? 1 : 0));
   2008     }
   2009 
   2010     @Override
   2011     public void writeString(final int fieldNumber, final String value) throws IOException {
   2012       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2013       writeStringNoTag(value);
   2014     }
   2015 
   2016     @Override
   2017     public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
   2018       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2019       writeBytesNoTag(value);
   2020     }
   2021 
   2022     @Override
   2023     public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
   2024       writeByteArray(fieldNumber, value, 0, value.length);
   2025     }
   2026 
   2027     @Override
   2028     public void writeByteArray(
   2029         final int fieldNumber, final byte[] value, final int offset, final int length)
   2030         throws IOException {
   2031       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2032       writeByteArrayNoTag(value, offset, length);
   2033     }
   2034 
   2035     @Override
   2036     public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
   2037         throws IOException {
   2038       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2039       writeUInt32NoTag(value.capacity());
   2040       writeRawBytes(value);
   2041     }
   2042 
   2043     @Override
   2044     public void writeBytesNoTag(final ByteString value) throws IOException {
   2045       writeUInt32NoTag(value.size());
   2046       value.writeTo(this);
   2047     }
   2048 
   2049     @Override
   2050     public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
   2051       writeUInt32NoTag(length);
   2052       write(value, offset, length);
   2053     }
   2054 
   2055     @Override
   2056     public void writeRawBytes(final ByteBuffer value) throws IOException {
   2057       if (value.hasArray()) {
   2058         write(value.array(), value.arrayOffset(), value.capacity());
   2059       } else {
   2060         ByteBuffer duplicated = value.duplicate();
   2061         duplicated.clear();
   2062         write(duplicated);
   2063       }
   2064     }
   2065 
   2066     @Override
   2067     public void writeMessage(final int fieldNumber, final MessageLite value)
   2068         throws IOException {
   2069       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2070       writeMessageNoTag(value);
   2071     }
   2072 
   2073     @Override
   2074     public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
   2075         throws IOException {
   2076       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   2077       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   2078       writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
   2079       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   2080     }
   2081 
   2082     @Override
   2083     public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
   2084         throws IOException {
   2085       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   2086       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   2087       writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
   2088       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   2089     }
   2090 
   2091     @Override
   2092     public void writeMessageNoTag(final MessageLite value) throws IOException {
   2093       writeUInt32NoTag(value.getSerializedSize());
   2094       value.writeTo(this);
   2095     }
   2096 
   2097     @Override
   2098     public void write(byte value) throws IOException {
   2099       if (position == limit) {
   2100         doFlush();
   2101       }
   2102 
   2103       buffer(value);
   2104     }
   2105 
   2106     @Override
   2107     public void writeInt32NoTag(int value) throws IOException {
   2108       if (value >= 0) {
   2109         writeUInt32NoTag(value);
   2110       } else {
   2111         // Must sign-extend.
   2112         writeUInt64NoTag(value);
   2113       }
   2114     }
   2115 
   2116     @Override
   2117     public void writeUInt32NoTag(int value) throws IOException {
   2118       flushIfNotAvailable(MAX_VARINT_SIZE);
   2119       bufferUInt32NoTag(value);
   2120     }
   2121 
   2122     @Override
   2123     public void writeFixed32NoTag(final int value) throws IOException {
   2124       flushIfNotAvailable(FIXED_32_SIZE);
   2125       bufferFixed32NoTag(value);
   2126     }
   2127 
   2128     @Override
   2129     public void writeUInt64NoTag(long value) throws IOException {
   2130       flushIfNotAvailable(MAX_VARINT_SIZE);
   2131       bufferUInt64NoTag(value);
   2132     }
   2133 
   2134     @Override
   2135     public void writeFixed64NoTag(final long value) throws IOException {
   2136       flushIfNotAvailable(FIXED_64_SIZE);
   2137       bufferFixed64NoTag(value);
   2138     }
   2139 
   2140     @Override
   2141     public void writeStringNoTag(String value) throws IOException {
   2142       // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
   2143       // and at most 3 times of it. We take advantage of this in both branches below.
   2144       final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
   2145       final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
   2146 
   2147       // If we are streaming and the potential length is too big to fit in our buffer, we take the
   2148       // slower path.
   2149       if (maxLengthVarIntSize + maxLength > limit) {
   2150         // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
   2151         // does the same internally and then does *another copy* to return a byte[] of exactly the
   2152         // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
   2153         // UTF-8 encoded bytes.
   2154         final byte[] encodedBytes = new byte[maxLength];
   2155         int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
   2156         writeUInt32NoTag(actualLength);
   2157         writeLazy(encodedBytes, 0, actualLength);
   2158         return;
   2159       }
   2160 
   2161       // Fast path: we have enough space available in our buffer for the string...
   2162       if (maxLengthVarIntSize + maxLength > limit - position) {
   2163         // Flush to free up space.
   2164         doFlush();
   2165       }
   2166 
   2167       final int oldPosition = position;
   2168       try {
   2169         // Optimize for the case where we know this length results in a constant varint length as
   2170         // this saves a pass for measuring the length of the string.
   2171         final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
   2172 
   2173         if (minLengthVarIntSize == maxLengthVarIntSize) {
   2174           position = oldPosition + minLengthVarIntSize;
   2175           int newPosition = Utf8.encode(value, buffer, position, limit - position);
   2176           // Since this class is stateful and tracks the position, we rewind and store the state,
   2177           // prepend the length, then reset it back to the end of the string.
   2178           position = oldPosition;
   2179           int length = newPosition - oldPosition - minLengthVarIntSize;
   2180           bufferUInt32NoTag(length);
   2181           position = newPosition;
   2182           totalBytesWritten += length;
   2183         } else {
   2184           int length = Utf8.encodedLength(value);
   2185           bufferUInt32NoTag(length);
   2186           position = Utf8.encode(value, buffer, position, length);
   2187           totalBytesWritten += length;
   2188         }
   2189       } catch (UnpairedSurrogateException e) {
   2190         // Roll back the change and convert to an IOException.
   2191         totalBytesWritten -= position - oldPosition;
   2192         position = oldPosition;
   2193 
   2194         // TODO(nathanmittler): We should throw an IOException here instead.
   2195         inefficientWriteStringNoTag(value, e);
   2196       } catch (IndexOutOfBoundsException e) {
   2197         throw new OutOfSpaceException(e);
   2198       }
   2199     }
   2200 
   2201     @Override
   2202     public void flush() throws IOException {
   2203       if (position > 0) {
   2204         // Flush the buffer.
   2205         doFlush();
   2206       }
   2207     }
   2208 
   2209     @Override
   2210     public void write(byte[] value, int offset, int length) throws IOException {
   2211       flush();
   2212       out.write(value, offset, length);
   2213       totalBytesWritten += length;
   2214     }
   2215 
   2216     @Override
   2217     public void writeLazy(byte[] value, int offset, int length) throws IOException {
   2218       flush();
   2219       out.writeLazy(value, offset, length);
   2220       totalBytesWritten += length;
   2221     }
   2222 
   2223     @Override
   2224     public void write(ByteBuffer value) throws IOException {
   2225       flush();
   2226       int length = value.remaining();
   2227       out.write(value);
   2228       totalBytesWritten += length;
   2229     }
   2230 
   2231     @Override
   2232     public void writeLazy(ByteBuffer value) throws IOException {
   2233       flush();
   2234       int length = value.remaining();
   2235       out.writeLazy(value);
   2236       totalBytesWritten += length;
   2237     }
   2238 
   2239     private void flushIfNotAvailable(int requiredSize) throws IOException {
   2240       if (limit - position < requiredSize) {
   2241         doFlush();
   2242       }
   2243     }
   2244 
   2245     private void doFlush() throws IOException {
   2246       out.write(buffer, 0, position);
   2247       position = 0;
   2248     }
   2249   }
   2250 
   2251   /**
   2252    * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal
   2253    * buffering to optimize writes to the {@link OutputStream}.
   2254    */
   2255   private static final class OutputStreamEncoder extends AbstractBufferedEncoder {
   2256     private final OutputStream out;
   2257 
   2258     OutputStreamEncoder(OutputStream out, int bufferSize) {
   2259       super(bufferSize);
   2260       if (out == null) {
   2261         throw new NullPointerException("out");
   2262       }
   2263       this.out = out;
   2264     }
   2265 
   2266     @Override
   2267     public void writeTag(final int fieldNumber, final int wireType) throws IOException {
   2268       writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
   2269     }
   2270 
   2271     @Override
   2272     public void writeInt32(final int fieldNumber, final int value) throws IOException {
   2273       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   2274       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   2275       bufferInt32NoTag(value);
   2276     }
   2277 
   2278     @Override
   2279     public void writeUInt32(final int fieldNumber, final int value) throws IOException {
   2280       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   2281       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   2282       bufferUInt32NoTag(value);
   2283     }
   2284 
   2285     @Override
   2286     public void writeFixed32(final int fieldNumber, final int value) throws IOException {
   2287       flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
   2288       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
   2289       bufferFixed32NoTag(value);
   2290     }
   2291 
   2292     @Override
   2293     public void writeUInt64(final int fieldNumber, final long value) throws IOException {
   2294       flushIfNotAvailable(MAX_VARINT_SIZE * 2);
   2295       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   2296       bufferUInt64NoTag(value);
   2297     }
   2298 
   2299     @Override
   2300     public void writeFixed64(final int fieldNumber, final long value) throws IOException {
   2301       flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
   2302       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
   2303       bufferFixed64NoTag(value);
   2304     }
   2305 
   2306     @Override
   2307     public void writeBool(final int fieldNumber, final boolean value) throws IOException {
   2308       flushIfNotAvailable(MAX_VARINT_SIZE + 1);
   2309       bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
   2310       buffer((byte) (value ? 1 : 0));
   2311     }
   2312 
   2313     @Override
   2314     public void writeString(final int fieldNumber, final String value) throws IOException {
   2315       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2316       writeStringNoTag(value);
   2317     }
   2318 
   2319     @Override
   2320     public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
   2321       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2322       writeBytesNoTag(value);
   2323     }
   2324 
   2325     @Override
   2326     public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
   2327       writeByteArray(fieldNumber, value, 0, value.length);
   2328     }
   2329 
   2330     @Override
   2331     public void writeByteArray(
   2332         final int fieldNumber, final byte[] value, final int offset, final int length)
   2333         throws IOException {
   2334       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2335       writeByteArrayNoTag(value, offset, length);
   2336     }
   2337 
   2338     @Override
   2339     public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
   2340         throws IOException {
   2341       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2342       writeUInt32NoTag(value.capacity());
   2343       writeRawBytes(value);
   2344     }
   2345 
   2346     @Override
   2347     public void writeBytesNoTag(final ByteString value) throws IOException {
   2348       writeUInt32NoTag(value.size());
   2349       value.writeTo(this);
   2350     }
   2351 
   2352     @Override
   2353     public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
   2354       writeUInt32NoTag(length);
   2355       write(value, offset, length);
   2356     }
   2357 
   2358     @Override
   2359     public void writeRawBytes(final ByteBuffer value) throws IOException {
   2360       if (value.hasArray()) {
   2361         write(value.array(), value.arrayOffset(), value.capacity());
   2362       } else {
   2363         ByteBuffer duplicated = value.duplicate();
   2364         duplicated.clear();
   2365         write(duplicated);
   2366       }
   2367     }
   2368 
   2369     @Override
   2370     public void writeMessage(final int fieldNumber, final MessageLite value)
   2371         throws IOException {
   2372       writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
   2373       writeMessageNoTag(value);
   2374     }
   2375 
   2376     @Override
   2377     public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
   2378         throws IOException {
   2379       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   2380       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   2381       writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
   2382       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   2383     }
   2384 
   2385     @Override
   2386     public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
   2387         throws IOException {
   2388       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
   2389       writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
   2390       writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
   2391       writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
   2392     }
   2393 
   2394     @Override
   2395     public void writeMessageNoTag(final MessageLite value) throws IOException {
   2396       writeUInt32NoTag(value.getSerializedSize());
   2397       value.writeTo(this);
   2398     }
   2399 
   2400     @Override
   2401     public void write(byte value) throws IOException {
   2402       if (position == limit) {
   2403         doFlush();
   2404       }
   2405 
   2406       buffer(value);
   2407     }
   2408 
   2409     @Override
   2410     public void writeInt32NoTag(int value) throws IOException {
   2411       if (value >= 0) {
   2412         writeUInt32NoTag(value);
   2413       } else {
   2414         // Must sign-extend.
   2415         writeUInt64NoTag(value);
   2416       }
   2417     }
   2418 
   2419     @Override
   2420     public void writeUInt32NoTag(int value) throws IOException {
   2421       flushIfNotAvailable(MAX_VARINT_SIZE);
   2422       bufferUInt32NoTag(value);
   2423     }
   2424 
   2425     @Override
   2426     public void writeFixed32NoTag(final int value) throws IOException {
   2427       flushIfNotAvailable(FIXED_32_SIZE);
   2428       bufferFixed32NoTag(value);
   2429     }
   2430 
   2431     @Override
   2432     public void writeUInt64NoTag(long value) throws IOException {
   2433       flushIfNotAvailable(MAX_VARINT_SIZE);
   2434       bufferUInt64NoTag(value);
   2435     }
   2436 
   2437     @Override
   2438     public void writeFixed64NoTag(final long value) throws IOException {
   2439       flushIfNotAvailable(FIXED_64_SIZE);
   2440       bufferFixed64NoTag(value);
   2441     }
   2442 
   2443     @Override
   2444     public void writeStringNoTag(String value) throws IOException {
   2445       try {
   2446         // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
   2447         // and at most 3 times of it. We take advantage of this in both branches below.
   2448         final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
   2449         final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
   2450 
   2451         // If we are streaming and the potential length is too big to fit in our buffer, we take the
   2452         // slower path.
   2453         if (maxLengthVarIntSize + maxLength > limit) {
   2454           // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
   2455           // does the same internally and then does *another copy* to return a byte[] of exactly the
   2456           // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
   2457           // UTF-8 encoded bytes.
   2458           final byte[] encodedBytes = new byte[maxLength];
   2459           int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
   2460           writeUInt32NoTag(actualLength);
   2461           writeLazy(encodedBytes, 0, actualLength);
   2462           return;
   2463         }
   2464 
   2465         // Fast path: we have enough space available in our buffer for the string...
   2466         if (maxLengthVarIntSize + maxLength > limit - position) {
   2467           // Flush to free up space.
   2468           doFlush();
   2469         }
   2470 
   2471         // Optimize for the case where we know this length results in a constant varint length as
   2472         // this saves a pass for measuring the length of the string.
   2473         final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
   2474         int oldPosition = position;
   2475         final int length;
   2476         try {
   2477           if (minLengthVarIntSize == maxLengthVarIntSize) {
   2478             position = oldPosition + minLengthVarIntSize;
   2479             int newPosition = Utf8.encode(value, buffer, position, limit - position);
   2480             // Since this class is stateful and tracks the position, we rewind and store the
   2481             // state, prepend the length, then reset it back to the end of the string.
   2482             position = oldPosition;
   2483             length = newPosition - oldPosition - minLengthVarIntSize;
   2484             bufferUInt32NoTag(length);
   2485             position = newPosition;
   2486           } else {
   2487             length = Utf8.encodedLength(value);
   2488             bufferUInt32NoTag(length);
   2489             position = Utf8.encode(value, buffer, position, length);
   2490           }
   2491           totalBytesWritten += length;
   2492         } catch (UnpairedSurrogateException e) {
   2493           // Be extra careful and restore the original position for retrying the write with the
   2494           // less efficient path.
   2495           totalBytesWritten -= position - oldPosition;
   2496           position = oldPosition;
   2497           throw e;
   2498         } catch (ArrayIndexOutOfBoundsException e) {
   2499           throw new OutOfSpaceException(e);
   2500         }
   2501       } catch (UnpairedSurrogateException e) {
   2502         inefficientWriteStringNoTag(value, e);
   2503       }
   2504     }
   2505 
   2506     @Override
   2507     public void flush() throws IOException {
   2508       if (position > 0) {
   2509         // Flush the buffer.
   2510         doFlush();
   2511       }
   2512     }
   2513 
   2514     @Override
   2515     public void write(byte[] value, int offset, int length)
   2516         throws IOException {
   2517       if (limit - position >= length) {
   2518         // We have room in the current buffer.
   2519         System.arraycopy(value, offset, buffer, position, length);
   2520         position += length;
   2521         totalBytesWritten += length;
   2522       } else {
   2523         // Write extends past current buffer.  Fill the rest of this buffer and
   2524         // flush.
   2525         final int bytesWritten = limit - position;
   2526         System.arraycopy(value, offset, buffer, position, bytesWritten);
   2527         offset += bytesWritten;
   2528         length -= bytesWritten;
   2529         position = limit;
   2530         totalBytesWritten += bytesWritten;
   2531         doFlush();
   2532 
   2533         // Now deal with the rest.
   2534         // Since we have an output stream, this is our buffer
   2535         // and buffer offset == 0
   2536         if (length <= limit) {
   2537           // Fits in new buffer.
   2538           System.arraycopy(value, offset, buffer, 0, length);
   2539           position = length;
   2540         } else {
   2541           // Write is very big.  Let's do it all at once.
   2542           out.write(value, offset, length);
   2543         }
   2544         totalBytesWritten += length;
   2545       }
   2546     }
   2547 
   2548     @Override
   2549     public void writeLazy(byte[] value, int offset, int length) throws IOException {
   2550       write(value, offset, length);
   2551     }
   2552 
   2553     @Override
   2554     public void write(ByteBuffer value) throws IOException {
   2555       int length = value.remaining();
   2556       if (limit - position >= length) {
   2557         // We have room in the current buffer.
   2558         value.get(buffer, position, length);
   2559         position += length;
   2560         totalBytesWritten += length;
   2561       } else {
   2562         // Write extends past current buffer.  Fill the rest of this buffer and
   2563         // flush.
   2564         final int bytesWritten = limit - position;
   2565         value.get(buffer, position, bytesWritten);
   2566         length -= bytesWritten;
   2567         position = limit;
   2568         totalBytesWritten += bytesWritten;
   2569         doFlush();
   2570 
   2571         // Now deal with the rest.
   2572         // Since we have an output stream, this is our buffer
   2573         // and buffer offset == 0
   2574         while (length > limit) {
   2575           // Copy data into the buffer before writing it to OutputStream.
   2576           value.get(buffer, 0, limit);
   2577           out.write(buffer, 0, limit);
   2578           length -= limit;
   2579           totalBytesWritten += limit;
   2580         }
   2581         value.get(buffer, 0, length);
   2582         position = length;
   2583         totalBytesWritten += length;
   2584       }
   2585     }
   2586 
   2587     @Override
   2588     public void writeLazy(ByteBuffer value) throws IOException {
   2589       write(value);
   2590     }
   2591 
   2592     private void flushIfNotAvailable(int requiredSize) throws IOException {
   2593       if (limit - position < requiredSize) {
   2594         doFlush();
   2595       }
   2596     }
   2597 
   2598     private void doFlush() throws IOException {
   2599       out.write(buffer, 0, position);
   2600       position = 0;
   2601     }
   2602   }
   2603 
   2604   /**
   2605    * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
   2606    * platform.
   2607    */
   2608   private static sun.misc.Unsafe getUnsafe() {
   2609     sun.misc.Unsafe unsafe = null;
   2610     try {
   2611       unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() {
   2612         @Override
   2613         public sun.misc.Unsafe run() throws Exception {
   2614           Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
   2615 
   2616           for (Field f : k.getDeclaredFields()) {
   2617             f.setAccessible(true);
   2618             Object x = f.get(null);
   2619             if (k.isInstance(x)) {
   2620               return k.cast(x);
   2621             }
   2622           }
   2623           // The sun.misc.Unsafe field does not exist.
   2624           return null;
   2625         }
   2626       });
   2627     } catch (Throwable e) {
   2628       // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
   2629       // for Unsafe.
   2630     }
   2631 
   2632     logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
   2633         unsafe != null ? "available" : "unavailable");
   2634     return unsafe;
   2635   }
   2636 
   2637   /**
   2638    * Indicates whether or not unsafe array operations are supported on this platform.
   2639    */
   2640   // TODO(nathanmittler): Add support for Android's MemoryBlock.
   2641   private static boolean supportsUnsafeArrayOperations() {
   2642     boolean supported = false;
   2643     if (UNSAFE != null) {
   2644       try {
   2645         UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class);
   2646         UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class);
   2647         supported = true;
   2648       } catch (Throwable e) {
   2649         // Do nothing.
   2650       }
   2651     }
   2652     logger.log(Level.FINEST, "Unsafe array operations: {}",
   2653         supported ? "available" : "unavailable");
   2654     return supported;
   2655   }
   2656 
   2657   /**
   2658    * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
   2659    * available.
   2660    */
   2661   private static <T> int byteArrayBaseOffset() {
   2662     return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
   2663   }
   2664 }
   2665