• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import static com.google.protobuf.Internal.checkNotNull;
34 import static com.google.protobuf.WireFormat.FIXED32_SIZE;
35 import static com.google.protobuf.WireFormat.FIXED64_SIZE;
36 import static com.google.protobuf.WireFormat.MAX_VARINT32_SIZE;
37 import static com.google.protobuf.WireFormat.MAX_VARINT64_SIZE;
38 import static com.google.protobuf.WireFormat.MESSAGE_SET_ITEM;
39 import static com.google.protobuf.WireFormat.MESSAGE_SET_MESSAGE;
40 import static com.google.protobuf.WireFormat.MESSAGE_SET_TYPE_ID;
41 import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
42 import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
43 import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
44 import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
45 import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
46 import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;
47 
48 import java.io.IOException;
49 import java.nio.ByteBuffer;
50 import java.nio.ByteOrder;
51 import java.util.ArrayDeque;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Queue;
55 
56 /**
57  * A protobuf writer that serializes messages in their binary form. Messages are serialized in
58  * reverse in order to avoid calculating the serialized size of each nested message. Since the
59  * message size is not known in advance, the writer employs a strategy of chunking and buffer
60  * chaining. Buffers are allocated as-needed by a provided {@link BufferAllocator}. Once writing is
61  * finished, the application can access the buffers in forward-writing order by calling {@link
62  * #complete()}.
63  *
64  * <p>Once {@link #complete()} has been called, the writer can not be reused for additional writes.
65  * The {@link #getTotalBytesWritten()} will continue to reflect the total of the write and will not
66  * be reset.
67  */
68 @ExperimentalApi
69 abstract class BinaryWriter extends ByteOutput implements Writer {
70   public static final int DEFAULT_CHUNK_SIZE = 4096;
71 
72   private final BufferAllocator alloc;
73   private final int chunkSize;
74 
75   final ArrayDeque<AllocatedBuffer> buffers = new ArrayDeque<AllocatedBuffer>(4);
76   int totalDoneBytes;
77 
78   /**
79    * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@link
80    * #DEFAULT_CHUNK_SIZE} as necessary.
81    */
newHeapInstance(BufferAllocator alloc)82   public static BinaryWriter newHeapInstance(BufferAllocator alloc) {
83     return newHeapInstance(alloc, DEFAULT_CHUNK_SIZE);
84   }
85 
86   /**
87    * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@code chunkSize} as
88    * necessary.
89    */
newHeapInstance(BufferAllocator alloc, int chunkSize)90   public static BinaryWriter newHeapInstance(BufferAllocator alloc, int chunkSize) {
91     return isUnsafeHeapSupported()
92         ? newUnsafeHeapInstance(alloc, chunkSize)
93         : newSafeHeapInstance(alloc, chunkSize);
94   }
95 
96   /**
97    * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@link
98    * #DEFAULT_CHUNK_SIZE} as necessary.
99    */
newDirectInstance(BufferAllocator alloc)100   public static BinaryWriter newDirectInstance(BufferAllocator alloc) {
101     return newDirectInstance(alloc, DEFAULT_CHUNK_SIZE);
102   }
103 
104   /**
105    * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@code
106    * chunkSize} as necessary.
107    */
newDirectInstance(BufferAllocator alloc, int chunkSize)108   public static BinaryWriter newDirectInstance(BufferAllocator alloc, int chunkSize) {
109     return isUnsafeDirectSupported()
110         ? newUnsafeDirectInstance(alloc, chunkSize)
111         : newSafeDirectInstance(alloc, chunkSize);
112   }
113 
isUnsafeHeapSupported()114   static boolean isUnsafeHeapSupported() {
115     return UnsafeHeapWriter.isSupported();
116   }
117 
isUnsafeDirectSupported()118   static boolean isUnsafeDirectSupported() {
119     return UnsafeDirectWriter.isSupported();
120   }
121 
newSafeHeapInstance(BufferAllocator alloc, int chunkSize)122   static BinaryWriter newSafeHeapInstance(BufferAllocator alloc, int chunkSize) {
123     return new SafeHeapWriter(alloc, chunkSize);
124   }
125 
newUnsafeHeapInstance(BufferAllocator alloc, int chunkSize)126   static BinaryWriter newUnsafeHeapInstance(BufferAllocator alloc, int chunkSize) {
127     if (!isUnsafeHeapSupported()) {
128       throw new UnsupportedOperationException("Unsafe operations not supported");
129     }
130     return new UnsafeHeapWriter(alloc, chunkSize);
131   }
132 
newSafeDirectInstance(BufferAllocator alloc, int chunkSize)133   static BinaryWriter newSafeDirectInstance(BufferAllocator alloc, int chunkSize) {
134     return new SafeDirectWriter(alloc, chunkSize);
135   }
136 
newUnsafeDirectInstance(BufferAllocator alloc, int chunkSize)137   static BinaryWriter newUnsafeDirectInstance(BufferAllocator alloc, int chunkSize) {
138     if (!isUnsafeDirectSupported()) {
139       throw new UnsupportedOperationException("Unsafe operations not supported");
140     }
141     return new UnsafeDirectWriter(alloc, chunkSize);
142   }
143 
144   /** Only allow subclassing for inner classes. */
BinaryWriter(BufferAllocator alloc, int chunkSize)145   private BinaryWriter(BufferAllocator alloc, int chunkSize) {
146     if (chunkSize <= 0) {
147       throw new IllegalArgumentException("chunkSize must be > 0");
148     }
149     this.alloc = checkNotNull(alloc, "alloc");
150     this.chunkSize = chunkSize;
151   }
152 
153   @Override
fieldOrder()154   public final FieldOrder fieldOrder() {
155     return FieldOrder.DESCENDING;
156   }
157 
158   /**
159    * Completes the write operation and returns a queue of {@link AllocatedBuffer} objects in
160    * forward-writing order. This method should only be called once.
161    *
162    * <p>After calling this method, the writer can not be reused. Create a new writer for future
163    * writes.
164    */
complete()165   public final Queue<AllocatedBuffer> complete() {
166     finishCurrentBuffer();
167     return buffers;
168   }
169 
170   @Override
writeSFixed32(int fieldNumber, int value)171   public final void writeSFixed32(int fieldNumber, int value) throws IOException {
172     writeFixed32(fieldNumber, value);
173   }
174 
175   @Override
writeInt64(int fieldNumber, long value)176   public final void writeInt64(int fieldNumber, long value) throws IOException {
177     writeUInt64(fieldNumber, value);
178   }
179 
180   @Override
writeSFixed64(int fieldNumber, long value)181   public final void writeSFixed64(int fieldNumber, long value) throws IOException {
182     writeFixed64(fieldNumber, value);
183   }
184 
185   @Override
writeFloat(int fieldNumber, float value)186   public final void writeFloat(int fieldNumber, float value) throws IOException {
187     writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
188   }
189 
190   @Override
writeDouble(int fieldNumber, double value)191   public final void writeDouble(int fieldNumber, double value) throws IOException {
192     writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
193   }
194 
195   @Override
writeEnum(int fieldNumber, int value)196   public final void writeEnum(int fieldNumber, int value) throws IOException {
197     writeInt32(fieldNumber, value);
198   }
199 
200   @Override
writeInt32List(int fieldNumber, List<Integer> list, boolean packed)201   public final void writeInt32List(int fieldNumber, List<Integer> list, boolean packed)
202       throws IOException {
203     if (list instanceof IntArrayList) {
204       writeInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
205     } else {
206       writeInt32List_Internal(fieldNumber, list, packed);
207     }
208   }
209 
writeInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)210   private final void writeInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
211       throws IOException {
212     if (packed) {
213       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
214       int prevBytes = getTotalBytesWritten();
215       for (int i = list.size() - 1; i >= 0; --i) {
216         writeInt32(list.get(i));
217       }
218       int length = getTotalBytesWritten() - prevBytes;
219       writeVarint32(length);
220       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
221     } else {
222       for (int i = list.size() - 1; i >= 0; --i) {
223         writeInt32(fieldNumber, list.get(i));
224       }
225     }
226   }
227 
writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)228   private final void writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
229       throws IOException {
230     if (packed) {
231       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
232       int prevBytes = getTotalBytesWritten();
233       for (int i = list.size() - 1; i >= 0; --i) {
234         writeInt32(list.getInt(i));
235       }
236       int length = getTotalBytesWritten() - prevBytes;
237       writeVarint32(length);
238       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
239     } else {
240       for (int i = list.size() - 1; i >= 0; --i) {
241         writeInt32(fieldNumber, list.getInt(i));
242       }
243     }
244   }
245 
246   @Override
writeFixed32List(int fieldNumber, List<Integer> list, boolean packed)247   public final void writeFixed32List(int fieldNumber, List<Integer> list, boolean packed)
248       throws IOException {
249     if (list instanceof IntArrayList) {
250       writeFixed32List_Internal(fieldNumber, (IntArrayList) list, packed);
251     } else {
252       writeFixed32List_Internal(fieldNumber, list, packed);
253     }
254   }
255 
writeFixed32List_Internal(int fieldNumber, List<Integer> list, boolean packed)256   private final void writeFixed32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
257       throws IOException {
258     if (packed) {
259       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
260       int prevBytes = getTotalBytesWritten();
261       for (int i = list.size() - 1; i >= 0; --i) {
262         writeFixed32(list.get(i));
263       }
264       int length = getTotalBytesWritten() - prevBytes;
265       writeVarint32(length);
266       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
267     } else {
268       for (int i = list.size() - 1; i >= 0; --i) {
269         writeFixed32(fieldNumber, list.get(i));
270       }
271     }
272   }
273 
writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed)274   private final void writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
275       throws IOException {
276     if (packed) {
277       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
278       int prevBytes = getTotalBytesWritten();
279       for (int i = list.size() - 1; i >= 0; --i) {
280         writeFixed32(list.getInt(i));
281       }
282       int length = getTotalBytesWritten() - prevBytes;
283       writeVarint32(length);
284       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
285     } else {
286       for (int i = list.size() - 1; i >= 0; --i) {
287         writeFixed32(fieldNumber, list.getInt(i));
288       }
289     }
290   }
291 
292   @Override
writeInt64List(int fieldNumber, List<Long> list, boolean packed)293   public final void writeInt64List(int fieldNumber, List<Long> list, boolean packed)
294       throws IOException {
295     writeUInt64List(fieldNumber, list, packed);
296   }
297 
298   @Override
writeUInt64List(int fieldNumber, List<Long> list, boolean packed)299   public final void writeUInt64List(int fieldNumber, List<Long> list, boolean packed)
300       throws IOException {
301     if (list instanceof LongArrayList) {
302       writeUInt64List_Internal(fieldNumber, (LongArrayList) list, packed);
303     } else {
304       writeUInt64List_Internal(fieldNumber, list, packed);
305     }
306   }
307 
writeUInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)308   private final void writeUInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
309       throws IOException {
310     if (packed) {
311       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
312       int prevBytes = getTotalBytesWritten();
313       for (int i = list.size() - 1; i >= 0; --i) {
314         writeVarint64(list.get(i));
315       }
316       int length = getTotalBytesWritten() - prevBytes;
317       writeVarint32(length);
318       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
319     } else {
320       for (int i = list.size() - 1; i >= 0; --i) {
321         writeUInt64(fieldNumber, list.get(i));
322       }
323     }
324   }
325 
writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)326   private final void writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
327       throws IOException {
328     if (packed) {
329       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
330       int prevBytes = getTotalBytesWritten();
331       for (int i = list.size() - 1; i >= 0; --i) {
332         writeVarint64(list.getLong(i));
333       }
334       int length = getTotalBytesWritten() - prevBytes;
335       writeVarint32(length);
336       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
337     } else {
338       for (int i = list.size() - 1; i >= 0; --i) {
339         writeUInt64(fieldNumber, list.getLong(i));
340       }
341     }
342   }
343 
344   @Override
writeFixed64List(int fieldNumber, List<Long> list, boolean packed)345   public final void writeFixed64List(int fieldNumber, List<Long> list, boolean packed)
346       throws IOException {
347     if (list instanceof LongArrayList) {
348       writeFixed64List_Internal(fieldNumber, (LongArrayList) list, packed);
349     } else {
350       writeFixed64List_Internal(fieldNumber, list, packed);
351     }
352   }
353 
writeFixed64List_Internal(int fieldNumber, List<Long> list, boolean packed)354   private final void writeFixed64List_Internal(int fieldNumber, List<Long> list, boolean packed)
355       throws IOException {
356     if (packed) {
357       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
358       int prevBytes = getTotalBytesWritten();
359       for (int i = list.size() - 1; i >= 0; --i) {
360         writeFixed64(list.get(i));
361       }
362       int length = getTotalBytesWritten() - prevBytes;
363       writeVarint32(length);
364       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
365     } else {
366       for (int i = list.size() - 1; i >= 0; --i) {
367         writeFixed64(fieldNumber, list.get(i));
368       }
369     }
370   }
371 
writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed)372   private final void writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
373       throws IOException {
374     if (packed) {
375       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
376       int prevBytes = getTotalBytesWritten();
377       for (int i = list.size() - 1; i >= 0; --i) {
378         writeFixed64(list.getLong(i));
379       }
380       int length = getTotalBytesWritten() - prevBytes;
381       writeVarint32(length);
382       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
383     } else {
384       for (int i = list.size() - 1; i >= 0; --i) {
385         writeFixed64(fieldNumber, list.getLong(i));
386       }
387     }
388   }
389 
390   @Override
writeFloatList(int fieldNumber, List<Float> list, boolean packed)391   public final void writeFloatList(int fieldNumber, List<Float> list, boolean packed)
392       throws IOException {
393     if (list instanceof FloatArrayList) {
394       writeFloatList_Internal(fieldNumber, (FloatArrayList) list, packed);
395     } else {
396       writeFloatList_Internal(fieldNumber, list, packed);
397     }
398   }
399 
writeFloatList_Internal(int fieldNumber, List<Float> list, boolean packed)400   private final void writeFloatList_Internal(int fieldNumber, List<Float> list, boolean packed)
401       throws IOException {
402     if (packed) {
403       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
404       int prevBytes = getTotalBytesWritten();
405       for (int i = list.size() - 1; i >= 0; --i) {
406         writeFixed32(Float.floatToRawIntBits(list.get(i)));
407       }
408       int length = getTotalBytesWritten() - prevBytes;
409       writeVarint32(length);
410       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
411     } else {
412       for (int i = list.size() - 1; i >= 0; --i) {
413         writeFloat(fieldNumber, list.get(i));
414       }
415     }
416   }
417 
writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed)418   private final void writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed)
419       throws IOException {
420     if (packed) {
421       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
422       int prevBytes = getTotalBytesWritten();
423       for (int i = list.size() - 1; i >= 0; --i) {
424         writeFixed32(Float.floatToRawIntBits(list.getFloat(i)));
425       }
426       int length = getTotalBytesWritten() - prevBytes;
427       writeVarint32(length);
428       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
429     } else {
430       for (int i = list.size() - 1; i >= 0; --i) {
431         writeFloat(fieldNumber, list.getFloat(i));
432       }
433     }
434   }
435 
436   @Override
writeDoubleList(int fieldNumber, List<Double> list, boolean packed)437   public final void writeDoubleList(int fieldNumber, List<Double> list, boolean packed)
438       throws IOException {
439     if (list instanceof DoubleArrayList) {
440       writeDoubleList_Internal(fieldNumber, (DoubleArrayList) list, packed);
441     } else {
442       writeDoubleList_Internal(fieldNumber, list, packed);
443     }
444   }
445 
writeDoubleList_Internal(int fieldNumber, List<Double> list, boolean packed)446   private final void writeDoubleList_Internal(int fieldNumber, List<Double> list, boolean packed)
447       throws IOException {
448     if (packed) {
449       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
450       int prevBytes = getTotalBytesWritten();
451       for (int i = list.size() - 1; i >= 0; --i) {
452         writeFixed64(Double.doubleToRawLongBits(list.get(i)));
453       }
454       int length = getTotalBytesWritten() - prevBytes;
455       writeVarint32(length);
456       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
457     } else {
458       for (int i = list.size() - 1; i >= 0; --i) {
459         writeDouble(fieldNumber, list.get(i));
460       }
461     }
462   }
463 
writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed)464   private final void writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed)
465       throws IOException {
466     if (packed) {
467       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
468       int prevBytes = getTotalBytesWritten();
469       for (int i = list.size() - 1; i >= 0; --i) {
470         writeFixed64(Double.doubleToRawLongBits(list.getDouble(i)));
471       }
472       int length = getTotalBytesWritten() - prevBytes;
473       writeVarint32(length);
474       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
475     } else {
476       for (int i = list.size() - 1; i >= 0; --i) {
477         writeDouble(fieldNumber, list.getDouble(i));
478       }
479     }
480   }
481 
482   @Override
writeEnumList(int fieldNumber, List<Integer> list, boolean packed)483   public final void writeEnumList(int fieldNumber, List<Integer> list, boolean packed)
484       throws IOException {
485     writeInt32List(fieldNumber, list, packed);
486   }
487 
488   @Override
writeBoolList(int fieldNumber, List<Boolean> list, boolean packed)489   public final void writeBoolList(int fieldNumber, List<Boolean> list, boolean packed)
490       throws IOException {
491     if (list instanceof BooleanArrayList) {
492       writeBoolList_Internal(fieldNumber, (BooleanArrayList) list, packed);
493     } else {
494       writeBoolList_Internal(fieldNumber, list, packed);
495     }
496   }
497 
writeBoolList_Internal(int fieldNumber, List<Boolean> list, boolean packed)498   private final void writeBoolList_Internal(int fieldNumber, List<Boolean> list, boolean packed)
499       throws IOException {
500     if (packed) {
501       requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
502       int prevBytes = getTotalBytesWritten();
503       for (int i = list.size() - 1; i >= 0; --i) {
504         writeBool(list.get(i));
505       }
506       int length = getTotalBytesWritten() - prevBytes;
507       writeVarint32(length);
508       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
509     } else {
510       for (int i = list.size() - 1; i >= 0; --i) {
511         writeBool(fieldNumber, list.get(i));
512       }
513     }
514   }
515 
writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed)516   private final void writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed)
517       throws IOException {
518     if (packed) {
519       requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
520       int prevBytes = getTotalBytesWritten();
521       for (int i = list.size() - 1; i >= 0; --i) {
522         writeBool(list.getBoolean(i));
523       }
524       int length = getTotalBytesWritten() - prevBytes;
525       writeVarint32(length);
526       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
527     } else {
528       for (int i = list.size() - 1; i >= 0; --i) {
529         writeBool(fieldNumber, list.getBoolean(i));
530       }
531     }
532   }
533 
534   @Override
writeStringList(int fieldNumber, List<String> list)535   public final void writeStringList(int fieldNumber, List<String> list) throws IOException {
536     if (list instanceof LazyStringList) {
537       final LazyStringList lazyList = (LazyStringList) list;
538       for (int i = list.size() - 1; i >= 0; i--) {
539         writeLazyString(fieldNumber, lazyList.getRaw(i));
540       }
541     } else {
542       for (int i = list.size() - 1; i >= 0; i--) {
543         writeString(fieldNumber, list.get(i));
544       }
545     }
546   }
547 
writeLazyString(int fieldNumber, Object value)548   private void writeLazyString(int fieldNumber, Object value) throws IOException {
549     if (value instanceof String) {
550       writeString(fieldNumber, (String) value);
551     } else {
552       writeBytes(fieldNumber, (ByteString) value);
553     }
554   }
555 
556   @Override
writeBytesList(int fieldNumber, List<ByteString> list)557   public final void writeBytesList(int fieldNumber, List<ByteString> list) throws IOException {
558     for (int i = list.size() - 1; i >= 0; i--) {
559       writeBytes(fieldNumber, list.get(i));
560     }
561   }
562 
563   @Override
writeUInt32List(int fieldNumber, List<Integer> list, boolean packed)564   public final void writeUInt32List(int fieldNumber, List<Integer> list, boolean packed)
565       throws IOException {
566     if (list instanceof IntArrayList) {
567       writeUInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
568     } else {
569       writeUInt32List_Internal(fieldNumber, list, packed);
570     }
571   }
572 
writeUInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)573   private final void writeUInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
574       throws IOException {
575     if (packed) {
576       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
577       int prevBytes = getTotalBytesWritten();
578       for (int i = list.size() - 1; i >= 0; --i) {
579         writeVarint32(list.get(i));
580       }
581       int length = getTotalBytesWritten() - prevBytes;
582       writeVarint32(length);
583       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
584     } else {
585       for (int i = list.size() - 1; i >= 0; --i) {
586         writeUInt32(fieldNumber, list.get(i));
587       }
588     }
589   }
590 
writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)591   private final void writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
592       throws IOException {
593     if (packed) {
594       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
595       int prevBytes = getTotalBytesWritten();
596       for (int i = list.size() - 1; i >= 0; --i) {
597         writeVarint32(list.getInt(i));
598       }
599       int length = getTotalBytesWritten() - prevBytes;
600       writeVarint32(length);
601       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
602     } else {
603       for (int i = list.size() - 1; i >= 0; --i) {
604         writeUInt32(fieldNumber, list.getInt(i));
605       }
606     }
607   }
608 
609   @Override
writeSFixed32List(int fieldNumber, List<Integer> list, boolean packed)610   public final void writeSFixed32List(int fieldNumber, List<Integer> list, boolean packed)
611       throws IOException {
612     writeFixed32List(fieldNumber, list, packed);
613   }
614 
615   @Override
writeSFixed64List(int fieldNumber, List<Long> list, boolean packed)616   public final void writeSFixed64List(int fieldNumber, List<Long> list, boolean packed)
617       throws IOException {
618     writeFixed64List(fieldNumber, list, packed);
619   }
620 
621   @Override
writeSInt32List(int fieldNumber, List<Integer> list, boolean packed)622   public final void writeSInt32List(int fieldNumber, List<Integer> list, boolean packed)
623       throws IOException {
624     if (list instanceof IntArrayList) {
625       writeSInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
626     } else {
627       writeSInt32List_Internal(fieldNumber, list, packed);
628     }
629   }
630 
writeSInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)631   private final void writeSInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
632       throws IOException {
633     if (packed) {
634       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
635       int prevBytes = getTotalBytesWritten();
636       for (int i = list.size() - 1; i >= 0; --i) {
637         writeSInt32(list.get(i));
638       }
639       int length = getTotalBytesWritten() - prevBytes;
640       writeVarint32(length);
641       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
642     } else {
643       for (int i = list.size() - 1; i >= 0; --i) {
644         writeSInt32(fieldNumber, list.get(i));
645       }
646     }
647   }
648 
writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)649   private final void writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
650       throws IOException {
651     if (packed) {
652       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
653       int prevBytes = getTotalBytesWritten();
654       for (int i = list.size() - 1; i >= 0; --i) {
655         writeSInt32(list.getInt(i));
656       }
657       int length = getTotalBytesWritten() - prevBytes;
658       writeVarint32(length);
659       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
660     } else {
661       for (int i = list.size() - 1; i >= 0; --i) {
662         writeSInt32(fieldNumber, list.getInt(i));
663       }
664     }
665   }
666 
667   @Override
writeSInt64List(int fieldNumber, List<Long> list, boolean packed)668   public final void writeSInt64List(int fieldNumber, List<Long> list, boolean packed)
669       throws IOException {
670     if (list instanceof LongArrayList) {
671       writeSInt64List_Internal(fieldNumber, (LongArrayList) list, packed);
672     } else {
673       writeSInt64List_Internal(fieldNumber, list, packed);
674     }
675   }
676 
677   private static final int MAP_KEY_NUMBER = 1;
678   private static final int MAP_VALUE_NUMBER = 2;
679 
680   @Override
writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)681   public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
682       throws IOException {
683     // TODO(liujisi): Reverse write those entries.
684     for (Map.Entry<K, V> entry : map.entrySet()) {
685       int prevBytes = getTotalBytesWritten();
686       writeMapEntryField(this, MAP_VALUE_NUMBER, metadata.valueType, entry.getValue());
687       writeMapEntryField(this, MAP_KEY_NUMBER, metadata.keyType, entry.getKey());
688       int length = getTotalBytesWritten() - prevBytes;
689       writeVarint32(length);
690       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
691     }
692   }
693 
writeMapEntryField( Writer writer, int fieldNumber, WireFormat.FieldType fieldType, Object object)694   static final void writeMapEntryField(
695       Writer writer, int fieldNumber, WireFormat.FieldType fieldType, Object object)
696       throws IOException {
697     switch (fieldType) {
698       case BOOL:
699         writer.writeBool(fieldNumber, (Boolean) object);
700         break;
701       case FIXED32:
702         writer.writeFixed32(fieldNumber, (Integer) object);
703         break;
704       case FIXED64:
705         writer.writeFixed64(fieldNumber, (Long) object);
706         break;
707       case INT32:
708         writer.writeInt32(fieldNumber, (Integer) object);
709         break;
710       case INT64:
711         writer.writeInt64(fieldNumber, (Long) object);
712         break;
713       case SFIXED32:
714         writer.writeSFixed32(fieldNumber, (Integer) object);
715         break;
716       case SFIXED64:
717         writer.writeSFixed64(fieldNumber, (Long) object);
718         break;
719       case SINT32:
720         writer.writeSInt32(fieldNumber, (Integer) object);
721         break;
722       case SINT64:
723         writer.writeSInt64(fieldNumber, (Long) object);
724         break;
725       case STRING:
726         writer.writeString(fieldNumber, (String) object);
727         break;
728       case UINT32:
729         writer.writeUInt32(fieldNumber, (Integer) object);
730         break;
731       case UINT64:
732         writer.writeUInt64(fieldNumber, (Long) object);
733         break;
734       case FLOAT:
735         writer.writeFloat(fieldNumber, (Float) object);
736         break;
737       case DOUBLE:
738         writer.writeDouble(fieldNumber, (Double) object);
739         break;
740       case MESSAGE:
741         writer.writeMessage(fieldNumber, object);
742         break;
743       case BYTES:
744         writer.writeBytes(fieldNumber, (ByteString) object);
745         break;
746       case ENUM:
747         if (object instanceof Internal.EnumLite) {
748           writer.writeEnum(fieldNumber, ((Internal.EnumLite) object).getNumber());
749         } else if (object instanceof Integer) {
750           writer.writeEnum(fieldNumber, (Integer) object);
751         } else {
752           throw new IllegalArgumentException("Unexpected type for enum in map.");
753         }
754         break;
755       default:
756         throw new IllegalArgumentException("Unsupported map value type for: " + fieldType);
757     }
758   }
759 
writeSInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)760   private final void writeSInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
761       throws IOException {
762     if (packed) {
763       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
764       int prevBytes = getTotalBytesWritten();
765       for (int i = list.size() - 1; i >= 0; --i) {
766         writeSInt64(list.get(i));
767       }
768       int length = getTotalBytesWritten() - prevBytes;
769       writeVarint32(length);
770       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
771     } else {
772       for (int i = list.size() - 1; i >= 0; --i) {
773         writeSInt64(fieldNumber, list.get(i));
774       }
775     }
776   }
777 
writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)778   private final void writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
779       throws IOException {
780     if (packed) {
781       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
782       int prevBytes = getTotalBytesWritten();
783       for (int i = list.size() - 1; i >= 0; --i) {
784         writeSInt64(list.getLong(i));
785       }
786       int length = getTotalBytesWritten() - prevBytes;
787       writeVarint32(length);
788       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
789     } else {
790       for (int i = list.size() - 1; i >= 0; --i) {
791         writeSInt64(fieldNumber, list.getLong(i));
792       }
793     }
794   }
795 
796   @Override
writeMessageList(int fieldNumber, List<?> list)797   public final void writeMessageList(int fieldNumber, List<?> list) throws IOException {
798     for (int i = list.size() - 1; i >= 0; i--) {
799       writeMessage(fieldNumber, list.get(i));
800     }
801   }
802 
803   @Override
writeMessageList(int fieldNumber, List<?> list, Schema schema)804   public final void writeMessageList(int fieldNumber, List<?> list, Schema schema)
805       throws IOException {
806     for (int i = list.size() - 1; i >= 0; i--) {
807       writeMessage(fieldNumber, list.get(i), schema);
808     }
809   }
810 
811   @Override
writeGroupList(int fieldNumber, List<?> list)812   public final void writeGroupList(int fieldNumber, List<?> list) throws IOException {
813     for (int i = list.size() - 1; i >= 0; i--) {
814       writeGroup(fieldNumber, list.get(i));
815     }
816   }
817 
818   @Override
writeGroupList(int fieldNumber, List<?> list, Schema schema)819   public final void writeGroupList(int fieldNumber, List<?> list, Schema schema)
820       throws IOException {
821     for (int i = list.size() - 1; i >= 0; i--) {
822       writeGroup(fieldNumber, list.get(i), schema);
823     }
824   }
825 
826   @Override
writeMessageSetItem(int fieldNumber, Object value)827   public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException {
828     writeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
829     if (value instanceof ByteString) {
830       writeBytes(MESSAGE_SET_MESSAGE, (ByteString) value);
831     } else {
832       writeMessage(MESSAGE_SET_MESSAGE, value);
833     }
834     writeUInt32(MESSAGE_SET_TYPE_ID, fieldNumber);
835     writeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
836   }
837 
newHeapBuffer()838   final AllocatedBuffer newHeapBuffer() {
839     return alloc.allocateHeapBuffer(chunkSize);
840   }
841 
newHeapBuffer(int capacity)842   final AllocatedBuffer newHeapBuffer(int capacity) {
843     return alloc.allocateHeapBuffer(Math.max(capacity, chunkSize));
844   }
845 
newDirectBuffer()846   final AllocatedBuffer newDirectBuffer() {
847     return alloc.allocateDirectBuffer(chunkSize);
848   }
849 
newDirectBuffer(int capacity)850   final AllocatedBuffer newDirectBuffer(int capacity) {
851     return alloc.allocateDirectBuffer(Math.max(capacity, chunkSize));
852   }
853 
854   /**
855    * Gets the total number of bytes that have been written. This will not be reset by a call to
856    * {@link #complete()}.
857    */
getTotalBytesWritten()858   public abstract int getTotalBytesWritten();
859 
requireSpace(int size)860   abstract void requireSpace(int size);
861 
finishCurrentBuffer()862   abstract void finishCurrentBuffer();
863 
writeTag(int fieldNumber, int wireType)864   abstract void writeTag(int fieldNumber, int wireType);
865 
writeVarint32(int value)866   abstract void writeVarint32(int value);
867 
writeInt32(int value)868   abstract void writeInt32(int value);
869 
writeSInt32(int value)870   abstract void writeSInt32(int value);
871 
writeFixed32(int value)872   abstract void writeFixed32(int value);
873 
writeVarint64(long value)874   abstract void writeVarint64(long value);
875 
writeSInt64(long value)876   abstract void writeSInt64(long value);
877 
writeFixed64(long value)878   abstract void writeFixed64(long value);
879 
writeBool(boolean value)880   abstract void writeBool(boolean value);
881 
writeString(String in)882   abstract void writeString(String in);
883 
884   /**
885    * Not using the version in CodedOutputStream due to the fact that benchmarks have shown a
886    * performance improvement when returning a byte (rather than an int).
887    */
computeUInt64SizeNoTag(long value)888   private static byte computeUInt64SizeNoTag(long value) {
889     // handle two popular special cases up front ...
890     if ((value & (~0L << 7)) == 0L) {
891       // Byte 1
892       return 1;
893     }
894     if (value < 0L) {
895       // Byte 10
896       return 10;
897     }
898     // ... leaving us with 8 remaining, which we can divide and conquer
899     byte n = 2;
900     if ((value & (~0L << 35)) != 0L) {
901       // Byte 6-9
902       n += 4; // + (value >>> 63);
903       value >>>= 28;
904     }
905     if ((value & (~0L << 21)) != 0L) {
906       // Byte 4-5 or 8-9
907       n += 2;
908       value >>>= 14;
909     }
910     if ((value & (~0L << 14)) != 0L) {
911       // Byte 3 or 7
912       n += 1;
913     }
914     return n;
915   }
916 
917   /** Writer that uses safe operations on target array. */
918   private static final class SafeHeapWriter extends BinaryWriter {
919     private AllocatedBuffer allocatedBuffer;
920     private byte[] buffer;
921     private int offset;
922     private int limit;
923     private int offsetMinusOne;
924     private int limitMinusOne;
925     private int pos;
926 
SafeHeapWriter(BufferAllocator alloc, int chunkSize)927     SafeHeapWriter(BufferAllocator alloc, int chunkSize) {
928       super(alloc, chunkSize);
929       nextBuffer();
930     }
931 
932     @Override
finishCurrentBuffer()933     void finishCurrentBuffer() {
934       if (allocatedBuffer != null) {
935         totalDoneBytes += bytesWrittenToCurrentBuffer();
936         allocatedBuffer.position((pos - allocatedBuffer.arrayOffset()) + 1);
937         allocatedBuffer = null;
938         pos = 0;
939         limitMinusOne = 0;
940       }
941     }
942 
nextBuffer()943     private void nextBuffer() {
944       nextBuffer(newHeapBuffer());
945     }
946 
nextBuffer(int capacity)947     private void nextBuffer(int capacity) {
948       nextBuffer(newHeapBuffer(capacity));
949     }
950 
nextBuffer(AllocatedBuffer allocatedBuffer)951     private void nextBuffer(AllocatedBuffer allocatedBuffer) {
952       if (!allocatedBuffer.hasArray()) {
953         throw new RuntimeException("Allocator returned non-heap buffer");
954       }
955 
956       finishCurrentBuffer();
957 
958       buffers.addFirst(allocatedBuffer);
959 
960       this.allocatedBuffer = allocatedBuffer;
961       this.buffer = allocatedBuffer.array();
962       int arrayOffset = allocatedBuffer.arrayOffset();
963       this.limit = arrayOffset + allocatedBuffer.limit();
964       this.offset = arrayOffset + allocatedBuffer.position();
965       this.offsetMinusOne = offset - 1;
966       this.limitMinusOne = limit - 1;
967       this.pos = limitMinusOne;
968     }
969 
970     @Override
getTotalBytesWritten()971     public int getTotalBytesWritten() {
972       return totalDoneBytes + bytesWrittenToCurrentBuffer();
973     }
974 
bytesWrittenToCurrentBuffer()975     int bytesWrittenToCurrentBuffer() {
976       return limitMinusOne - pos;
977     }
978 
spaceLeft()979     int spaceLeft() {
980       return pos - offsetMinusOne;
981     }
982 
983     @Override
writeUInt32(int fieldNumber, int value)984     public void writeUInt32(int fieldNumber, int value) throws IOException {
985       requireSpace(MAX_VARINT32_SIZE * 2);
986       writeVarint32(value);
987       writeTag(fieldNumber, WIRETYPE_VARINT);
988     }
989 
990     @Override
writeInt32(int fieldNumber, int value)991     public void writeInt32(int fieldNumber, int value) throws IOException {
992       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
993       writeInt32(value);
994       writeTag(fieldNumber, WIRETYPE_VARINT);
995     }
996 
997     @Override
writeSInt32(int fieldNumber, int value)998     public void writeSInt32(int fieldNumber, int value) throws IOException {
999       requireSpace(MAX_VARINT32_SIZE * 2);
1000       writeSInt32(value);
1001       writeTag(fieldNumber, WIRETYPE_VARINT);
1002     }
1003 
1004     @Override
writeFixed32(int fieldNumber, int value)1005     public void writeFixed32(int fieldNumber, int value) throws IOException {
1006       requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
1007       writeFixed32(value);
1008       writeTag(fieldNumber, WIRETYPE_FIXED32);
1009     }
1010 
1011     @Override
writeUInt64(int fieldNumber, long value)1012     public void writeUInt64(int fieldNumber, long value) throws IOException {
1013       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
1014       writeVarint64(value);
1015       writeTag(fieldNumber, WIRETYPE_VARINT);
1016     }
1017 
1018     @Override
writeSInt64(int fieldNumber, long value)1019     public void writeSInt64(int fieldNumber, long value) throws IOException {
1020       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
1021       writeSInt64(value);
1022       writeTag(fieldNumber, WIRETYPE_VARINT);
1023     }
1024 
1025     @Override
writeFixed64(int fieldNumber, long value)1026     public void writeFixed64(int fieldNumber, long value) throws IOException {
1027       requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
1028       writeFixed64(value);
1029       writeTag(fieldNumber, WIRETYPE_FIXED64);
1030     }
1031 
1032     @Override
writeBool(int fieldNumber, boolean value)1033     public void writeBool(int fieldNumber, boolean value) throws IOException {
1034       requireSpace(MAX_VARINT32_SIZE + 1);
1035       write((byte) (value ? 1 : 0));
1036       writeTag(fieldNumber, WIRETYPE_VARINT);
1037     }
1038 
1039     @Override
writeString(int fieldNumber, String value)1040     public void writeString(int fieldNumber, String value) throws IOException {
1041       int prevBytes = getTotalBytesWritten();
1042       writeString(value);
1043       int length = getTotalBytesWritten() - prevBytes;
1044       requireSpace(2 * MAX_VARINT32_SIZE);
1045       writeVarint32(length);
1046       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1047     }
1048 
1049     @Override
writeBytes(int fieldNumber, ByteString value)1050     public void writeBytes(int fieldNumber, ByteString value) throws IOException {
1051       try {
1052         value.writeToReverse(this);
1053       } catch (IOException e) {
1054         // Should never happen since the writer does not throw.
1055         throw new RuntimeException(e);
1056       }
1057 
1058       requireSpace(MAX_VARINT32_SIZE * 2);
1059       writeVarint32(value.size());
1060       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1061     }
1062 
1063     @Override
writeMessage(int fieldNumber, Object value)1064     public void writeMessage(int fieldNumber, Object value) throws IOException {
1065       int prevBytes = getTotalBytesWritten();
1066       Protobuf.getInstance().writeTo(value, this);
1067       int length = getTotalBytesWritten() - prevBytes;
1068       requireSpace(MAX_VARINT32_SIZE * 2);
1069       writeVarint32(length);
1070       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1071     }
1072 
1073     @Override
writeMessage(int fieldNumber, Object value, Schema schema)1074     public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
1075       int prevBytes = getTotalBytesWritten();
1076       schema.writeTo(value, this);
1077       int length = getTotalBytesWritten() - prevBytes;
1078       requireSpace(MAX_VARINT32_SIZE * 2);
1079       writeVarint32(length);
1080       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1081     }
1082 
1083     @Override
writeGroup(int fieldNumber, Object value)1084     public void writeGroup(int fieldNumber, Object value) throws IOException {
1085       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1086       Protobuf.getInstance().writeTo(value, this);
1087       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1088     }
1089 
1090     @Override
writeGroup(int fieldNumber, Object value, Schema schema)1091     public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
1092       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1093       schema.writeTo(value, this);
1094       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1095     }
1096 
1097     @Override
writeStartGroup(int fieldNumber)1098     public void writeStartGroup(int fieldNumber) {
1099       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1100     }
1101 
1102     @Override
writeEndGroup(int fieldNumber)1103     public void writeEndGroup(int fieldNumber) {
1104       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1105     }
1106 
1107     @Override
writeInt32(int value)1108     void writeInt32(int value) {
1109       if (value >= 0) {
1110         writeVarint32(value);
1111       } else {
1112         writeVarint64(value);
1113       }
1114     }
1115 
1116     @Override
writeSInt32(int value)1117     void writeSInt32(int value) {
1118       writeVarint32(CodedOutputStream.encodeZigZag32(value));
1119     }
1120 
1121     @Override
writeSInt64(long value)1122     void writeSInt64(long value) {
1123       writeVarint64(CodedOutputStream.encodeZigZag64(value));
1124     }
1125 
1126     @Override
writeBool(boolean value)1127     void writeBool(boolean value) {
1128       write((byte) (value ? 1 : 0));
1129     }
1130 
1131     @Override
writeTag(int fieldNumber, int wireType)1132     void writeTag(int fieldNumber, int wireType) {
1133       writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
1134     }
1135 
1136     @Override
writeVarint32(int value)1137     void writeVarint32(int value) {
1138       if ((value & (~0 << 7)) == 0) {
1139         writeVarint32OneByte(value);
1140       } else if ((value & (~0 << 14)) == 0) {
1141         writeVarint32TwoBytes(value);
1142       } else if ((value & (~0 << 21)) == 0) {
1143         writeVarint32ThreeBytes(value);
1144       } else if ((value & (~0 << 28)) == 0) {
1145         writeVarint32FourBytes(value);
1146       } else {
1147         writeVarint32FiveBytes(value);
1148       }
1149     }
1150 
writeVarint32OneByte(int value)1151     private void writeVarint32OneByte(int value) {
1152       buffer[pos--] = (byte) value;
1153     }
1154 
writeVarint32TwoBytes(int value)1155     private void writeVarint32TwoBytes(int value) {
1156       buffer[pos--] = (byte) (value >>> 7);
1157       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1158     }
1159 
writeVarint32ThreeBytes(int value)1160     private void writeVarint32ThreeBytes(int value) {
1161       buffer[pos--] = (byte) (value >>> 14);
1162       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1163       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1164     }
1165 
writeVarint32FourBytes(int value)1166     private void writeVarint32FourBytes(int value) {
1167       buffer[pos--] = (byte) (value >>> 21);
1168       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1169       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1170       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1171     }
1172 
writeVarint32FiveBytes(int value)1173     private void writeVarint32FiveBytes(int value) {
1174       buffer[pos--] = (byte) (value >>> 28);
1175       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1176       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1177       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1178       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1179     }
1180 
1181     @Override
writeVarint64(long value)1182     void writeVarint64(long value) {
1183       switch (computeUInt64SizeNoTag(value)) {
1184         case 1:
1185           writeVarint64OneByte(value);
1186           break;
1187         case 2:
1188           writeVarint64TwoBytes(value);
1189           break;
1190         case 3:
1191           writeVarint64ThreeBytes(value);
1192           break;
1193         case 4:
1194           writeVarint64FourBytes(value);
1195           break;
1196         case 5:
1197           writeVarint64FiveBytes(value);
1198           break;
1199         case 6:
1200           writeVarint64SixBytes(value);
1201           break;
1202         case 7:
1203           writeVarint64SevenBytes(value);
1204           break;
1205         case 8:
1206           writeVarint64EightBytes(value);
1207           break;
1208         case 9:
1209           writeVarint64NineBytes(value);
1210           break;
1211         case 10:
1212           writeVarint64TenBytes(value);
1213           break;
1214       }
1215     }
1216 
writeVarint64OneByte(long value)1217     private void writeVarint64OneByte(long value) {
1218       buffer[pos--] = (byte) value;
1219     }
1220 
writeVarint64TwoBytes(long value)1221     private void writeVarint64TwoBytes(long value) {
1222       buffer[pos--] = (byte) (value >>> 7);
1223       buffer[pos--] = (byte) (((int) value & 0x7F) | 0x80);
1224     }
1225 
writeVarint64ThreeBytes(long value)1226     private void writeVarint64ThreeBytes(long value) {
1227       buffer[pos--] = (byte) (((int) value) >>> 14);
1228       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1229       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1230     }
1231 
writeVarint64FourBytes(long value)1232     private void writeVarint64FourBytes(long value) {
1233       buffer[pos--] = (byte) (value >>> 21);
1234       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1235       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1236       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1237     }
1238 
writeVarint64FiveBytes(long value)1239     private void writeVarint64FiveBytes(long value) {
1240       buffer[pos--] = (byte) (value >>> 28);
1241       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1242       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1243       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1244       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1245     }
1246 
writeVarint64SixBytes(long value)1247     private void writeVarint64SixBytes(long value) {
1248       buffer[pos--] = (byte) (value >>> 35);
1249       buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
1250       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1251       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1252       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1253       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1254     }
1255 
writeVarint64SevenBytes(long value)1256     private void writeVarint64SevenBytes(long value) {
1257       buffer[pos--] = (byte) (value >>> 42);
1258       buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
1259       buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
1260       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1261       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1262       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1263       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1264     }
1265 
writeVarint64EightBytes(long value)1266     private void writeVarint64EightBytes(long value) {
1267       buffer[pos--] = (byte) (value >>> 49);
1268       buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
1269       buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
1270       buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
1271       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1272       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1273       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1274       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1275     }
1276 
writeVarint64NineBytes(long value)1277     private void writeVarint64NineBytes(long value) {
1278       buffer[pos--] = (byte) (value >>> 56);
1279       buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80);
1280       buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
1281       buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
1282       buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
1283       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1284       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1285       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1286       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1287     }
1288 
writeVarint64TenBytes(long value)1289     private void writeVarint64TenBytes(long value) {
1290       buffer[pos--] = (byte) (value >>> 63);
1291       buffer[pos--] = (byte) (((value >>> 56) & 0x7F) | 0x80);
1292       buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80);
1293       buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
1294       buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
1295       buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
1296       buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
1297       buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
1298       buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
1299       buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
1300     }
1301 
1302     @Override
writeFixed32(int value)1303     void writeFixed32(int value) {
1304       buffer[pos--] = (byte) ((value >> 24) & 0xFF);
1305       buffer[pos--] = (byte) ((value >> 16) & 0xFF);
1306       buffer[pos--] = (byte) ((value >> 8) & 0xFF);
1307       buffer[pos--] = (byte) (value & 0xFF);
1308     }
1309 
1310     @Override
writeFixed64(long value)1311     void writeFixed64(long value) {
1312       buffer[pos--] = (byte) ((int) (value >> 56) & 0xFF);
1313       buffer[pos--] = (byte) ((int) (value >> 48) & 0xFF);
1314       buffer[pos--] = (byte) ((int) (value >> 40) & 0xFF);
1315       buffer[pos--] = (byte) ((int) (value >> 32) & 0xFF);
1316       buffer[pos--] = (byte) ((int) (value >> 24) & 0xFF);
1317       buffer[pos--] = (byte) ((int) (value >> 16) & 0xFF);
1318       buffer[pos--] = (byte) ((int) (value >> 8) & 0xFF);
1319       buffer[pos--] = (byte) ((int) (value) & 0xFF);
1320     }
1321 
1322     @Override
writeString(String in)1323     void writeString(String in) {
1324       // Request enough space to write the ASCII string.
1325       requireSpace(in.length());
1326 
1327       // We know the buffer is big enough...
1328       int i = in.length() - 1;
1329       // Set pos to the start of the ASCII string.
1330       pos -= i;
1331       // Designed to take advantage of
1332       // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination
1333       for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
1334         buffer[pos + i] = (byte) c;
1335       }
1336       if (i == -1) {
1337         // Move pos past the String.
1338         pos -= 1;
1339         return;
1340       }
1341       pos += i;
1342       for (char c; i >= 0; i--) {
1343         c = in.charAt(i);
1344         if (c < 0x80 && pos > offsetMinusOne) {
1345           buffer[pos--] = (byte) c;
1346         } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes
1347           buffer[pos--] = (byte) (0x80 | (0x3F & c));
1348           buffer[pos--] = (byte) ((0xF << 6) | (c >>> 6));
1349         } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
1350             && pos > (offset + 1)) {
1351           // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
1352           buffer[pos--] = (byte) (0x80 | (0x3F & c));
1353           buffer[pos--] = (byte) (0x80 | (0x3F & (c >>> 6)));
1354           buffer[pos--] = (byte) ((0xF << 5) | (c >>> 12));
1355         } else if (pos > (offset + 2)) {
1356           // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
1357           // four UTF-8 bytes
1358           char high = 0;
1359           if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
1360             throw new Utf8.UnpairedSurrogateException(i - 1, i);
1361           }
1362           i--;
1363           int codePoint = Character.toCodePoint(high, c);
1364           buffer[pos--] = (byte) (0x80 | (0x3F & codePoint));
1365           buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
1366           buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
1367           buffer[pos--] = (byte) ((0xF << 4) | (codePoint >>> 18));
1368         } else {
1369           // Buffer is full - allocate a new one and revisit the current character.
1370           requireSpace(i);
1371           i++;
1372         }
1373       }
1374     }
1375 
1376     @Override
write(byte value)1377     public void write(byte value) {
1378       buffer[pos--] = value;
1379     }
1380 
1381     @Override
write(byte[] value, int offset, int length)1382     public void write(byte[] value, int offset, int length) {
1383       if (spaceLeft() < length) {
1384         nextBuffer(length);
1385       }
1386 
1387       pos -= length;
1388       System.arraycopy(value, offset, buffer, pos + 1, length);
1389     }
1390 
1391     @Override
writeLazy(byte[] value, int offset, int length)1392     public void writeLazy(byte[] value, int offset, int length) {
1393       if (spaceLeft() < length) {
1394         // We consider the value to be immutable (likely the internals of a ByteString). Just
1395         // wrap it in a Netty buffer and add it to the output buffer.
1396         totalDoneBytes += length;
1397         buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
1398 
1399         // Advance the writer to the next buffer.
1400         // TODO(nathanmittler): Consider slicing if space available above some threshold.
1401         nextBuffer();
1402         return;
1403       }
1404 
1405       pos -= length;
1406       System.arraycopy(value, offset, buffer, pos + 1, length);
1407     }
1408 
1409     @Override
write(ByteBuffer value)1410     public void write(ByteBuffer value) {
1411       int length = value.remaining();
1412       if (spaceLeft() < length) {
1413         nextBuffer(length);
1414       }
1415 
1416       pos -= length;
1417       value.get(buffer, pos + 1, length);
1418     }
1419 
1420     @Override
writeLazy(ByteBuffer value)1421     public void writeLazy(ByteBuffer value) {
1422       int length = value.remaining();
1423       if (spaceLeft() < length) {
1424         // We consider the value to be immutable (likely the internals of a ByteString). Just
1425         // wrap it in a Netty buffer and add it to the output buffer.
1426         totalDoneBytes += length;
1427         buffers.addFirst(AllocatedBuffer.wrap(value));
1428 
1429         // Advance the writer to the next buffer.
1430         // TODO(nathanmittler): Consider slicing if space available above some threshold.
1431         nextBuffer();
1432       }
1433 
1434       pos -= length;
1435       value.get(buffer, pos + 1, length);
1436     }
1437 
1438     @Override
requireSpace(int size)1439     void requireSpace(int size) {
1440       if (spaceLeft() < size) {
1441         nextBuffer(size);
1442       }
1443     }
1444   }
1445 
1446   /** Writer that uses unsafe operations on a target array. */
1447   private static final class UnsafeHeapWriter extends BinaryWriter {
1448     private AllocatedBuffer allocatedBuffer;
1449     private byte[] buffer;
1450     private long offset;
1451     private long limit;
1452     private long offsetMinusOne;
1453     private long limitMinusOne;
1454     private long pos;
1455 
UnsafeHeapWriter(BufferAllocator alloc, int chunkSize)1456     UnsafeHeapWriter(BufferAllocator alloc, int chunkSize) {
1457       super(alloc, chunkSize);
1458       nextBuffer();
1459     }
1460 
1461     /** Indicates whether the required unsafe operations are supported on this platform. */
isSupported()1462     static boolean isSupported() {
1463       return UnsafeUtil.hasUnsafeArrayOperations();
1464     }
1465 
1466     @Override
finishCurrentBuffer()1467     void finishCurrentBuffer() {
1468       if (allocatedBuffer != null) {
1469         totalDoneBytes += bytesWrittenToCurrentBuffer();
1470         allocatedBuffer.position((arrayPos() - allocatedBuffer.arrayOffset()) + 1);
1471         allocatedBuffer = null;
1472         pos = 0;
1473         limitMinusOne = 0;
1474       }
1475     }
1476 
arrayPos()1477     private int arrayPos() {
1478       return (int) pos;
1479     }
1480 
nextBuffer()1481     private void nextBuffer() {
1482       nextBuffer(newHeapBuffer());
1483     }
1484 
nextBuffer(int capacity)1485     private void nextBuffer(int capacity) {
1486       nextBuffer(newHeapBuffer(capacity));
1487     }
1488 
nextBuffer(AllocatedBuffer allocatedBuffer)1489     private void nextBuffer(AllocatedBuffer allocatedBuffer) {
1490       if (!allocatedBuffer.hasArray()) {
1491         throw new RuntimeException("Allocator returned non-heap buffer");
1492       }
1493 
1494       finishCurrentBuffer();
1495       buffers.addFirst(allocatedBuffer);
1496 
1497       this.allocatedBuffer = allocatedBuffer;
1498       this.buffer = allocatedBuffer.array();
1499       int arrayOffset = allocatedBuffer.arrayOffset();
1500       this.limit = arrayOffset + allocatedBuffer.limit();
1501       this.offset = arrayOffset + allocatedBuffer.position();
1502       this.offsetMinusOne = offset - 1;
1503       this.limitMinusOne = limit - 1;
1504       this.pos = limitMinusOne;
1505     }
1506 
1507     @Override
getTotalBytesWritten()1508     public int getTotalBytesWritten() {
1509       return totalDoneBytes + bytesWrittenToCurrentBuffer();
1510     }
1511 
bytesWrittenToCurrentBuffer()1512     int bytesWrittenToCurrentBuffer() {
1513       return (int) (limitMinusOne - pos);
1514     }
1515 
spaceLeft()1516     int spaceLeft() {
1517       return (int) (pos - offsetMinusOne);
1518     }
1519 
1520     @Override
writeUInt32(int fieldNumber, int value)1521     public void writeUInt32(int fieldNumber, int value) {
1522       requireSpace(MAX_VARINT32_SIZE * 2);
1523       writeVarint32(value);
1524       writeTag(fieldNumber, WIRETYPE_VARINT);
1525     }
1526 
1527     @Override
writeInt32(int fieldNumber, int value)1528     public void writeInt32(int fieldNumber, int value) {
1529       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
1530       writeInt32(value);
1531       writeTag(fieldNumber, WIRETYPE_VARINT);
1532     }
1533 
1534     @Override
writeSInt32(int fieldNumber, int value)1535     public void writeSInt32(int fieldNumber, int value) {
1536       requireSpace(MAX_VARINT32_SIZE * 2);
1537       writeSInt32(value);
1538       writeTag(fieldNumber, WIRETYPE_VARINT);
1539     }
1540 
1541     @Override
writeFixed32(int fieldNumber, int value)1542     public void writeFixed32(int fieldNumber, int value) {
1543       requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
1544       writeFixed32(value);
1545       writeTag(fieldNumber, WIRETYPE_FIXED32);
1546     }
1547 
1548     @Override
writeUInt64(int fieldNumber, long value)1549     public void writeUInt64(int fieldNumber, long value) {
1550       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
1551       writeVarint64(value);
1552       writeTag(fieldNumber, WIRETYPE_VARINT);
1553     }
1554 
1555     @Override
writeSInt64(int fieldNumber, long value)1556     public void writeSInt64(int fieldNumber, long value) {
1557       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
1558       writeSInt64(value);
1559       writeTag(fieldNumber, WIRETYPE_VARINT);
1560     }
1561 
1562     @Override
writeFixed64(int fieldNumber, long value)1563     public void writeFixed64(int fieldNumber, long value) {
1564       requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
1565       writeFixed64(value);
1566       writeTag(fieldNumber, WIRETYPE_FIXED64);
1567     }
1568 
1569     @Override
writeBool(int fieldNumber, boolean value)1570     public void writeBool(int fieldNumber, boolean value) {
1571       requireSpace(MAX_VARINT32_SIZE + 1);
1572       write((byte) (value ? 1 : 0));
1573       writeTag(fieldNumber, WIRETYPE_VARINT);
1574     }
1575 
1576     @Override
writeString(int fieldNumber, String value)1577     public void writeString(int fieldNumber, String value) {
1578       int prevBytes = getTotalBytesWritten();
1579       writeString(value);
1580       int length = getTotalBytesWritten() - prevBytes;
1581       requireSpace(2 * MAX_VARINT32_SIZE);
1582       writeVarint32(length);
1583       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1584     }
1585 
1586     @Override
writeBytes(int fieldNumber, ByteString value)1587     public void writeBytes(int fieldNumber, ByteString value) {
1588       try {
1589         value.writeToReverse(this);
1590       } catch (IOException e) {
1591         // Should never happen since the writer does not throw.
1592         throw new RuntimeException(e);
1593       }
1594 
1595       requireSpace(MAX_VARINT32_SIZE * 2);
1596       writeVarint32(value.size());
1597       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1598     }
1599 
1600     @Override
writeMessage(int fieldNumber, Object value)1601     public void writeMessage(int fieldNumber, Object value) throws IOException {
1602       int prevBytes = getTotalBytesWritten();
1603       Protobuf.getInstance().writeTo(value, this);
1604       int length = getTotalBytesWritten() - prevBytes;
1605       requireSpace(MAX_VARINT32_SIZE * 2);
1606       writeVarint32(length);
1607       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1608     }
1609 
1610     @Override
writeMessage(int fieldNumber, Object value, Schema schema)1611     public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
1612       int prevBytes = getTotalBytesWritten();
1613       schema.writeTo(value, this);
1614       int length = getTotalBytesWritten() - prevBytes;
1615       requireSpace(MAX_VARINT32_SIZE * 2);
1616       writeVarint32(length);
1617       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
1618     }
1619 
1620     @Override
writeGroup(int fieldNumber, Object value)1621     public void writeGroup(int fieldNumber, Object value) throws IOException {
1622       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1623       Protobuf.getInstance().writeTo(value, this);
1624       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1625     }
1626 
1627     @Override
writeGroup(int fieldNumber, Object value, Schema schema)1628     public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
1629       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1630       schema.writeTo(value, this);
1631       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1632     }
1633 
1634     @Override
writeStartGroup(int fieldNumber)1635     public void writeStartGroup(int fieldNumber) {
1636       writeTag(fieldNumber, WIRETYPE_START_GROUP);
1637     }
1638 
1639     @Override
writeEndGroup(int fieldNumber)1640     public void writeEndGroup(int fieldNumber) {
1641       writeTag(fieldNumber, WIRETYPE_END_GROUP);
1642     }
1643 
1644     @Override
writeInt32(int value)1645     void writeInt32(int value) {
1646       if (value >= 0) {
1647         writeVarint32(value);
1648       } else {
1649         writeVarint64(value);
1650       }
1651     }
1652 
1653     @Override
writeSInt32(int value)1654     void writeSInt32(int value) {
1655       writeVarint32(CodedOutputStream.encodeZigZag32(value));
1656     }
1657 
1658     @Override
writeSInt64(long value)1659     void writeSInt64(long value) {
1660       writeVarint64(CodedOutputStream.encodeZigZag64(value));
1661     }
1662 
1663     @Override
writeBool(boolean value)1664     void writeBool(boolean value) {
1665       write((byte) (value ? 1 : 0));
1666     }
1667 
1668     @Override
writeTag(int fieldNumber, int wireType)1669     void writeTag(int fieldNumber, int wireType) {
1670       writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
1671     }
1672 
1673     @Override
writeVarint32(int value)1674     void writeVarint32(int value) {
1675       if ((value & (~0 << 7)) == 0) {
1676         writeVarint32OneByte(value);
1677       } else if ((value & (~0 << 14)) == 0) {
1678         writeVarint32TwoBytes(value);
1679       } else if ((value & (~0 << 21)) == 0) {
1680         writeVarint32ThreeBytes(value);
1681       } else if ((value & (~0 << 28)) == 0) {
1682         writeVarint32FourBytes(value);
1683       } else {
1684         writeVarint32FiveBytes(value);
1685       }
1686     }
1687 
writeVarint32OneByte(int value)1688     private void writeVarint32OneByte(int value) {
1689       UnsafeUtil.putByte(buffer, pos--, (byte) value);
1690     }
1691 
writeVarint32TwoBytes(int value)1692     private void writeVarint32TwoBytes(int value) {
1693       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7));
1694       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1695     }
1696 
writeVarint32ThreeBytes(int value)1697     private void writeVarint32ThreeBytes(int value) {
1698       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 14));
1699       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1700       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1701     }
1702 
writeVarint32FourBytes(int value)1703     private void writeVarint32FourBytes(int value) {
1704       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21));
1705       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1706       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1707       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1708     }
1709 
writeVarint32FiveBytes(int value)1710     private void writeVarint32FiveBytes(int value) {
1711       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28));
1712       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1713       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1714       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1715       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1716     }
1717 
1718     @Override
writeVarint64(long value)1719     void writeVarint64(long value) {
1720       switch (computeUInt64SizeNoTag(value)) {
1721         case 1:
1722           writeVarint64OneByte(value);
1723           break;
1724         case 2:
1725           writeVarint64TwoBytes(value);
1726           break;
1727         case 3:
1728           writeVarint64ThreeBytes(value);
1729           break;
1730         case 4:
1731           writeVarint64FourBytes(value);
1732           break;
1733         case 5:
1734           writeVarint64FiveBytes(value);
1735           break;
1736         case 6:
1737           writeVarint64SixBytes(value);
1738           break;
1739         case 7:
1740           writeVarint64SevenBytes(value);
1741           break;
1742         case 8:
1743           writeVarint64EightBytes(value);
1744           break;
1745         case 9:
1746           writeVarint64NineBytes(value);
1747           break;
1748         case 10:
1749           writeVarint64TenBytes(value);
1750           break;
1751       }
1752     }
1753 
writeVarint64OneByte(long value)1754     private void writeVarint64OneByte(long value) {
1755       UnsafeUtil.putByte(buffer, pos--, (byte) value);
1756     }
1757 
writeVarint64TwoBytes(long value)1758     private void writeVarint64TwoBytes(long value) {
1759       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7));
1760       UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value & 0x7F) | 0x80));
1761     }
1762 
writeVarint64ThreeBytes(long value)1763     private void writeVarint64ThreeBytes(long value) {
1764       UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value) >>> 14));
1765       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1766       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1767     }
1768 
writeVarint64FourBytes(long value)1769     private void writeVarint64FourBytes(long value) {
1770       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21));
1771       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1772       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1773       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1774     }
1775 
writeVarint64FiveBytes(long value)1776     private void writeVarint64FiveBytes(long value) {
1777       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28));
1778       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1779       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1780       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1781       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1782     }
1783 
writeVarint64SixBytes(long value)1784     private void writeVarint64SixBytes(long value) {
1785       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 35));
1786       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
1787       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1788       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1789       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1790       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1791     }
1792 
writeVarint64SevenBytes(long value)1793     private void writeVarint64SevenBytes(long value) {
1794       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 42));
1795       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
1796       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
1797       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1798       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1799       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1800       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1801     }
1802 
writeVarint64EightBytes(long value)1803     private void writeVarint64EightBytes(long value) {
1804       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 49));
1805       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
1806       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
1807       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
1808       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1809       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1810       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1811       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1812     }
1813 
writeVarint64NineBytes(long value)1814     private void writeVarint64NineBytes(long value) {
1815       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 56));
1816       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
1817       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
1818       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
1819       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
1820       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1821       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1822       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1823       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1824     }
1825 
writeVarint64TenBytes(long value)1826     private void writeVarint64TenBytes(long value) {
1827       UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 63));
1828       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
1829       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
1830       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
1831       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
1832       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
1833       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
1834       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
1835       UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
1836       UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
1837     }
1838 
1839     @Override
writeFixed32(int value)1840     void writeFixed32(int value) {
1841       UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 24) & 0xFF));
1842       UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 16) & 0xFF));
1843       UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 8) & 0xFF));
1844       UnsafeUtil.putByte(buffer, pos--, (byte) (value & 0xFF));
1845     }
1846 
1847     @Override
writeFixed64(long value)1848     void writeFixed64(long value) {
1849       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 56) & 0xFF));
1850       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 48) & 0xFF));
1851       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 40) & 0xFF));
1852       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 32) & 0xFF));
1853       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 24) & 0xFF));
1854       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 16) & 0xFF));
1855       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 8) & 0xFF));
1856       UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value) & 0xFF));
1857     }
1858 
1859     @Override
writeString(String in)1860     void writeString(String in) {
1861       // Request enough space to write the ASCII string.
1862       requireSpace(in.length());
1863 
1864       // We know the buffer is big enough...
1865       int i = in.length() - 1;
1866       // Set pos to the start of the ASCII string.
1867       // pos -= i;
1868       // Designed to take advantage of
1869       // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination
1870       for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
1871         UnsafeUtil.putByte(buffer, pos--, (byte) c);
1872       }
1873       if (i == -1) {
1874         // Move pos past the String.
1875         return;
1876       }
1877       for (char c; i >= 0; i--) {
1878         c = in.charAt(i);
1879         if (c < 0x80 && pos > offsetMinusOne) {
1880           UnsafeUtil.putByte(buffer, pos--, (byte) c);
1881         } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes
1882           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c)));
1883           UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 6) | (c >>> 6)));
1884         } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
1885             && pos > offset + 1) {
1886           // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
1887           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c)));
1888           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
1889           UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 5) | (c >>> 12)));
1890         } else if (pos > offset + 2) {
1891           // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
1892           // four UTF-8 bytes
1893           final char high;
1894           if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
1895             throw new Utf8.UnpairedSurrogateException(i - 1, i);
1896           }
1897           i--;
1898           int codePoint = Character.toCodePoint(high, c);
1899           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & codePoint)));
1900           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
1901           UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
1902           UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
1903         } else {
1904           // Buffer is full - allocate a new one and revisit the current character.
1905           requireSpace(i);
1906           i++;
1907         }
1908       }
1909     }
1910 
1911     @Override
write(byte value)1912     public void write(byte value) {
1913       UnsafeUtil.putByte(buffer, pos--, value);
1914     }
1915 
1916     @Override
write(byte[] value, int offset, int length)1917     public void write(byte[] value, int offset, int length) {
1918       if (offset < 0 || offset + length > value.length) {
1919         throw new ArrayIndexOutOfBoundsException(
1920             String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length));
1921       }
1922       requireSpace(length);
1923 
1924       pos -= length;
1925       System.arraycopy(value, offset, buffer, arrayPos() + 1, length);
1926     }
1927 
1928     @Override
writeLazy(byte[] value, int offset, int length)1929     public void writeLazy(byte[] value, int offset, int length) {
1930       if (offset < 0 || offset + length > value.length) {
1931         throw new ArrayIndexOutOfBoundsException(
1932             String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length));
1933       }
1934       if (spaceLeft() < length) {
1935         // We consider the value to be immutable (likely the internals of a ByteString). Just
1936         // wrap it in a Netty buffer and add it to the output buffer.
1937         totalDoneBytes += length;
1938         buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
1939 
1940         // Advance the writer to the next buffer.
1941         // TODO(nathanmittler): Consider slicing if space available above some threshold.
1942         nextBuffer();
1943         return;
1944       }
1945 
1946       pos -= length;
1947       System.arraycopy(value, offset, buffer, arrayPos() + 1, length);
1948     }
1949 
1950     @Override
write(ByteBuffer value)1951     public void write(ByteBuffer value) {
1952       int length = value.remaining();
1953       requireSpace(length);
1954 
1955       pos -= length;
1956       value.get(buffer, arrayPos() + 1, length);
1957     }
1958 
1959     @Override
writeLazy(ByteBuffer value)1960     public void writeLazy(ByteBuffer value) {
1961       int length = value.remaining();
1962       if (spaceLeft() < length) {
1963         // We consider the value to be immutable (likely the internals of a ByteString). Just
1964         // wrap it in a Netty buffer and add it to the output buffer.
1965         totalDoneBytes += length;
1966         buffers.addFirst(AllocatedBuffer.wrap(value));
1967 
1968         // Advance the writer to the next buffer.
1969         // TODO(nathanmittler): Consider slicing if space available above some threshold.
1970         nextBuffer();
1971       }
1972 
1973       pos -= length;
1974       value.get(buffer, arrayPos() + 1, length);
1975     }
1976 
1977     @Override
requireSpace(int size)1978     void requireSpace(int size) {
1979       if (spaceLeft() < size) {
1980         nextBuffer(size);
1981       }
1982     }
1983   }
1984 
1985   /** Writer that uses safe operations on a target {@link ByteBuffer}. */
1986   private static final class SafeDirectWriter extends BinaryWriter {
1987     private ByteBuffer buffer;
1988     private int limitMinusOne;
1989     private int pos;
1990 
SafeDirectWriter(BufferAllocator alloc, int chunkSize)1991     SafeDirectWriter(BufferAllocator alloc, int chunkSize) {
1992       super(alloc, chunkSize);
1993       nextBuffer();
1994     }
1995 
nextBuffer()1996     private void nextBuffer() {
1997       nextBuffer(newDirectBuffer());
1998     }
1999 
nextBuffer(int capacity)2000     private void nextBuffer(int capacity) {
2001       nextBuffer(newDirectBuffer(capacity));
2002     }
2003 
nextBuffer(AllocatedBuffer allocatedBuffer)2004     private void nextBuffer(AllocatedBuffer allocatedBuffer) {
2005       if (!allocatedBuffer.hasNioBuffer()) {
2006         throw new RuntimeException("Allocated buffer does not have NIO buffer");
2007       }
2008       ByteBuffer nioBuffer = allocatedBuffer.nioBuffer();
2009       if (!nioBuffer.isDirect()) {
2010         throw new RuntimeException("Allocator returned non-direct buffer");
2011       }
2012 
2013       finishCurrentBuffer();
2014       buffers.addFirst(allocatedBuffer);
2015 
2016       buffer = nioBuffer;
2017       buffer.limit(buffer.capacity());
2018       buffer.position(0);
2019       // Set byte order to little endian for fast writing of fixed 32/64.
2020       buffer.order(ByteOrder.LITTLE_ENDIAN);
2021 
2022       limitMinusOne = buffer.limit() - 1;
2023       pos = limitMinusOne;
2024     }
2025 
2026     @Override
getTotalBytesWritten()2027     public int getTotalBytesWritten() {
2028       return totalDoneBytes + bytesWrittenToCurrentBuffer();
2029     }
2030 
bytesWrittenToCurrentBuffer()2031     private int bytesWrittenToCurrentBuffer() {
2032       return limitMinusOne - pos;
2033     }
2034 
spaceLeft()2035     private int spaceLeft() {
2036       return pos + 1;
2037     }
2038 
2039     @Override
finishCurrentBuffer()2040     void finishCurrentBuffer() {
2041       if (buffer != null) {
2042         totalDoneBytes += bytesWrittenToCurrentBuffer();
2043         // Update the indices on the netty buffer.
2044         buffer.position(pos + 1);
2045         buffer = null;
2046         pos = 0;
2047         limitMinusOne = 0;
2048       }
2049     }
2050 
2051     @Override
writeUInt32(int fieldNumber, int value)2052     public void writeUInt32(int fieldNumber, int value) {
2053       requireSpace(MAX_VARINT32_SIZE * 2);
2054       writeVarint32(value);
2055       writeTag(fieldNumber, WIRETYPE_VARINT);
2056     }
2057 
2058     @Override
writeInt32(int fieldNumber, int value)2059     public void writeInt32(int fieldNumber, int value) {
2060       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2061       writeInt32(value);
2062       writeTag(fieldNumber, WIRETYPE_VARINT);
2063     }
2064 
2065     @Override
writeSInt32(int fieldNumber, int value)2066     public void writeSInt32(int fieldNumber, int value) {
2067       requireSpace(MAX_VARINT32_SIZE * 2);
2068       writeSInt32(value);
2069       writeTag(fieldNumber, WIRETYPE_VARINT);
2070     }
2071 
2072     @Override
writeFixed32(int fieldNumber, int value)2073     public void writeFixed32(int fieldNumber, int value) {
2074       requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
2075       writeFixed32(value);
2076       writeTag(fieldNumber, WIRETYPE_FIXED32);
2077     }
2078 
2079     @Override
writeUInt64(int fieldNumber, long value)2080     public void writeUInt64(int fieldNumber, long value) {
2081       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2082       writeVarint64(value);
2083       writeTag(fieldNumber, WIRETYPE_VARINT);
2084     }
2085 
2086     @Override
writeSInt64(int fieldNumber, long value)2087     public void writeSInt64(int fieldNumber, long value) {
2088       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2089       writeSInt64(value);
2090       writeTag(fieldNumber, WIRETYPE_VARINT);
2091     }
2092 
2093     @Override
writeFixed64(int fieldNumber, long value)2094     public void writeFixed64(int fieldNumber, long value) {
2095       requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
2096       writeFixed64(value);
2097       writeTag(fieldNumber, WIRETYPE_FIXED64);
2098     }
2099 
2100     @Override
writeBool(int fieldNumber, boolean value)2101     public void writeBool(int fieldNumber, boolean value) {
2102       requireSpace(MAX_VARINT32_SIZE + 1);
2103       write((byte) (value ? 1 : 0));
2104       writeTag(fieldNumber, WIRETYPE_VARINT);
2105     }
2106 
2107     @Override
writeString(int fieldNumber, String value)2108     public void writeString(int fieldNumber, String value) {
2109       int prevBytes = getTotalBytesWritten();
2110       writeString(value);
2111       int length = getTotalBytesWritten() - prevBytes;
2112       requireSpace(2 * MAX_VARINT32_SIZE);
2113       writeVarint32(length);
2114       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2115     }
2116 
2117     @Override
writeBytes(int fieldNumber, ByteString value)2118     public void writeBytes(int fieldNumber, ByteString value) {
2119       try {
2120         value.writeToReverse(this);
2121       } catch (IOException e) {
2122         // Should never happen since the writer does not throw.
2123         throw new RuntimeException(e);
2124       }
2125 
2126       requireSpace(MAX_VARINT32_SIZE * 2);
2127       writeVarint32(value.size());
2128       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2129     }
2130 
2131     @Override
writeMessage(int fieldNumber, Object value)2132     public void writeMessage(int fieldNumber, Object value) throws IOException {
2133       int prevBytes = getTotalBytesWritten();
2134       Protobuf.getInstance().writeTo(value, this);
2135       int length = getTotalBytesWritten() - prevBytes;
2136       requireSpace(MAX_VARINT32_SIZE * 2);
2137       writeVarint32(length);
2138       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2139     }
2140 
2141     @Override
writeMessage(int fieldNumber, Object value, Schema schema)2142     public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
2143       int prevBytes = getTotalBytesWritten();
2144       schema.writeTo(value, this);
2145       int length = getTotalBytesWritten() - prevBytes;
2146       requireSpace(MAX_VARINT32_SIZE * 2);
2147       writeVarint32(length);
2148       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2149     }
2150 
2151     @Override
writeGroup(int fieldNumber, Object value)2152     public void writeGroup(int fieldNumber, Object value) throws IOException {
2153       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2154       Protobuf.getInstance().writeTo(value, this);
2155       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2156     }
2157 
2158     @Override
writeGroup(int fieldNumber, Object value, Schema schema)2159     public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
2160       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2161       schema.writeTo(value, this);
2162       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2163     }
2164 
2165     @Override
writeStartGroup(int fieldNumber)2166     public void writeStartGroup(int fieldNumber) {
2167       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2168     }
2169 
2170     @Override
writeEndGroup(int fieldNumber)2171     public void writeEndGroup(int fieldNumber) {
2172       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2173     }
2174 
2175     @Override
writeInt32(int value)2176     void writeInt32(int value) {
2177       if (value >= 0) {
2178         writeVarint32(value);
2179       } else {
2180         writeVarint64(value);
2181       }
2182     }
2183 
2184     @Override
writeSInt32(int value)2185     void writeSInt32(int value) {
2186       writeVarint32(CodedOutputStream.encodeZigZag32(value));
2187     }
2188 
2189     @Override
writeSInt64(long value)2190     void writeSInt64(long value) {
2191       writeVarint64(CodedOutputStream.encodeZigZag64(value));
2192     }
2193 
2194     @Override
writeBool(boolean value)2195     void writeBool(boolean value) {
2196       write((byte) (value ? 1 : 0));
2197     }
2198 
2199     @Override
writeTag(int fieldNumber, int wireType)2200     void writeTag(int fieldNumber, int wireType) {
2201       writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
2202     }
2203 
2204     @Override
writeVarint32(int value)2205     void writeVarint32(int value) {
2206       if ((value & (~0 << 7)) == 0) {
2207         writeVarint32OneByte(value);
2208       } else if ((value & (~0 << 14)) == 0) {
2209         writeVarint32TwoBytes(value);
2210       } else if ((value & (~0 << 21)) == 0) {
2211         writeVarint32ThreeBytes(value);
2212       } else if ((value & (~0 << 28)) == 0) {
2213         writeVarint32FourBytes(value);
2214       } else {
2215         writeVarint32FiveBytes(value);
2216       }
2217     }
2218 
writeVarint32OneByte(int value)2219     private void writeVarint32OneByte(int value) {
2220       buffer.put(pos--, (byte) value);
2221     }
2222 
writeVarint32TwoBytes(int value)2223     private void writeVarint32TwoBytes(int value) {
2224       // Byte order is little-endian.
2225       pos -= 2;
2226       buffer.putShort(pos + 1, (short) (((value & (0x7F << 7)) << 1) | ((value & 0x7F) | 0x80)));
2227     }
2228 
writeVarint32ThreeBytes(int value)2229     private void writeVarint32ThreeBytes(int value) {
2230       // Byte order is little-endian.
2231       pos -= 3;
2232       buffer.putInt(
2233           pos,
2234           ((value & (0x7F << 14)) << 10)
2235               | (((value & (0x7F << 7)) | (0x80 << 7)) << 9)
2236               | ((value & 0x7F) | 0x80) << 8);
2237     }
2238 
writeVarint32FourBytes(int value)2239     private void writeVarint32FourBytes(int value) {
2240       // Byte order is little-endian.
2241       pos -= 4;
2242       buffer.putInt(
2243           pos + 1,
2244           ((value & (0x7F << 21)) << 3)
2245               | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
2246               | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
2247               | ((value & 0x7F) | 0x80));
2248     }
2249 
writeVarint32FiveBytes(int value)2250     private void writeVarint32FiveBytes(int value) {
2251       // Byte order is little-endian.
2252       buffer.put(pos--, (byte) (value >>> 28));
2253       pos -= 4;
2254       buffer.putInt(
2255           pos + 1,
2256           ((((value >>> 21) & 0x7F) | 0x80) << 24)
2257               | ((((value >>> 14) & 0x7F) | 0x80) << 16)
2258               | ((((value >>> 7) & 0x7F) | 0x80) << 8)
2259               | ((value & 0x7F) | 0x80));
2260     }
2261 
2262     @Override
writeVarint64(long value)2263     void writeVarint64(long value) {
2264       switch (computeUInt64SizeNoTag(value)) {
2265         case 1:
2266           writeVarint64OneByte(value);
2267           break;
2268         case 2:
2269           writeVarint64TwoBytes(value);
2270           break;
2271         case 3:
2272           writeVarint64ThreeBytes(value);
2273           break;
2274         case 4:
2275           writeVarint64FourBytes(value);
2276           break;
2277         case 5:
2278           writeVarint64FiveBytes(value);
2279           break;
2280         case 6:
2281           writeVarint64SixBytes(value);
2282           break;
2283         case 7:
2284           writeVarint64SevenBytes(value);
2285           break;
2286         case 8:
2287           writeVarint64EightBytes(value);
2288           break;
2289         case 9:
2290           writeVarint64NineBytes(value);
2291           break;
2292         case 10:
2293           writeVarint64TenBytes(value);
2294           break;
2295       }
2296     }
2297 
writeVarint64OneByte(long value)2298     private void writeVarint64OneByte(long value) {
2299       writeVarint32OneByte((int) value);
2300     }
2301 
writeVarint64TwoBytes(long value)2302     private void writeVarint64TwoBytes(long value) {
2303       writeVarint32TwoBytes((int) value);
2304     }
2305 
writeVarint64ThreeBytes(long value)2306     private void writeVarint64ThreeBytes(long value) {
2307       writeVarint32ThreeBytes((int) value);
2308     }
2309 
writeVarint64FourBytes(long value)2310     private void writeVarint64FourBytes(long value) {
2311       writeVarint32FourBytes((int) value);
2312     }
2313 
writeVarint64FiveBytes(long value)2314     private void writeVarint64FiveBytes(long value) {
2315       // Byte order is little-endian.
2316       pos -= 5;
2317       buffer.putLong(
2318           pos - 2,
2319           ((value & (0x7FL << 28)) << 28)
2320               | (((value & (0x7F << 21)) | (0x80 << 21)) << 27)
2321               | (((value & (0x7F << 14)) | (0x80 << 14)) << 26)
2322               | (((value & (0x7F << 7)) | (0x80 << 7)) << 25)
2323               | (((value & 0x7F) | 0x80)) << 24);
2324     }
2325 
writeVarint64SixBytes(long value)2326     private void writeVarint64SixBytes(long value) {
2327       // Byte order is little-endian.
2328       pos -= 6;
2329       buffer.putLong(
2330           pos - 1,
2331           ((value & (0x7FL << 35)) << 21)
2332               | (((value & (0x7FL << 28)) | (0x80L << 28)) << 20)
2333               | (((value & (0x7F << 21)) | (0x80 << 21)) << 19)
2334               | (((value & (0x7F << 14)) | (0x80 << 14)) << 18)
2335               | (((value & (0x7F << 7)) | (0x80 << 7)) << 17)
2336               | (((value & 0x7F) | 0x80)) << 16);
2337     }
2338 
writeVarint64SevenBytes(long value)2339     private void writeVarint64SevenBytes(long value) {
2340       // Byte order is little-endian.
2341       pos -= 7;
2342       buffer.putLong(
2343           pos,
2344           ((value & (0x7FL << 42)) << 14)
2345               | (((value & (0x7FL << 35)) | (0x80L << 35)) << 13)
2346               | (((value & (0x7FL << 28)) | (0x80L << 28)) << 12)
2347               | (((value & (0x7F << 21)) | (0x80 << 21)) << 11)
2348               | (((value & (0x7F << 14)) | (0x80 << 14)) << 10)
2349               | (((value & (0x7F << 7)) | (0x80 << 7)) << 9)
2350               | (((value & 0x7F) | 0x80)) << 8);
2351     }
2352 
writeVarint64EightBytes(long value)2353     private void writeVarint64EightBytes(long value) {
2354       // Byte order is little-endian.
2355       pos -= 8;
2356       buffer.putLong(
2357           pos + 1,
2358           ((value & (0x7FL << 49)) << 7)
2359               | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6)
2360               | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5)
2361               | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4)
2362               | (((value & (0x7F << 21)) | (0x80 << 21)) << 3)
2363               | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
2364               | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
2365               | ((value & 0x7F) | 0x80));
2366     }
2367 
writeVarint64EightBytesWithSign(long value)2368     private void writeVarint64EightBytesWithSign(long value) {
2369       // Byte order is little-endian.
2370       pos -= 8;
2371       buffer.putLong(
2372           pos + 1,
2373           (((value & (0x7FL << 49)) | (0x80L << 49)) << 7)
2374               | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6)
2375               | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5)
2376               | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4)
2377               | (((value & (0x7F << 21)) | (0x80 << 21)) << 3)
2378               | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
2379               | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
2380               | ((value & 0x7F) | 0x80));
2381     }
2382 
writeVarint64NineBytes(long value)2383     private void writeVarint64NineBytes(long value) {
2384       buffer.put(pos--, (byte) (value >>> 56));
2385       writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL);
2386     }
2387 
writeVarint64TenBytes(long value)2388     private void writeVarint64TenBytes(long value) {
2389       buffer.put(pos--, (byte) (value >>> 63));
2390       buffer.put(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
2391       writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL);
2392     }
2393 
2394     @Override
writeFixed32(int value)2395     void writeFixed32(int value) {
2396       pos -= 4;
2397       buffer.putInt(pos + 1, value);
2398     }
2399 
2400     @Override
writeFixed64(long value)2401     void writeFixed64(long value) {
2402       pos -= 8;
2403       buffer.putLong(pos + 1, value);
2404     }
2405 
2406     @Override
writeString(String in)2407     void writeString(String in) {
2408       // Request enough space to write the ASCII string.
2409       requireSpace(in.length());
2410 
2411       // We know the buffer is big enough...
2412       int i = in.length() - 1;
2413       pos -= i;
2414       // Designed to take advantage of
2415       // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination
2416       for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
2417         buffer.put(pos + i, (byte) c);
2418       }
2419       if (i == -1) {
2420         // Move the position past the ASCII string.
2421         pos -= 1;
2422         return;
2423       }
2424       pos += i;
2425       for (char c; i >= 0; i--) {
2426         c = in.charAt(i);
2427         if (c < 0x80 && pos >= 0) {
2428           buffer.put(pos--, (byte) c);
2429         } else if (c < 0x800 && pos > 0) { // 11 bits, two UTF-8 bytes
2430           buffer.put(pos--, (byte) (0x80 | (0x3F & c)));
2431           buffer.put(pos--, (byte) ((0xF << 6) | (c >>> 6)));
2432         } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && pos > 1) {
2433           // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
2434           buffer.put(pos--, (byte) (0x80 | (0x3F & c)));
2435           buffer.put(pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
2436           buffer.put(pos--, (byte) ((0xF << 5) | (c >>> 12)));
2437         } else if (pos > 2) {
2438           // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
2439           // four UTF-8 bytes
2440           char high = 0;
2441           if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
2442             throw new Utf8.UnpairedSurrogateException(i - 1, i);
2443           }
2444           i--;
2445           int codePoint = Character.toCodePoint(high, c);
2446           buffer.put(pos--, (byte) (0x80 | (0x3F & codePoint)));
2447           buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
2448           buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
2449           buffer.put(pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
2450         } else {
2451           // Buffer is full - allocate a new one and revisit the current character.
2452           requireSpace(i);
2453           i++;
2454         }
2455       }
2456     }
2457 
2458     @Override
write(byte value)2459     public void write(byte value) {
2460       buffer.put(pos--, value);
2461     }
2462 
2463     @Override
write(byte[] value, int offset, int length)2464     public void write(byte[] value, int offset, int length) {
2465       if (spaceLeft() < length) {
2466         nextBuffer(length);
2467       }
2468 
2469       pos -= length;
2470       buffer.position(pos + 1);
2471       buffer.put(value, offset, length);
2472     }
2473 
2474     @Override
writeLazy(byte[] value, int offset, int length)2475     public void writeLazy(byte[] value, int offset, int length) {
2476       if (spaceLeft() < length) {
2477         // We consider the value to be immutable (likely the internals of a ByteString). Just
2478         // wrap it in a Netty buffer and add it to the output buffer.
2479         totalDoneBytes += length;
2480         buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
2481 
2482         // Advance the writer to the next buffer.
2483         // TODO(nathanmittler): Consider slicing if space available above some threshold.
2484         nextBuffer();
2485         return;
2486       }
2487 
2488       pos -= length;
2489       buffer.position(pos + 1);
2490       buffer.put(value, offset, length);
2491     }
2492 
2493     @Override
write(ByteBuffer value)2494     public void write(ByteBuffer value) {
2495       int length = value.remaining();
2496       if (spaceLeft() < length) {
2497         nextBuffer(length);
2498       }
2499 
2500       pos -= length;
2501       buffer.position(pos + 1);
2502       buffer.put(value);
2503     }
2504 
2505     @Override
writeLazy(ByteBuffer value)2506     public void writeLazy(ByteBuffer value) {
2507       int length = value.remaining();
2508       if (spaceLeft() < length) {
2509         // We consider the value to be immutable (likely the internals of a ByteString). Just
2510         // wrap it in a Netty buffer and add it to the output buffer.
2511         totalDoneBytes += length;
2512         buffers.addFirst(AllocatedBuffer.wrap(value));
2513 
2514         // Advance the writer to the next buffer.
2515         // TODO(nathanmittler): Consider slicing if space available above some threshold.
2516         nextBuffer();
2517         return;
2518       }
2519 
2520       pos -= length;
2521       buffer.position(pos + 1);
2522       buffer.put(value);
2523     }
2524 
2525     @Override
requireSpace(int size)2526     void requireSpace(int size) {
2527       if (spaceLeft() < size) {
2528         nextBuffer(size);
2529       }
2530     }
2531   }
2532 
2533   /** Writer that uses unsafe operations on a target {@link ByteBuffer}. */
2534   private static final class UnsafeDirectWriter extends BinaryWriter {
2535     private ByteBuffer buffer;
2536     private long bufferOffset;
2537     private long limitMinusOne;
2538     private long pos;
2539 
UnsafeDirectWriter(BufferAllocator alloc, int chunkSize)2540     UnsafeDirectWriter(BufferAllocator alloc, int chunkSize) {
2541       super(alloc, chunkSize);
2542       nextBuffer();
2543     }
2544 
2545     /** Indicates whether the required unsafe operations are supported on this platform. */
isSupported()2546     private static boolean isSupported() {
2547       return UnsafeUtil.hasUnsafeByteBufferOperations();
2548     }
2549 
nextBuffer()2550     private void nextBuffer() {
2551       nextBuffer(newDirectBuffer());
2552     }
2553 
nextBuffer(int capacity)2554     private void nextBuffer(int capacity) {
2555       nextBuffer(newDirectBuffer(capacity));
2556     }
2557 
nextBuffer(AllocatedBuffer allocatedBuffer)2558     private void nextBuffer(AllocatedBuffer allocatedBuffer) {
2559       if (!allocatedBuffer.hasNioBuffer()) {
2560         throw new RuntimeException("Allocated buffer does not have NIO buffer");
2561       }
2562       ByteBuffer nioBuffer = allocatedBuffer.nioBuffer();
2563       if (!nioBuffer.isDirect()) {
2564         throw new RuntimeException("Allocator returned non-direct buffer");
2565       }
2566 
2567       finishCurrentBuffer();
2568       buffers.addFirst(allocatedBuffer);
2569 
2570       buffer = nioBuffer;
2571       buffer.limit(buffer.capacity());
2572       buffer.position(0);
2573 
2574       bufferOffset = UnsafeUtil.addressOffset(buffer);
2575       limitMinusOne = bufferOffset + (buffer.limit() - 1);
2576       pos = limitMinusOne;
2577     }
2578 
2579     @Override
getTotalBytesWritten()2580     public int getTotalBytesWritten() {
2581       return totalDoneBytes + bytesWrittenToCurrentBuffer();
2582     }
2583 
bytesWrittenToCurrentBuffer()2584     private int bytesWrittenToCurrentBuffer() {
2585       return (int) (limitMinusOne - pos);
2586     }
2587 
spaceLeft()2588     private int spaceLeft() {
2589       return bufferPos() + 1;
2590     }
2591 
2592     @Override
finishCurrentBuffer()2593     void finishCurrentBuffer() {
2594       if (buffer != null) {
2595         totalDoneBytes += bytesWrittenToCurrentBuffer();
2596         // Update the indices on the netty buffer.
2597         buffer.position(bufferPos() + 1);
2598         buffer = null;
2599         pos = 0;
2600         limitMinusOne = 0;
2601       }
2602     }
2603 
bufferPos()2604     private int bufferPos() {
2605       return (int) (pos - bufferOffset);
2606     }
2607 
2608     @Override
writeUInt32(int fieldNumber, int value)2609     public void writeUInt32(int fieldNumber, int value) {
2610       requireSpace(MAX_VARINT32_SIZE * 2);
2611       writeVarint32(value);
2612       writeTag(fieldNumber, WIRETYPE_VARINT);
2613     }
2614 
2615     @Override
writeInt32(int fieldNumber, int value)2616     public void writeInt32(int fieldNumber, int value) {
2617       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2618       writeInt32(value);
2619       writeTag(fieldNumber, WIRETYPE_VARINT);
2620     }
2621 
2622     @Override
writeSInt32(int fieldNumber, int value)2623     public void writeSInt32(int fieldNumber, int value) {
2624       requireSpace(MAX_VARINT32_SIZE * 2);
2625       writeSInt32(value);
2626       writeTag(fieldNumber, WIRETYPE_VARINT);
2627     }
2628 
2629     @Override
writeFixed32(int fieldNumber, int value)2630     public void writeFixed32(int fieldNumber, int value) {
2631       requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
2632       writeFixed32(value);
2633       writeTag(fieldNumber, WIRETYPE_FIXED32);
2634     }
2635 
2636     @Override
writeUInt64(int fieldNumber, long value)2637     public void writeUInt64(int fieldNumber, long value) {
2638       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2639       writeVarint64(value);
2640       writeTag(fieldNumber, WIRETYPE_VARINT);
2641     }
2642 
2643     @Override
writeSInt64(int fieldNumber, long value)2644     public void writeSInt64(int fieldNumber, long value) {
2645       requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
2646       writeSInt64(value);
2647       writeTag(fieldNumber, WIRETYPE_VARINT);
2648     }
2649 
2650     @Override
writeFixed64(int fieldNumber, long value)2651     public void writeFixed64(int fieldNumber, long value) {
2652       requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
2653       writeFixed64(value);
2654       writeTag(fieldNumber, WIRETYPE_FIXED64);
2655     }
2656 
2657     @Override
writeBool(int fieldNumber, boolean value)2658     public void writeBool(int fieldNumber, boolean value) {
2659       requireSpace(MAX_VARINT32_SIZE + 1);
2660       write((byte) (value ? 1 : 0));
2661       writeTag(fieldNumber, WIRETYPE_VARINT);
2662     }
2663 
2664     @Override
writeString(int fieldNumber, String value)2665     public void writeString(int fieldNumber, String value) {
2666       int prevBytes = getTotalBytesWritten();
2667       writeString(value);
2668       int length = getTotalBytesWritten() - prevBytes;
2669       requireSpace(2 * MAX_VARINT32_SIZE);
2670       writeVarint32(length);
2671       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2672     }
2673 
2674     @Override
writeBytes(int fieldNumber, ByteString value)2675     public void writeBytes(int fieldNumber, ByteString value) {
2676       try {
2677         value.writeToReverse(this);
2678       } catch (IOException e) {
2679         // Should never happen since the writer does not throw.
2680         throw new RuntimeException(e);
2681       }
2682 
2683       requireSpace(MAX_VARINT32_SIZE * 2);
2684       writeVarint32(value.size());
2685       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2686     }
2687 
2688     @Override
writeMessage(int fieldNumber, Object value)2689     public void writeMessage(int fieldNumber, Object value) throws IOException {
2690       int prevBytes = getTotalBytesWritten();
2691       Protobuf.getInstance().writeTo(value, this);
2692       int length = getTotalBytesWritten() - prevBytes;
2693       requireSpace(MAX_VARINT32_SIZE * 2);
2694       writeVarint32(length);
2695       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2696     }
2697 
2698     @Override
writeMessage(int fieldNumber, Object value, Schema schema)2699     public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
2700       int prevBytes = getTotalBytesWritten();
2701       schema.writeTo(value, this);
2702       int length = getTotalBytesWritten() - prevBytes;
2703       requireSpace(MAX_VARINT32_SIZE * 2);
2704       writeVarint32(length);
2705       writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2706     }
2707 
2708     @Override
writeGroup(int fieldNumber, Object value)2709     public void writeGroup(int fieldNumber, Object value) throws IOException {
2710       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2711       Protobuf.getInstance().writeTo(value, this);
2712       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2713     }
2714 
2715     @Override
writeGroup(int fieldNumber, Object value, Schema schema)2716     public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
2717       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2718       schema.writeTo(value, this);
2719       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2720     }
2721 
2722     @Override
writeStartGroup(int fieldNumber)2723     public void writeStartGroup(int fieldNumber) {
2724       writeTag(fieldNumber, WIRETYPE_START_GROUP);
2725     }
2726 
2727     @Override
writeEndGroup(int fieldNumber)2728     public void writeEndGroup(int fieldNumber) {
2729       writeTag(fieldNumber, WIRETYPE_END_GROUP);
2730     }
2731 
2732     @Override
writeInt32(int value)2733     void writeInt32(int value) {
2734       if (value >= 0) {
2735         writeVarint32(value);
2736       } else {
2737         writeVarint64(value);
2738       }
2739     }
2740 
2741     @Override
writeSInt32(int value)2742     void writeSInt32(int value) {
2743       writeVarint32(CodedOutputStream.encodeZigZag32(value));
2744     }
2745 
2746     @Override
writeSInt64(long value)2747     void writeSInt64(long value) {
2748       writeVarint64(CodedOutputStream.encodeZigZag64(value));
2749     }
2750 
2751     @Override
writeBool(boolean value)2752     void writeBool(boolean value) {
2753       write((byte) (value ? 1 : 0));
2754     }
2755 
2756     @Override
writeTag(int fieldNumber, int wireType)2757     void writeTag(int fieldNumber, int wireType) {
2758       writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
2759     }
2760 
2761     @Override
writeVarint32(int value)2762     void writeVarint32(int value) {
2763       if ((value & (~0 << 7)) == 0) {
2764         writeVarint32OneByte(value);
2765       } else if ((value & (~0 << 14)) == 0) {
2766         writeVarint32TwoBytes(value);
2767       } else if ((value & (~0 << 21)) == 0) {
2768         writeVarint32ThreeBytes(value);
2769       } else if ((value & (~0 << 28)) == 0) {
2770         writeVarint32FourBytes(value);
2771       } else {
2772         writeVarint32FiveBytes(value);
2773       }
2774     }
2775 
writeVarint32OneByte(int value)2776     private void writeVarint32OneByte(int value) {
2777       UnsafeUtil.putByte(pos--, (byte) value);
2778     }
2779 
writeVarint32TwoBytes(int value)2780     private void writeVarint32TwoBytes(int value) {
2781       UnsafeUtil.putByte(pos--, (byte) (value >>> 7));
2782       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2783     }
2784 
writeVarint32ThreeBytes(int value)2785     private void writeVarint32ThreeBytes(int value) {
2786       UnsafeUtil.putByte(pos--, (byte) (value >>> 14));
2787       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2788       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2789     }
2790 
writeVarint32FourBytes(int value)2791     private void writeVarint32FourBytes(int value) {
2792       UnsafeUtil.putByte(pos--, (byte) (value >>> 21));
2793       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2794       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2795       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2796     }
2797 
writeVarint32FiveBytes(int value)2798     private void writeVarint32FiveBytes(int value) {
2799       UnsafeUtil.putByte(pos--, (byte) (value >>> 28));
2800       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2801       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2802       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2803       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2804     }
2805 
2806     @Override
writeVarint64(long value)2807     void writeVarint64(long value) {
2808       switch (computeUInt64SizeNoTag(value)) {
2809         case 1:
2810           writeVarint64OneByte(value);
2811           break;
2812         case 2:
2813           writeVarint64TwoBytes(value);
2814           break;
2815         case 3:
2816           writeVarint64ThreeBytes(value);
2817           break;
2818         case 4:
2819           writeVarint64FourBytes(value);
2820           break;
2821         case 5:
2822           writeVarint64FiveBytes(value);
2823           break;
2824         case 6:
2825           writeVarint64SixBytes(value);
2826           break;
2827         case 7:
2828           writeVarint64SevenBytes(value);
2829           break;
2830         case 8:
2831           writeVarint64EightBytes(value);
2832           break;
2833         case 9:
2834           writeVarint64NineBytes(value);
2835           break;
2836         case 10:
2837           writeVarint64TenBytes(value);
2838           break;
2839       }
2840     }
2841 
writeVarint64OneByte(long value)2842     private void writeVarint64OneByte(long value) {
2843       UnsafeUtil.putByte(pos--, (byte) value);
2844     }
2845 
writeVarint64TwoBytes(long value)2846     private void writeVarint64TwoBytes(long value) {
2847       UnsafeUtil.putByte(pos--, (byte) (value >>> 7));
2848       UnsafeUtil.putByte(pos--, (byte) (((int) value & 0x7F) | 0x80));
2849     }
2850 
writeVarint64ThreeBytes(long value)2851     private void writeVarint64ThreeBytes(long value) {
2852       UnsafeUtil.putByte(pos--, (byte) (((int) value) >>> 14));
2853       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2854       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2855     }
2856 
writeVarint64FourBytes(long value)2857     private void writeVarint64FourBytes(long value) {
2858       UnsafeUtil.putByte(pos--, (byte) (value >>> 21));
2859       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2860       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2861       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2862     }
2863 
writeVarint64FiveBytes(long value)2864     private void writeVarint64FiveBytes(long value) {
2865       UnsafeUtil.putByte(pos--, (byte) (value >>> 28));
2866       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2867       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2868       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2869       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2870     }
2871 
writeVarint64SixBytes(long value)2872     private void writeVarint64SixBytes(long value) {
2873       UnsafeUtil.putByte(pos--, (byte) (value >>> 35));
2874       UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
2875       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2876       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2877       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2878       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2879     }
2880 
writeVarint64SevenBytes(long value)2881     private void writeVarint64SevenBytes(long value) {
2882       UnsafeUtil.putByte(pos--, (byte) (value >>> 42));
2883       UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
2884       UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
2885       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2886       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2887       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2888       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2889     }
2890 
writeVarint64EightBytes(long value)2891     private void writeVarint64EightBytes(long value) {
2892       UnsafeUtil.putByte(pos--, (byte) (value >>> 49));
2893       UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
2894       UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
2895       UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
2896       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2897       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2898       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2899       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2900     }
2901 
writeVarint64NineBytes(long value)2902     private void writeVarint64NineBytes(long value) {
2903       UnsafeUtil.putByte(pos--, (byte) (value >>> 56));
2904       UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
2905       UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
2906       UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
2907       UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
2908       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2909       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2910       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2911       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2912     }
2913 
writeVarint64TenBytes(long value)2914     private void writeVarint64TenBytes(long value) {
2915       UnsafeUtil.putByte(pos--, (byte) (value >>> 63));
2916       UnsafeUtil.putByte(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
2917       UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
2918       UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
2919       UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
2920       UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
2921       UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
2922       UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
2923       UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
2924       UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
2925     }
2926 
2927     @Override
writeFixed32(int value)2928     void writeFixed32(int value) {
2929       UnsafeUtil.putByte(pos--, (byte) ((value >> 24) & 0xFF));
2930       UnsafeUtil.putByte(pos--, (byte) ((value >> 16) & 0xFF));
2931       UnsafeUtil.putByte(pos--, (byte) ((value >> 8) & 0xFF));
2932       UnsafeUtil.putByte(pos--, (byte) (value & 0xFF));
2933     }
2934 
2935     @Override
writeFixed64(long value)2936     void writeFixed64(long value) {
2937       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 56) & 0xFF));
2938       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 48) & 0xFF));
2939       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 40) & 0xFF));
2940       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 32) & 0xFF));
2941       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 24) & 0xFF));
2942       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 16) & 0xFF));
2943       UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 8) & 0xFF));
2944       UnsafeUtil.putByte(pos--, (byte) ((int) (value) & 0xFF));
2945     }
2946 
2947     @Override
writeString(String in)2948     void writeString(String in) {
2949       // Request enough space to write the ASCII string.
2950       requireSpace(in.length());
2951 
2952       // We know the buffer is big enough...
2953       int i = in.length() - 1;
2954       // Designed to take advantage of
2955       // https://wiki.openjdk.java.net/display/HotSpotInternals/RangeCheckElimination
2956       for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
2957         UnsafeUtil.putByte(pos--, (byte) c);
2958       }
2959       if (i == -1) {
2960         // ASCII.
2961         return;
2962       }
2963       for (char c; i >= 0; i--) {
2964         c = in.charAt(i);
2965         if (c < 0x80 && pos >= bufferOffset) {
2966           UnsafeUtil.putByte(pos--, (byte) c);
2967         } else if (c < 0x800 && pos > bufferOffset) { // 11 bits, two UTF-8 bytes
2968           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c)));
2969           UnsafeUtil.putByte(pos--, (byte) ((0xF << 6) | (c >>> 6)));
2970         } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
2971             && pos > bufferOffset + 1) {
2972           // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
2973           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c)));
2974           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
2975           UnsafeUtil.putByte(pos--, (byte) ((0xF << 5) | (c >>> 12)));
2976         } else if (pos > bufferOffset + 2) {
2977           // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
2978           // four UTF-8 bytes
2979           final char high;
2980           if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
2981             throw new Utf8.UnpairedSurrogateException(i - 1, i);
2982           }
2983           i--;
2984           int codePoint = Character.toCodePoint(high, c);
2985           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & codePoint)));
2986           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
2987           UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
2988           UnsafeUtil.putByte(pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
2989         } else {
2990           // Buffer is full - allocate a new one and revisit the current character.
2991           requireSpace(i);
2992           i++;
2993         }
2994       }
2995     }
2996 
2997     @Override
write(byte value)2998     public void write(byte value) {
2999       UnsafeUtil.putByte(pos--, value);
3000     }
3001 
3002     @Override
write(byte[] value, int offset, int length)3003     public void write(byte[] value, int offset, int length) {
3004       if (spaceLeft() < length) {
3005         nextBuffer(length);
3006       }
3007 
3008       pos -= length;
3009       buffer.position(bufferPos() + 1);
3010       buffer.put(value, offset, length);
3011     }
3012 
3013     @Override
writeLazy(byte[] value, int offset, int length)3014     public void writeLazy(byte[] value, int offset, int length) {
3015       if (spaceLeft() < length) {
3016         // We consider the value to be immutable (likely the internals of a ByteString). Just
3017         // wrap it in a Netty buffer and add it to the output buffer.
3018         totalDoneBytes += length;
3019         buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
3020 
3021         // Advance the writer to the next buffer.
3022         // TODO(nathanmittler): Consider slicing if space available above some threshold.
3023         nextBuffer();
3024         return;
3025       }
3026 
3027       pos -= length;
3028       buffer.position(bufferPos() + 1);
3029       buffer.put(value, offset, length);
3030     }
3031 
3032     @Override
write(ByteBuffer value)3033     public void write(ByteBuffer value) {
3034       int length = value.remaining();
3035       if (spaceLeft() < length) {
3036         nextBuffer(length);
3037       }
3038 
3039       pos -= length;
3040       buffer.position(bufferPos() + 1);
3041       buffer.put(value);
3042     }
3043 
3044     @Override
writeLazy(ByteBuffer value)3045     public void writeLazy(ByteBuffer value) {
3046       int length = value.remaining();
3047       if (spaceLeft() < length) {
3048         // We consider the value to be immutable (likely the internals of a ByteString). Just
3049         // wrap it in a Netty buffer and add it to the output buffer.
3050         totalDoneBytes += length;
3051         buffers.addFirst(AllocatedBuffer.wrap(value));
3052 
3053         // Advance the writer to the next buffer.
3054         // TODO(nathanmittler): Consider slicing if space available above some threshold.
3055         nextBuffer();
3056         return;
3057       }
3058 
3059       pos -= length;
3060       buffer.position(bufferPos() + 1);
3061       buffer.put(value);
3062     }
3063 
3064     @Override
requireSpace(int size)3065     void requireSpace(int size) {
3066       if (spaceLeft() < size) {
3067         nextBuffer(size);
3068       }
3069     }
3070   }
3071 }
3072