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