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