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