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