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