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