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