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