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