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