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