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