1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2013 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 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.nano; 32 33 import java.io.IOException; 34 import java.io.UnsupportedEncodingException; 35 36 /** 37 * Encodes and writes protocol message fields. 38 * 39 * <p>This class contains two kinds of methods: methods that write specific 40 * protocol message constructs and field types (e.g. {@link #writeTag} and 41 * {@link #writeInt32}) and methods that write low-level values (e.g. 42 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are 43 * writing encoded protocol messages, you should use the former methods, but if 44 * you are writing some other format of your own design, use the latter. 45 * 46 * <p>This class is totally unsynchronized. 47 * 48 * @author kneton@google.com Kenton Varda 49 */ 50 public final class CodedOutputByteBufferNano { 51 private final byte[] buffer; 52 private final int limit; 53 private int position; 54 CodedOutputByteBufferNano(final byte[] buffer, final int offset, final int length)55 private CodedOutputByteBufferNano(final byte[] buffer, final int offset, 56 final int length) { 57 this.buffer = buffer; 58 position = offset; 59 limit = offset + length; 60 } 61 62 /** 63 * Create a new {@code CodedOutputStream} that writes directly to the given 64 * byte array. If more bytes are written than fit in the array, 65 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 66 * array is faster than writing to an {@code OutputStream}. 67 */ newInstance(final byte[] flatArray)68 public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) { 69 return newInstance(flatArray, 0, flatArray.length); 70 } 71 72 /** 73 * Create a new {@code CodedOutputStream} that writes directly to the given 74 * byte array slice. If more bytes are written than fit in the slice, 75 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 76 * array is faster than writing to an {@code OutputStream}. 77 */ newInstance(final byte[] flatArray, final int offset, final int length)78 public static CodedOutputByteBufferNano newInstance(final byte[] flatArray, 79 final int offset, 80 final int length) { 81 return new CodedOutputByteBufferNano(flatArray, offset, length); 82 } 83 84 // ----------------------------------------------------------------- 85 86 /** Write a {@code double} field, including tag, to the stream. */ writeDouble(final int fieldNumber, final double value)87 public void writeDouble(final int fieldNumber, final double value) 88 throws IOException { 89 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 90 writeDoubleNoTag(value); 91 } 92 93 /** Write a {@code float} field, including tag, to the stream. */ writeFloat(final int fieldNumber, final float value)94 public void writeFloat(final int fieldNumber, final float value) 95 throws IOException { 96 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 97 writeFloatNoTag(value); 98 } 99 100 /** Write a {@code uint64} field, including tag, to the stream. */ writeUInt64(final int fieldNumber, final long value)101 public void writeUInt64(final int fieldNumber, final long value) 102 throws IOException { 103 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 104 writeUInt64NoTag(value); 105 } 106 107 /** Write an {@code int64} field, including tag, to the stream. */ writeInt64(final int fieldNumber, final long value)108 public void writeInt64(final int fieldNumber, final long value) 109 throws IOException { 110 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 111 writeInt64NoTag(value); 112 } 113 114 /** Write an {@code int32} field, including tag, to the stream. */ writeInt32(final int fieldNumber, final int value)115 public void writeInt32(final int fieldNumber, final int value) 116 throws IOException { 117 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 118 writeInt32NoTag(value); 119 } 120 121 /** Write a {@code fixed64} field, including tag, to the stream. */ writeFixed64(final int fieldNumber, final long value)122 public void writeFixed64(final int fieldNumber, final long value) 123 throws IOException { 124 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 125 writeFixed64NoTag(value); 126 } 127 128 /** Write a {@code fixed32} field, including tag, to the stream. */ writeFixed32(final int fieldNumber, final int value)129 public void writeFixed32(final int fieldNumber, final int value) 130 throws IOException { 131 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 132 writeFixed32NoTag(value); 133 } 134 135 /** Write a {@code bool} field, including tag, to the stream. */ writeBool(final int fieldNumber, final boolean value)136 public void writeBool(final int fieldNumber, final boolean value) 137 throws IOException { 138 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 139 writeBoolNoTag(value); 140 } 141 142 /** Write a {@code string} field, including tag, to the stream. */ writeString(final int fieldNumber, final String value)143 public void writeString(final int fieldNumber, final String value) 144 throws IOException { 145 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 146 writeStringNoTag(value); 147 } 148 149 /** Write a {@code group} field, including tag, to the stream. */ writeGroup(final int fieldNumber, final MessageNano value)150 public void writeGroup(final int fieldNumber, final MessageNano value) 151 throws IOException { 152 writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP); 153 writeGroupNoTag(value); 154 writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); 155 } 156 157 /** Write an embedded message field, including tag, to the stream. */ writeMessage(final int fieldNumber, final MessageNano value)158 public void writeMessage(final int fieldNumber, final MessageNano value) 159 throws IOException { 160 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 161 writeMessageNoTag(value); 162 } 163 164 /** Write a {@code bytes} field, including tag, to the stream. */ writeBytes(final int fieldNumber, final byte[] value)165 public void writeBytes(final int fieldNumber, final byte[] value) 166 throws IOException { 167 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 168 writeBytesNoTag(value); 169 } 170 171 /** Write a {@code uint32} field, including tag, to the stream. */ writeUInt32(final int fieldNumber, final int value)172 public void writeUInt32(final int fieldNumber, final int value) 173 throws IOException { 174 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 175 writeUInt32NoTag(value); 176 } 177 178 /** 179 * Write an enum field, including tag, to the stream. Caller is responsible 180 * for converting the enum value to its numeric value. 181 */ writeEnum(final int fieldNumber, final int value)182 public void writeEnum(final int fieldNumber, final int value) 183 throws IOException { 184 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 185 writeEnumNoTag(value); 186 } 187 188 /** Write an {@code sfixed32} field, including tag, to the stream. */ writeSFixed32(final int fieldNumber, final int value)189 public void writeSFixed32(final int fieldNumber, final int value) 190 throws IOException { 191 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 192 writeSFixed32NoTag(value); 193 } 194 195 /** Write an {@code sfixed64} field, including tag, to the stream. */ writeSFixed64(final int fieldNumber, final long value)196 public void writeSFixed64(final int fieldNumber, final long value) 197 throws IOException { 198 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 199 writeSFixed64NoTag(value); 200 } 201 202 /** Write an {@code sint32} field, including tag, to the stream. */ writeSInt32(final int fieldNumber, final int value)203 public void writeSInt32(final int fieldNumber, final int value) 204 throws IOException { 205 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 206 writeSInt32NoTag(value); 207 } 208 209 /** Write an {@code sint64} field, including tag, to the stream. */ writeSInt64(final int fieldNumber, final long value)210 public void writeSInt64(final int fieldNumber, final long value) 211 throws IOException { 212 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 213 writeSInt64NoTag(value); 214 } 215 216 /** 217 * Write a MessageSet extension field to the stream. For historical reasons, 218 * the wire format differs from normal fields. 219 */ 220 // public void writeMessageSetExtension(final int fieldNumber, 221 // final MessageMicro value) 222 // throws IOException { 223 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 224 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 225 // writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 226 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 227 // } 228 229 /** 230 * Write an unparsed MessageSet extension field to the stream. For 231 * historical reasons, the wire format differs from normal fields. 232 */ 233 // public void writeRawMessageSetExtension(final int fieldNumber, 234 // final ByteStringMicro value) 235 // throws IOException { 236 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 237 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 238 // writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 239 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 240 // } 241 242 // ----------------------------------------------------------------- 243 244 /** Write a {@code double} field to the stream. */ writeDoubleNoTag(final double value)245 public void writeDoubleNoTag(final double value) throws IOException { 246 writeRawLittleEndian64(Double.doubleToLongBits(value)); 247 } 248 249 /** Write a {@code float} field to the stream. */ writeFloatNoTag(final float value)250 public void writeFloatNoTag(final float value) throws IOException { 251 writeRawLittleEndian32(Float.floatToIntBits(value)); 252 } 253 254 /** Write a {@code uint64} field to the stream. */ writeUInt64NoTag(final long value)255 public void writeUInt64NoTag(final long value) throws IOException { 256 writeRawVarint64(value); 257 } 258 259 /** Write an {@code int64} field to the stream. */ writeInt64NoTag(final long value)260 public void writeInt64NoTag(final long value) throws IOException { 261 writeRawVarint64(value); 262 } 263 264 /** Write an {@code int32} field to the stream. */ writeInt32NoTag(final int value)265 public void writeInt32NoTag(final int value) throws IOException { 266 if (value >= 0) { 267 writeRawVarint32(value); 268 } else { 269 // Must sign-extend. 270 writeRawVarint64(value); 271 } 272 } 273 274 /** Write a {@code fixed64} field to the stream. */ writeFixed64NoTag(final long value)275 public void writeFixed64NoTag(final long value) throws IOException { 276 writeRawLittleEndian64(value); 277 } 278 279 /** Write a {@code fixed32} field to the stream. */ writeFixed32NoTag(final int value)280 public void writeFixed32NoTag(final int value) throws IOException { 281 writeRawLittleEndian32(value); 282 } 283 284 /** Write a {@code bool} field to the stream. */ writeBoolNoTag(final boolean value)285 public void writeBoolNoTag(final boolean value) throws IOException { 286 writeRawByte(value ? 1 : 0); 287 } 288 289 /** Write a {@code string} field to the stream. */ writeStringNoTag(final String value)290 public void writeStringNoTag(final String value) throws IOException { 291 // Unfortunately there does not appear to be any way to tell Java to encode 292 // UTF-8 directly into our buffer, so we have to let it create its own byte 293 // array and then copy. 294 final byte[] bytes = value.getBytes("UTF-8"); 295 writeRawVarint32(bytes.length); 296 writeRawBytes(bytes); 297 } 298 299 /** Write a {@code group} field to the stream. */ writeGroupNoTag(final MessageNano value)300 public void writeGroupNoTag(final MessageNano value) throws IOException { 301 value.writeTo(this); 302 } 303 304 /** Write an embedded message field to the stream. */ writeMessageNoTag(final MessageNano value)305 public void writeMessageNoTag(final MessageNano value) throws IOException { 306 writeRawVarint32(value.getCachedSize()); 307 value.writeTo(this); 308 } 309 310 /** Write a {@code bytes} field to the stream. */ writeBytesNoTag(final byte[] value)311 public void writeBytesNoTag(final byte[] value) throws IOException { 312 writeRawVarint32(value.length); 313 writeRawBytes(value); 314 } 315 316 /** Write a {@code uint32} field to the stream. */ writeUInt32NoTag(final int value)317 public void writeUInt32NoTag(final int value) throws IOException { 318 writeRawVarint32(value); 319 } 320 321 /** 322 * Write an enum field to the stream. Caller is responsible 323 * for converting the enum value to its numeric value. 324 */ writeEnumNoTag(final int value)325 public void writeEnumNoTag(final int value) throws IOException { 326 writeRawVarint32(value); 327 } 328 329 /** Write an {@code sfixed32} field to the stream. */ writeSFixed32NoTag(final int value)330 public void writeSFixed32NoTag(final int value) throws IOException { 331 writeRawLittleEndian32(value); 332 } 333 334 /** Write an {@code sfixed64} field to the stream. */ writeSFixed64NoTag(final long value)335 public void writeSFixed64NoTag(final long value) throws IOException { 336 writeRawLittleEndian64(value); 337 } 338 339 /** Write an {@code sint32} field to the stream. */ writeSInt32NoTag(final int value)340 public void writeSInt32NoTag(final int value) throws IOException { 341 writeRawVarint32(encodeZigZag32(value)); 342 } 343 344 /** Write an {@code sint64} field to the stream. */ writeSInt64NoTag(final long value)345 public void writeSInt64NoTag(final long value) throws IOException { 346 writeRawVarint64(encodeZigZag64(value)); 347 } 348 349 // ================================================================= 350 351 /** 352 * Compute the number of bytes that would be needed to encode a 353 * {@code double} field, including tag. 354 */ computeDoubleSize(final int fieldNumber, final double value)355 public static int computeDoubleSize(final int fieldNumber, 356 final double value) { 357 return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); 358 } 359 360 /** 361 * Compute the number of bytes that would be needed to encode a 362 * {@code float} field, including tag. 363 */ computeFloatSize(final int fieldNumber, final float value)364 public static int computeFloatSize(final int fieldNumber, final float value) { 365 return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); 366 } 367 368 /** 369 * Compute the number of bytes that would be needed to encode a 370 * {@code uint64} field, including tag. 371 */ computeUInt64Size(final int fieldNumber, final long value)372 public static int computeUInt64Size(final int fieldNumber, final long value) { 373 return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); 374 } 375 376 /** 377 * Compute the number of bytes that would be needed to encode an 378 * {@code int64} field, including tag. 379 */ computeInt64Size(final int fieldNumber, final long value)380 public static int computeInt64Size(final int fieldNumber, final long value) { 381 return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); 382 } 383 384 /** 385 * Compute the number of bytes that would be needed to encode an 386 * {@code int32} field, including tag. 387 */ computeInt32Size(final int fieldNumber, final int value)388 public static int computeInt32Size(final int fieldNumber, final int value) { 389 return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); 390 } 391 392 /** 393 * Compute the number of bytes that would be needed to encode a 394 * {@code fixed64} field, including tag. 395 */ computeFixed64Size(final int fieldNumber, final long value)396 public static int computeFixed64Size(final int fieldNumber, 397 final long value) { 398 return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); 399 } 400 401 /** 402 * Compute the number of bytes that would be needed to encode a 403 * {@code fixed32} field, including tag. 404 */ computeFixed32Size(final int fieldNumber, final int value)405 public static int computeFixed32Size(final int fieldNumber, 406 final int value) { 407 return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); 408 } 409 410 /** 411 * Compute the number of bytes that would be needed to encode a 412 * {@code bool} field, including tag. 413 */ computeBoolSize(final int fieldNumber, final boolean value)414 public static int computeBoolSize(final int fieldNumber, 415 final boolean value) { 416 return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); 417 } 418 419 /** 420 * Compute the number of bytes that would be needed to encode a 421 * {@code string} field, including tag. 422 */ computeStringSize(final int fieldNumber, final String value)423 public static int computeStringSize(final int fieldNumber, 424 final String value) { 425 return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); 426 } 427 428 /** 429 * Compute the number of bytes that would be needed to encode a 430 * {@code group} field, including tag. 431 */ computeGroupSize(final int fieldNumber, final MessageNano value)432 public static int computeGroupSize(final int fieldNumber, 433 final MessageNano value) { 434 return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); 435 } 436 437 /** 438 * Compute the number of bytes that would be needed to encode an 439 * embedded message field, including tag. 440 */ computeMessageSize(final int fieldNumber, final MessageNano value)441 public static int computeMessageSize(final int fieldNumber, 442 final MessageNano value) { 443 return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); 444 } 445 446 /** 447 * Compute the number of bytes that would be needed to encode a 448 * {@code bytes} field, including tag. 449 */ computeBytesSize(final int fieldNumber, final byte[] value)450 public static int computeBytesSize(final int fieldNumber, 451 final byte[] value) { 452 return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); 453 } 454 455 /** 456 * Compute the number of bytes that would be needed to encode a 457 * {@code uint32} field, including tag. 458 */ computeUInt32Size(final int fieldNumber, final int value)459 public static int computeUInt32Size(final int fieldNumber, final int value) { 460 return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); 461 } 462 463 /** 464 * Compute the number of bytes that would be needed to encode an 465 * enum field, including tag. Caller is responsible for converting the 466 * enum value to its numeric value. 467 */ computeEnumSize(final int fieldNumber, final int value)468 public static int computeEnumSize(final int fieldNumber, final int value) { 469 return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); 470 } 471 472 /** 473 * Compute the number of bytes that would be needed to encode an 474 * {@code sfixed32} field, including tag. 475 */ computeSFixed32Size(final int fieldNumber, final int value)476 public static int computeSFixed32Size(final int fieldNumber, 477 final int value) { 478 return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); 479 } 480 481 /** 482 * Compute the number of bytes that would be needed to encode an 483 * {@code sfixed64} field, including tag. 484 */ computeSFixed64Size(final int fieldNumber, final long value)485 public static int computeSFixed64Size(final int fieldNumber, 486 final long value) { 487 return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); 488 } 489 490 /** 491 * Compute the number of bytes that would be needed to encode an 492 * {@code sint32} field, including tag. 493 */ computeSInt32Size(final int fieldNumber, final int value)494 public static int computeSInt32Size(final int fieldNumber, final int value) { 495 return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); 496 } 497 498 /** 499 * Compute the number of bytes that would be needed to encode an 500 * {@code sint64} field, including tag. 501 */ computeSInt64Size(final int fieldNumber, final long value)502 public static int computeSInt64Size(final int fieldNumber, final long value) { 503 return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); 504 } 505 506 /** 507 * Compute the number of bytes that would be needed to encode a 508 * MessageSet extension to the stream. For historical reasons, 509 * the wire format differs from normal fields. 510 */ 511 // public static int computeMessageSetExtensionSize( 512 // final int fieldNumber, final MessageMicro value) { 513 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 514 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 515 // computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 516 // } 517 518 /** 519 * Compute the number of bytes that would be needed to encode an 520 * unparsed MessageSet extension field to the stream. For 521 * historical reasons, the wire format differs from normal fields. 522 */ 523 // public static int computeRawMessageSetExtensionSize( 524 // final int fieldNumber, final ByteStringMicro value) { 525 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 526 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 527 // computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 528 // } 529 530 // ----------------------------------------------------------------- 531 532 /** 533 * Compute the number of bytes that would be needed to encode a 534 * {@code double} field, including tag. 535 */ computeDoubleSizeNoTag(final double value)536 public static int computeDoubleSizeNoTag(final double value) { 537 return LITTLE_ENDIAN_64_SIZE; 538 } 539 540 /** 541 * Compute the number of bytes that would be needed to encode a 542 * {@code float} field, including tag. 543 */ computeFloatSizeNoTag(final float value)544 public static int computeFloatSizeNoTag(final float value) { 545 return LITTLE_ENDIAN_32_SIZE; 546 } 547 548 /** 549 * Compute the number of bytes that would be needed to encode a 550 * {@code uint64} field, including tag. 551 */ computeUInt64SizeNoTag(final long value)552 public static int computeUInt64SizeNoTag(final long value) { 553 return computeRawVarint64Size(value); 554 } 555 556 /** 557 * Compute the number of bytes that would be needed to encode an 558 * {@code int64} field, including tag. 559 */ computeInt64SizeNoTag(final long value)560 public static int computeInt64SizeNoTag(final long value) { 561 return computeRawVarint64Size(value); 562 } 563 564 /** 565 * Compute the number of bytes that would be needed to encode an 566 * {@code int32} field, including tag. 567 */ computeInt32SizeNoTag(final int value)568 public static int computeInt32SizeNoTag(final int value) { 569 if (value >= 0) { 570 return computeRawVarint32Size(value); 571 } else { 572 // Must sign-extend. 573 return 10; 574 } 575 } 576 577 /** 578 * Compute the number of bytes that would be needed to encode a 579 * {@code fixed64} field. 580 */ computeFixed64SizeNoTag(final long value)581 public static int computeFixed64SizeNoTag(final long value) { 582 return LITTLE_ENDIAN_64_SIZE; 583 } 584 585 /** 586 * Compute the number of bytes that would be needed to encode a 587 * {@code fixed32} field. 588 */ computeFixed32SizeNoTag(final int value)589 public static int computeFixed32SizeNoTag(final int value) { 590 return LITTLE_ENDIAN_32_SIZE; 591 } 592 593 /** 594 * Compute the number of bytes that would be needed to encode a 595 * {@code bool} field. 596 */ computeBoolSizeNoTag(final boolean value)597 public static int computeBoolSizeNoTag(final boolean value) { 598 return 1; 599 } 600 601 /** 602 * Compute the number of bytes that would be needed to encode a 603 * {@code string} field. 604 */ computeStringSizeNoTag(final String value)605 public static int computeStringSizeNoTag(final String value) { 606 try { 607 final byte[] bytes = value.getBytes("UTF-8"); 608 return computeRawVarint32Size(bytes.length) + 609 bytes.length; 610 } catch (UnsupportedEncodingException e) { 611 throw new RuntimeException("UTF-8 not supported."); 612 } 613 } 614 615 /** 616 * Compute the number of bytes that would be needed to encode a 617 * {@code group} field. 618 */ computeGroupSizeNoTag(final MessageNano value)619 public static int computeGroupSizeNoTag(final MessageNano value) { 620 return value.getSerializedSize(); 621 } 622 623 /** 624 * Compute the number of bytes that would be needed to encode an embedded 625 * message field. 626 */ computeMessageSizeNoTag(final MessageNano value)627 public static int computeMessageSizeNoTag(final MessageNano value) { 628 final int size = value.getSerializedSize(); 629 return computeRawVarint32Size(size) + size; 630 } 631 632 /** 633 * Compute the number of bytes that would be needed to encode a 634 * {@code bytes} field. 635 */ computeBytesSizeNoTag(final byte[] value)636 public static int computeBytesSizeNoTag(final byte[] value) { 637 return computeRawVarint32Size(value.length) + value.length; 638 } 639 640 /** 641 * Compute the number of bytes that would be needed to encode a 642 * {@code uint32} field. 643 */ computeUInt32SizeNoTag(final int value)644 public static int computeUInt32SizeNoTag(final int value) { 645 return computeRawVarint32Size(value); 646 } 647 648 /** 649 * Compute the number of bytes that would be needed to encode an enum field. 650 * Caller is responsible for converting the enum value to its numeric value. 651 */ computeEnumSizeNoTag(final int value)652 public static int computeEnumSizeNoTag(final int value) { 653 return computeRawVarint32Size(value); 654 } 655 656 /** 657 * Compute the number of bytes that would be needed to encode an 658 * {@code sfixed32} field. 659 */ computeSFixed32SizeNoTag(final int value)660 public static int computeSFixed32SizeNoTag(final int value) { 661 return LITTLE_ENDIAN_32_SIZE; 662 } 663 664 /** 665 * Compute the number of bytes that would be needed to encode an 666 * {@code sfixed64} field. 667 */ computeSFixed64SizeNoTag(final long value)668 public static int computeSFixed64SizeNoTag(final long value) { 669 return LITTLE_ENDIAN_64_SIZE; 670 } 671 672 /** 673 * Compute the number of bytes that would be needed to encode an 674 * {@code sint32} field. 675 */ computeSInt32SizeNoTag(final int value)676 public static int computeSInt32SizeNoTag(final int value) { 677 return computeRawVarint32Size(encodeZigZag32(value)); 678 } 679 680 /** 681 * Compute the number of bytes that would be needed to encode an 682 * {@code sint64} field. 683 */ computeSInt64SizeNoTag(final long value)684 public static int computeSInt64SizeNoTag(final long value) { 685 return computeRawVarint64Size(encodeZigZag64(value)); 686 } 687 688 // ================================================================= 689 690 /** 691 * If writing to a flat array, return the space left in the array. 692 * Otherwise, throws {@code UnsupportedOperationException}. 693 */ spaceLeft()694 public int spaceLeft() { 695 return limit - position; 696 } 697 698 /** 699 * Verifies that {@link #spaceLeft()} returns zero. It's common to create 700 * a byte array that is exactly big enough to hold a message, then write to 701 * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} 702 * after writing verifies that the message was actually as big as expected, 703 * which can help catch bugs. 704 */ checkNoSpaceLeft()705 public void checkNoSpaceLeft() { 706 if (spaceLeft() != 0) { 707 throw new IllegalStateException( 708 "Did not write as much data as expected."); 709 } 710 } 711 712 /** 713 * If you create a CodedOutputStream around a simple flat array, you must 714 * not attempt to write more bytes than the array has space. Otherwise, 715 * this exception will be thrown. 716 */ 717 public static class OutOfSpaceException extends IOException { 718 private static final long serialVersionUID = -6947486886997889499L; 719 OutOfSpaceException(int position, int limit)720 OutOfSpaceException(int position, int limit) { 721 super("CodedOutputStream was writing to a flat byte array and ran " + 722 "out of space (pos " + position + " limit " + limit + ")."); 723 } 724 } 725 726 /** Write a single byte. */ writeRawByte(final byte value)727 public void writeRawByte(final byte value) throws IOException { 728 if (position == limit) { 729 // We're writing to a single buffer. 730 throw new OutOfSpaceException(position, limit); 731 } 732 733 buffer[position++] = value; 734 } 735 736 /** Write a single byte, represented by an integer value. */ writeRawByte(final int value)737 public void writeRawByte(final int value) throws IOException { 738 writeRawByte((byte) value); 739 } 740 741 /** Write an array of bytes. */ writeRawBytes(final byte[] value)742 public void writeRawBytes(final byte[] value) throws IOException { 743 writeRawBytes(value, 0, value.length); 744 } 745 746 /** Write part of an array of bytes. */ writeRawBytes(final byte[] value, int offset, int length)747 public void writeRawBytes(final byte[] value, int offset, int length) 748 throws IOException { 749 if (limit - position >= length) { 750 // We have room in the current buffer. 751 System.arraycopy(value, offset, buffer, position, length); 752 position += length; 753 } else { 754 // We're writing to a single buffer. 755 throw new OutOfSpaceException(position, limit); 756 } 757 } 758 759 /** Encode and write a tag. */ writeTag(final int fieldNumber, final int wireType)760 public void writeTag(final int fieldNumber, final int wireType) 761 throws IOException { 762 writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType)); 763 } 764 765 /** Compute the number of bytes that would be needed to encode a tag. */ computeTagSize(final int fieldNumber)766 public static int computeTagSize(final int fieldNumber) { 767 return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0)); 768 } 769 770 /** 771 * Encode and write a varint. {@code value} is treated as 772 * unsigned, so it won't be sign-extended if negative. 773 */ writeRawVarint32(int value)774 public void writeRawVarint32(int value) throws IOException { 775 while (true) { 776 if ((value & ~0x7F) == 0) { 777 writeRawByte(value); 778 return; 779 } else { 780 writeRawByte((value & 0x7F) | 0x80); 781 value >>>= 7; 782 } 783 } 784 } 785 786 /** 787 * Compute the number of bytes that would be needed to encode a varint. 788 * {@code value} is treated as unsigned, so it won't be sign-extended if 789 * negative. 790 */ computeRawVarint32Size(final int value)791 public static int computeRawVarint32Size(final int value) { 792 if ((value & (0xffffffff << 7)) == 0) return 1; 793 if ((value & (0xffffffff << 14)) == 0) return 2; 794 if ((value & (0xffffffff << 21)) == 0) return 3; 795 if ((value & (0xffffffff << 28)) == 0) return 4; 796 return 5; 797 } 798 799 /** Encode and write a varint. */ writeRawVarint64(long value)800 public void writeRawVarint64(long value) throws IOException { 801 while (true) { 802 if ((value & ~0x7FL) == 0) { 803 writeRawByte((int)value); 804 return; 805 } else { 806 writeRawByte(((int)value & 0x7F) | 0x80); 807 value >>>= 7; 808 } 809 } 810 } 811 812 /** Compute the number of bytes that would be needed to encode a varint. */ computeRawVarint64Size(final long value)813 public static int computeRawVarint64Size(final long value) { 814 if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; 815 if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; 816 if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; 817 if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; 818 if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; 819 if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; 820 if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; 821 if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; 822 if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; 823 return 10; 824 } 825 826 /** Write a little-endian 32-bit integer. */ writeRawLittleEndian32(final int value)827 public void writeRawLittleEndian32(final int value) throws IOException { 828 writeRawByte((value ) & 0xFF); 829 writeRawByte((value >> 8) & 0xFF); 830 writeRawByte((value >> 16) & 0xFF); 831 writeRawByte((value >> 24) & 0xFF); 832 } 833 834 public static final int LITTLE_ENDIAN_32_SIZE = 4; 835 836 /** Write a little-endian 64-bit integer. */ writeRawLittleEndian64(final long value)837 public void writeRawLittleEndian64(final long value) throws IOException { 838 writeRawByte((int)(value ) & 0xFF); 839 writeRawByte((int)(value >> 8) & 0xFF); 840 writeRawByte((int)(value >> 16) & 0xFF); 841 writeRawByte((int)(value >> 24) & 0xFF); 842 writeRawByte((int)(value >> 32) & 0xFF); 843 writeRawByte((int)(value >> 40) & 0xFF); 844 writeRawByte((int)(value >> 48) & 0xFF); 845 writeRawByte((int)(value >> 56) & 0xFF); 846 } 847 848 public static final int LITTLE_ENDIAN_64_SIZE = 8; 849 850 /** 851 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 852 * into values that can be efficiently encoded with varint. (Otherwise, 853 * negative values must be sign-extended to 64 bits to be varint encoded, 854 * thus always taking 10 bytes on the wire.) 855 * 856 * @param n A signed 32-bit integer. 857 * @return An unsigned 32-bit integer, stored in a signed int because 858 * Java has no explicit unsigned support. 859 */ encodeZigZag32(final int n)860 public static int encodeZigZag32(final int n) { 861 // Note: the right-shift must be arithmetic 862 return (n << 1) ^ (n >> 31); 863 } 864 865 /** 866 * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 867 * into values that can be efficiently encoded with varint. (Otherwise, 868 * negative values must be sign-extended to 64 bits to be varint encoded, 869 * thus always taking 10 bytes on the wire.) 870 * 871 * @param n A signed 64-bit integer. 872 * @return An unsigned 64-bit integer, stored in a signed int because 873 * Java has no explicit unsigned support. 874 */ encodeZigZag64(final long n)875 public static long encodeZigZag64(final long n) { 876 // Note: the right-shift must be arithmetic 877 return (n << 1) ^ (n >> 63); 878 } 879 } 880