1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2013 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.nano; 32 33 import java.io.IOException; 34 import java.nio.BufferOverflowException; 35 import java.nio.ByteBuffer; 36 import java.nio.ByteOrder; 37 import java.nio.ReadOnlyBufferException; 38 39 /** 40 * Encodes and writes protocol message fields. 41 * 42 * <p>This class contains two kinds of methods: methods that write specific 43 * protocol message constructs and field types (e.g. {@link #writeTag} and 44 * {@link #writeInt32}) and methods that write low-level values (e.g. 45 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are 46 * writing encoded protocol messages, you should use the former methods, but if 47 * you are writing some other format of your own design, use the latter. 48 * 49 * <p>This class is totally unsynchronized. 50 * 51 * @author kneton@google.com Kenton Varda 52 */ 53 public final class CodedOutputByteBufferNano { 54 /* max bytes per java UTF-16 char in UTF-8 */ 55 private static final int MAX_UTF8_EXPANSION = 3; 56 private final ByteBuffer buffer; 57 CodedOutputByteBufferNano(final byte[] buffer, final int offset, final int length)58 private CodedOutputByteBufferNano(final byte[] buffer, final int offset, 59 final int length) { 60 this(ByteBuffer.wrap(buffer, offset, length)); 61 } 62 CodedOutputByteBufferNano(final ByteBuffer buffer)63 private CodedOutputByteBufferNano(final ByteBuffer buffer) { 64 this.buffer = buffer; 65 this.buffer.order(ByteOrder.LITTLE_ENDIAN); 66 } 67 68 /** 69 * Create a new {@code CodedOutputStream} that writes directly to the given 70 * byte array. If more bytes are written than fit in the array, 71 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 72 * array is faster than writing to an {@code OutputStream}. 73 */ newInstance(final byte[] flatArray)74 public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) { 75 return newInstance(flatArray, 0, flatArray.length); 76 } 77 78 /** 79 * Create a new {@code CodedOutputStream} that writes directly to the given 80 * byte array slice. If more bytes are written than fit in the slice, 81 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 82 * array is faster than writing to an {@code OutputStream}. 83 */ newInstance(final byte[] flatArray, final int offset, final int length)84 public static CodedOutputByteBufferNano newInstance(final byte[] flatArray, 85 final int offset, 86 final int length) { 87 return new CodedOutputByteBufferNano(flatArray, offset, length); 88 } 89 90 // ----------------------------------------------------------------- 91 92 /** Write a {@code double} field, including tag, to the stream. */ writeDouble(final int fieldNumber, final double value)93 public void writeDouble(final int fieldNumber, final double value) 94 throws IOException { 95 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 96 writeDoubleNoTag(value); 97 } 98 99 /** Write a {@code float} field, including tag, to the stream. */ writeFloat(final int fieldNumber, final float value)100 public void writeFloat(final int fieldNumber, final float value) 101 throws IOException { 102 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 103 writeFloatNoTag(value); 104 } 105 106 /** Write a {@code uint64} field, including tag, to the stream. */ writeUInt64(final int fieldNumber, final long value)107 public void writeUInt64(final int fieldNumber, final long value) 108 throws IOException { 109 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 110 writeUInt64NoTag(value); 111 } 112 113 /** Write an {@code int64} field, including tag, to the stream. */ writeInt64(final int fieldNumber, final long value)114 public void writeInt64(final int fieldNumber, final long value) 115 throws IOException { 116 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 117 writeInt64NoTag(value); 118 } 119 120 /** Write an {@code int32} field, including tag, to the stream. */ writeInt32(final int fieldNumber, final int value)121 public void writeInt32(final int fieldNumber, final int value) 122 throws IOException { 123 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 124 writeInt32NoTag(value); 125 } 126 127 /** Write a {@code fixed64} field, including tag, to the stream. */ writeFixed64(final int fieldNumber, final long value)128 public void writeFixed64(final int fieldNumber, final long value) 129 throws IOException { 130 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 131 writeFixed64NoTag(value); 132 } 133 134 /** Write a {@code fixed32} field, including tag, to the stream. */ writeFixed32(final int fieldNumber, final int value)135 public void writeFixed32(final int fieldNumber, final int value) 136 throws IOException { 137 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 138 writeFixed32NoTag(value); 139 } 140 141 /** Write a {@code bool} field, including tag, to the stream. */ writeBool(final int fieldNumber, final boolean value)142 public void writeBool(final int fieldNumber, final boolean value) 143 throws IOException { 144 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 145 writeBoolNoTag(value); 146 } 147 148 /** Write a {@code string} field, including tag, to the stream. */ writeString(final int fieldNumber, final String value)149 public void writeString(final int fieldNumber, final String value) 150 throws IOException { 151 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 152 writeStringNoTag(value); 153 } 154 155 /** Write a {@code group} field, including tag, to the stream. */ writeGroup(final int fieldNumber, final MessageNano value)156 public void writeGroup(final int fieldNumber, final MessageNano value) 157 throws IOException { 158 writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP); 159 writeGroupNoTag(value); 160 writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); 161 } 162 163 /** Write an embedded message field, including tag, to the stream. */ writeMessage(final int fieldNumber, final MessageNano value)164 public void writeMessage(final int fieldNumber, final MessageNano value) 165 throws IOException { 166 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 167 writeMessageNoTag(value); 168 } 169 170 /** Write a {@code bytes} field, including tag, to the stream. */ writeBytes(final int fieldNumber, final byte[] value)171 public void writeBytes(final int fieldNumber, final byte[] value) 172 throws IOException { 173 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 174 writeBytesNoTag(value); 175 } 176 177 /** Write a {@code bytes} field, including tag, to the stream. */ writeBytes(final int fieldNumber, final byte[] value, final int offset, final int length)178 public void writeBytes(final int fieldNumber, final byte[] value, 179 final int offset, final int length) 180 throws IOException { 181 writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 182 writeBytesNoTag(value, offset, length); 183 } 184 185 /** Write a {@code uint32} field, including tag, to the stream. */ writeUInt32(final int fieldNumber, final int value)186 public void writeUInt32(final int fieldNumber, final int value) 187 throws IOException { 188 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 189 writeUInt32NoTag(value); 190 } 191 192 /** 193 * Write an enum field, including tag, to the stream. Caller is responsible 194 * for converting the enum value to its numeric value. 195 */ writeEnum(final int fieldNumber, final int value)196 public void writeEnum(final int fieldNumber, final int value) 197 throws IOException { 198 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 199 writeEnumNoTag(value); 200 } 201 202 /** Write an {@code sfixed32} field, including tag, to the stream. */ writeSFixed32(final int fieldNumber, final int value)203 public void writeSFixed32(final int fieldNumber, final int value) 204 throws IOException { 205 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); 206 writeSFixed32NoTag(value); 207 } 208 209 /** Write an {@code sfixed64} field, including tag, to the stream. */ writeSFixed64(final int fieldNumber, final long value)210 public void writeSFixed64(final int fieldNumber, final long value) 211 throws IOException { 212 writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); 213 writeSFixed64NoTag(value); 214 } 215 216 /** Write an {@code sint32} field, including tag, to the stream. */ writeSInt32(final int fieldNumber, final int value)217 public void writeSInt32(final int fieldNumber, final int value) 218 throws IOException { 219 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 220 writeSInt32NoTag(value); 221 } 222 223 /** Write an {@code sint64} field, including tag, to the stream. */ writeSInt64(final int fieldNumber, final long value)224 public void writeSInt64(final int fieldNumber, final long value) 225 throws IOException { 226 writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); 227 writeSInt64NoTag(value); 228 } 229 230 /** 231 * Write a MessageSet extension field to the stream. For historical reasons, 232 * the wire format differs from normal fields. 233 */ 234 // public void writeMessageSetExtension(final int fieldNumber, 235 // final MessageMicro value) 236 // throws IOException { 237 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 238 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 239 // writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 240 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 241 // } 242 243 /** 244 * Write an unparsed MessageSet extension field to the stream. For 245 * historical reasons, the wire format differs from normal fields. 246 */ 247 // public void writeRawMessageSetExtension(final int fieldNumber, 248 // final ByteStringMicro value) 249 // throws IOException { 250 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 251 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 252 // writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 253 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 254 // } 255 256 // ----------------------------------------------------------------- 257 258 /** Write a {@code double} field to the stream. */ writeDoubleNoTag(final double value)259 public void writeDoubleNoTag(final double value) throws IOException { 260 writeRawLittleEndian64(Double.doubleToLongBits(value)); 261 } 262 263 /** Write a {@code float} field to the stream. */ writeFloatNoTag(final float value)264 public void writeFloatNoTag(final float value) throws IOException { 265 writeRawLittleEndian32(Float.floatToIntBits(value)); 266 } 267 268 /** Write a {@code uint64} field to the stream. */ writeUInt64NoTag(final long value)269 public void writeUInt64NoTag(final long value) throws IOException { 270 writeRawVarint64(value); 271 } 272 273 /** Write an {@code int64} field to the stream. */ writeInt64NoTag(final long value)274 public void writeInt64NoTag(final long value) throws IOException { 275 writeRawVarint64(value); 276 } 277 278 /** Write an {@code int32} field to the stream. */ writeInt32NoTag(final int value)279 public void writeInt32NoTag(final int value) throws IOException { 280 if (value >= 0) { 281 writeRawVarint32(value); 282 } else { 283 // Must sign-extend. 284 writeRawVarint64(value); 285 } 286 } 287 288 /** Write a {@code fixed64} field to the stream. */ writeFixed64NoTag(final long value)289 public void writeFixed64NoTag(final long value) throws IOException { 290 writeRawLittleEndian64(value); 291 } 292 293 /** Write a {@code fixed32} field to the stream. */ writeFixed32NoTag(final int value)294 public void writeFixed32NoTag(final int value) throws IOException { 295 writeRawLittleEndian32(value); 296 } 297 298 /** Write a {@code bool} field to the stream. */ writeBoolNoTag(final boolean value)299 public void writeBoolNoTag(final boolean value) throws IOException { 300 writeRawByte(value ? 1 : 0); 301 } 302 303 /** Write a {@code string} field to the stream. */ writeStringNoTag(final String value)304 public void writeStringNoTag(final String value) throws IOException { 305 // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), 306 // and at most 3 times of it. Optimize for the case where we know this length results in a 307 // constant varint length - saves measuring length of the string. 308 try { 309 final int minLengthVarIntSize = computeRawVarint32Size(value.length()); 310 final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION); 311 if (minLengthVarIntSize == maxLengthVarIntSize) { 312 int oldPosition = buffer.position(); 313 // Buffer.position, when passed a position that is past its limit, throws 314 // IllegalArgumentException, and this class is documented to throw 315 // OutOfSpaceException instead. 316 if (buffer.remaining() < minLengthVarIntSize) { 317 throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit()); 318 } 319 buffer.position(oldPosition + minLengthVarIntSize); 320 encode(value, buffer); 321 int newPosition = buffer.position(); 322 buffer.position(oldPosition); 323 writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize); 324 buffer.position(newPosition); 325 } else { 326 writeRawVarint32(encodedLength(value)); 327 encode(value, buffer); 328 } 329 } catch (BufferOverflowException e) { 330 final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(), 331 buffer.limit()); 332 outOfSpaceException.initCause(e); 333 throw outOfSpaceException; 334 } 335 } 336 337 // These UTF-8 handling methods are copied from Guava's Utf8 class. 338 /** 339 * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string, 340 * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in 341 * both time and space. 342 * 343 * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired 344 * surrogates) 345 */ encodedLength(CharSequence sequence)346 private static int encodedLength(CharSequence sequence) { 347 // Warning to maintainers: this implementation is highly optimized. 348 int utf16Length = sequence.length(); 349 int utf8Length = utf16Length; 350 int i = 0; 351 352 // This loop optimizes for pure ASCII. 353 while (i < utf16Length && sequence.charAt(i) < 0x80) { 354 i++; 355 } 356 357 // This loop optimizes for chars less than 0x800. 358 for (; i < utf16Length; i++) { 359 char c = sequence.charAt(i); 360 if (c < 0x800) { 361 utf8Length += ((0x7f - c) >>> 31); // branch free! 362 } else { 363 utf8Length += encodedLengthGeneral(sequence, i); 364 break; 365 } 366 } 367 368 if (utf8Length < utf16Length) { 369 // Necessary and sufficient condition for overflow because of maximum 3x expansion 370 throw new IllegalArgumentException("UTF-8 length does not fit in int: " 371 + (utf8Length + (1L << 32))); 372 } 373 return utf8Length; 374 } 375 encodedLengthGeneral(CharSequence sequence, int start)376 private static int encodedLengthGeneral(CharSequence sequence, int start) { 377 int utf16Length = sequence.length(); 378 int utf8Length = 0; 379 for (int i = start; i < utf16Length; i++) { 380 char c = sequence.charAt(i); 381 if (c < 0x800) { 382 utf8Length += (0x7f - c) >>> 31; // branch free! 383 } else { 384 utf8Length += 2; 385 // jdk7+: if (Character.isSurrogate(c)) { 386 if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) { 387 // Check that we have a well-formed surrogate pair. 388 int cp = Character.codePointAt(sequence, i); 389 if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) { 390 throw new IllegalArgumentException("Unpaired surrogate at index " + i); 391 } 392 i++; 393 } 394 } 395 } 396 return utf8Length; 397 } 398 399 /** 400 * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is 401 * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time 402 * and space. Bytes are written starting at the current position. This method requires paired 403 * surrogates, and therefore does not support chunking. 404 * 405 * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to 406 * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the 407 * largest possible number of bytes that any input can be encoded to. 408 * 409 * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired 410 * surrogates) 411 * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in 412 * {@code byteBuffer}'s remaining space. 413 * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer. 414 */ encode(CharSequence sequence, ByteBuffer byteBuffer)415 private static void encode(CharSequence sequence, ByteBuffer byteBuffer) { 416 if (byteBuffer.isReadOnly()) { 417 throw new ReadOnlyBufferException(); 418 } else if (byteBuffer.hasArray()) { 419 try { 420 int encoded = encode(sequence, 421 byteBuffer.array(), 422 byteBuffer.arrayOffset() + byteBuffer.position(), 423 byteBuffer.remaining()); 424 byteBuffer.position(encoded - byteBuffer.arrayOffset()); 425 } catch (ArrayIndexOutOfBoundsException e) { 426 BufferOverflowException boe = new BufferOverflowException(); 427 boe.initCause(e); 428 throw boe; 429 } 430 } else { 431 encodeDirect(sequence, byteBuffer); 432 } 433 } 434 encodeDirect(CharSequence sequence, ByteBuffer byteBuffer)435 private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) { 436 int utf16Length = sequence.length(); 437 for (int i = 0; i < utf16Length; i++) { 438 final char c = sequence.charAt(i); 439 if (c < 0x80) { // ASCII 440 byteBuffer.put((byte) c); 441 } else if (c < 0x800) { // 11 bits, two UTF-8 bytes 442 byteBuffer.put((byte) ((0xF << 6) | (c >>> 6))); 443 byteBuffer.put((byte) (0x80 | (0x3F & c))); 444 } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) { 445 // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes 446 byteBuffer.put((byte) ((0xF << 5) | (c >>> 12))); 447 byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6)))); 448 byteBuffer.put((byte) (0x80 | (0x3F & c))); 449 } else { 450 final char low; 451 if (i + 1 == sequence.length() 452 || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { 453 throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); 454 } 455 int codePoint = Character.toCodePoint(c, low); 456 byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18))); 457 byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12)))); 458 byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6)))); 459 byteBuffer.put((byte) (0x80 | (0x3F & codePoint))); 460 } 461 } 462 } 463 encode(CharSequence sequence, byte[] bytes, int offset, int length)464 private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) { 465 int utf16Length = sequence.length(); 466 int j = offset; 467 int i = 0; 468 int limit = offset + length; 469 // Designed to take advantage of 470 // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination 471 for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) { 472 bytes[j + i] = (byte) c; 473 } 474 if (i == utf16Length) { 475 return j + utf16Length; 476 } 477 j += i; 478 for (char c; i < utf16Length; i++) { 479 c = sequence.charAt(i); 480 if (c < 0x80 && j < limit) { 481 bytes[j++] = (byte) c; 482 } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes 483 bytes[j++] = (byte) ((0xF << 6) | (c >>> 6)); 484 bytes[j++] = (byte) (0x80 | (0x3F & c)); 485 } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) { 486 // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes 487 bytes[j++] = (byte) ((0xF << 5) | (c >>> 12)); 488 bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6))); 489 bytes[j++] = (byte) (0x80 | (0x3F & c)); 490 } else if (j <= limit - 4) { 491 // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes 492 final char low; 493 if (i + 1 == sequence.length() 494 || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { 495 throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); 496 } 497 int codePoint = Character.toCodePoint(c, low); 498 bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18)); 499 bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12))); 500 bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6))); 501 bytes[j++] = (byte) (0x80 | (0x3F & codePoint)); 502 } else { 503 throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j); 504 } 505 } 506 return j; 507 } 508 509 // End guava UTF-8 methods 510 511 512 /** Write a {@code group} field to the stream. */ writeGroupNoTag(final MessageNano value)513 public void writeGroupNoTag(final MessageNano value) throws IOException { 514 value.writeTo(this); 515 } 516 517 /** Write an embedded message field to the stream. */ writeMessageNoTag(final MessageNano value)518 public void writeMessageNoTag(final MessageNano value) throws IOException { 519 writeRawVarint32(value.getCachedSize()); 520 value.writeTo(this); 521 } 522 523 /** Write a {@code bytes} field to the stream. */ writeBytesNoTag(final byte[] value)524 public void writeBytesNoTag(final byte[] value) throws IOException { 525 writeRawVarint32(value.length); 526 writeRawBytes(value); 527 } 528 529 /** Write a {@code bytes} field to the stream. */ writeBytesNoTag(final byte[] value, final int offset, final int length)530 public void writeBytesNoTag(final byte[] value, final int offset, final int length) 531 throws IOException { 532 writeRawVarint32(length); 533 writeRawBytes(value, offset, length); 534 } 535 536 /** Write a {@code uint32} field to the stream. */ writeUInt32NoTag(final int value)537 public void writeUInt32NoTag(final int value) throws IOException { 538 writeRawVarint32(value); 539 } 540 541 /** 542 * Write an enum field to the stream. Caller is responsible 543 * for converting the enum value to its numeric value. 544 */ writeEnumNoTag(final int value)545 public void writeEnumNoTag(final int value) throws IOException { 546 writeRawVarint32(value); 547 } 548 549 /** Write an {@code sfixed32} field to the stream. */ writeSFixed32NoTag(final int value)550 public void writeSFixed32NoTag(final int value) throws IOException { 551 writeRawLittleEndian32(value); 552 } 553 554 /** Write an {@code sfixed64} field to the stream. */ writeSFixed64NoTag(final long value)555 public void writeSFixed64NoTag(final long value) throws IOException { 556 writeRawLittleEndian64(value); 557 } 558 559 /** Write an {@code sint32} field to the stream. */ writeSInt32NoTag(final int value)560 public void writeSInt32NoTag(final int value) throws IOException { 561 writeRawVarint32(encodeZigZag32(value)); 562 } 563 564 /** Write an {@code sint64} field to the stream. */ writeSInt64NoTag(final long value)565 public void writeSInt64NoTag(final long value) throws IOException { 566 writeRawVarint64(encodeZigZag64(value)); 567 } 568 569 // ================================================================= 570 571 /** 572 * Compute the number of bytes that would be needed to encode a 573 * {@code double} field, including tag. 574 */ computeDoubleSize(final int fieldNumber, final double value)575 public static int computeDoubleSize(final int fieldNumber, 576 final double value) { 577 return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); 578 } 579 580 /** 581 * Compute the number of bytes that would be needed to encode a 582 * {@code float} field, including tag. 583 */ computeFloatSize(final int fieldNumber, final float value)584 public static int computeFloatSize(final int fieldNumber, final float value) { 585 return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); 586 } 587 588 /** 589 * Compute the number of bytes that would be needed to encode a 590 * {@code uint64} field, including tag. 591 */ computeUInt64Size(final int fieldNumber, final long value)592 public static int computeUInt64Size(final int fieldNumber, final long value) { 593 return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); 594 } 595 596 /** 597 * Compute the number of bytes that would be needed to encode an 598 * {@code int64} field, including tag. 599 */ computeInt64Size(final int fieldNumber, final long value)600 public static int computeInt64Size(final int fieldNumber, final long value) { 601 return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); 602 } 603 604 /** 605 * Compute the number of bytes that would be needed to encode an 606 * {@code int32} field, including tag. 607 */ computeInt32Size(final int fieldNumber, final int value)608 public static int computeInt32Size(final int fieldNumber, final int value) { 609 return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); 610 } 611 612 /** 613 * Compute the number of bytes that would be needed to encode a 614 * {@code fixed64} field, including tag. 615 */ computeFixed64Size(final int fieldNumber, final long value)616 public static int computeFixed64Size(final int fieldNumber, 617 final long value) { 618 return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); 619 } 620 621 /** 622 * Compute the number of bytes that would be needed to encode a 623 * {@code fixed32} field, including tag. 624 */ computeFixed32Size(final int fieldNumber, final int value)625 public static int computeFixed32Size(final int fieldNumber, 626 final int value) { 627 return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); 628 } 629 630 /** 631 * Compute the number of bytes that would be needed to encode a 632 * {@code bool} field, including tag. 633 */ computeBoolSize(final int fieldNumber, final boolean value)634 public static int computeBoolSize(final int fieldNumber, 635 final boolean value) { 636 return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); 637 } 638 639 /** 640 * Compute the number of bytes that would be needed to encode a 641 * {@code string} field, including tag. 642 */ computeStringSize(final int fieldNumber, final String value)643 public static int computeStringSize(final int fieldNumber, 644 final String value) { 645 return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); 646 } 647 648 /** 649 * Compute the number of bytes that would be needed to encode a 650 * {@code group} field, including tag. 651 */ computeGroupSize(final int fieldNumber, final MessageNano value)652 public static int computeGroupSize(final int fieldNumber, 653 final MessageNano value) { 654 return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); 655 } 656 657 /** 658 * Compute the number of bytes that would be needed to encode an 659 * embedded message field, including tag. 660 */ computeMessageSize(final int fieldNumber, final MessageNano value)661 public static int computeMessageSize(final int fieldNumber, 662 final MessageNano value) { 663 return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); 664 } 665 666 /** 667 * Compute the number of bytes that would be needed to encode a 668 * {@code bytes} field, including tag. 669 */ computeBytesSize(final int fieldNumber, final byte[] value)670 public static int computeBytesSize(final int fieldNumber, 671 final byte[] value) { 672 return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); 673 } 674 675 /** 676 * Compute the number of bytes that would be needed to encode a 677 * {@code bytes} field of the given length, including tag. 678 */ computeBytesSize(final int fieldNumber, final int length)679 public static int computeBytesSize(final int fieldNumber, 680 final int length) { 681 return computeTagSize(fieldNumber) + computeBytesSizeNoTag(length); 682 } 683 684 /** 685 * Compute the number of bytes that would be needed to encode a 686 * {@code uint32} field, including tag. 687 */ computeUInt32Size(final int fieldNumber, final int value)688 public static int computeUInt32Size(final int fieldNumber, final int value) { 689 return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); 690 } 691 692 /** 693 * Compute the number of bytes that would be needed to encode an 694 * enum field, including tag. Caller is responsible for converting the 695 * enum value to its numeric value. 696 */ computeEnumSize(final int fieldNumber, final int value)697 public static int computeEnumSize(final int fieldNumber, final int value) { 698 return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); 699 } 700 701 /** 702 * Compute the number of bytes that would be needed to encode an 703 * {@code sfixed32} field, including tag. 704 */ computeSFixed32Size(final int fieldNumber, final int value)705 public static int computeSFixed32Size(final int fieldNumber, 706 final int value) { 707 return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); 708 } 709 710 /** 711 * Compute the number of bytes that would be needed to encode an 712 * {@code sfixed64} field, including tag. 713 */ computeSFixed64Size(final int fieldNumber, final long value)714 public static int computeSFixed64Size(final int fieldNumber, 715 final long value) { 716 return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); 717 } 718 719 /** 720 * Compute the number of bytes that would be needed to encode an 721 * {@code sint32} field, including tag. 722 */ computeSInt32Size(final int fieldNumber, final int value)723 public static int computeSInt32Size(final int fieldNumber, final int value) { 724 return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); 725 } 726 727 /** 728 * Compute the number of bytes that would be needed to encode an 729 * {@code sint64} field, including tag. 730 */ computeSInt64Size(final int fieldNumber, final long value)731 public static int computeSInt64Size(final int fieldNumber, final long value) { 732 return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); 733 } 734 735 /** 736 * Compute the number of bytes that would be needed to encode a 737 * MessageSet extension to the stream. For historical reasons, 738 * the wire format differs from normal fields. 739 */ 740 // public static int computeMessageSetExtensionSize( 741 // final int fieldNumber, final MessageMicro value) { 742 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 743 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 744 // computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 745 // } 746 747 /** 748 * Compute the number of bytes that would be needed to encode an 749 * unparsed MessageSet extension field to the stream. For 750 * historical reasons, the wire format differs from normal fields. 751 */ 752 // public static int computeRawMessageSetExtensionSize( 753 // final int fieldNumber, final ByteStringMicro value) { 754 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 755 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 756 // computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 757 // } 758 759 // ----------------------------------------------------------------- 760 761 /** 762 * Compute the number of bytes that would be needed to encode a 763 * {@code double} field, including tag. 764 */ computeDoubleSizeNoTag(final double value)765 public static int computeDoubleSizeNoTag(final double value) { 766 return LITTLE_ENDIAN_64_SIZE; 767 } 768 769 /** 770 * Compute the number of bytes that would be needed to encode a 771 * {@code float} field, including tag. 772 */ computeFloatSizeNoTag(final float value)773 public static int computeFloatSizeNoTag(final float value) { 774 return LITTLE_ENDIAN_32_SIZE; 775 } 776 777 /** 778 * Compute the number of bytes that would be needed to encode a 779 * {@code uint64} field, including tag. 780 */ computeUInt64SizeNoTag(final long value)781 public static int computeUInt64SizeNoTag(final long value) { 782 return computeRawVarint64Size(value); 783 } 784 785 /** 786 * Compute the number of bytes that would be needed to encode an 787 * {@code int64} field, including tag. 788 */ computeInt64SizeNoTag(final long value)789 public static int computeInt64SizeNoTag(final long value) { 790 return computeRawVarint64Size(value); 791 } 792 793 /** 794 * Compute the number of bytes that would be needed to encode an 795 * {@code int32} field, including tag. 796 */ computeInt32SizeNoTag(final int value)797 public static int computeInt32SizeNoTag(final int value) { 798 if (value >= 0) { 799 return computeRawVarint32Size(value); 800 } else { 801 // Must sign-extend. 802 return 10; 803 } 804 } 805 806 /** 807 * Compute the number of bytes that would be needed to encode a 808 * {@code fixed64} field. 809 */ computeFixed64SizeNoTag(final long value)810 public static int computeFixed64SizeNoTag(final long value) { 811 return LITTLE_ENDIAN_64_SIZE; 812 } 813 814 /** 815 * Compute the number of bytes that would be needed to encode a 816 * {@code fixed32} field. 817 */ computeFixed32SizeNoTag(final int value)818 public static int computeFixed32SizeNoTag(final int value) { 819 return LITTLE_ENDIAN_32_SIZE; 820 } 821 822 /** 823 * Compute the number of bytes that would be needed to encode a 824 * {@code bool} field. 825 */ computeBoolSizeNoTag(final boolean value)826 public static int computeBoolSizeNoTag(final boolean value) { 827 return 1; 828 } 829 830 /** 831 * Compute the number of bytes that would be needed to encode a 832 * {@code string} field. 833 */ computeStringSizeNoTag(final String value)834 public static int computeStringSizeNoTag(final String value) { 835 final int length = encodedLength(value); 836 return computeRawVarint32Size(length) + length; 837 } 838 839 /** 840 * Compute the number of bytes that would be needed to encode a 841 * {@code group} field. 842 */ computeGroupSizeNoTag(final MessageNano value)843 public static int computeGroupSizeNoTag(final MessageNano value) { 844 return value.getSerializedSize(); 845 } 846 847 /** 848 * Compute the number of bytes that would be needed to encode an embedded 849 * message field. 850 */ computeMessageSizeNoTag(final MessageNano value)851 public static int computeMessageSizeNoTag(final MessageNano value) { 852 final int size = value.getSerializedSize(); 853 return computeRawVarint32Size(size) + size; 854 } 855 856 /** 857 * Compute the number of bytes that would be needed to encode a 858 * {@code bytes} field. 859 */ computeBytesSizeNoTag(final byte[] value)860 public static int computeBytesSizeNoTag(final byte[] value) { 861 return computeRawVarint32Size(value.length) + value.length; 862 } 863 864 /** 865 * Compute the number of bytes that would be needed to encode a 866 * {@code bytes} field of the given length. 867 */ computeBytesSizeNoTag(final int length)868 public static int computeBytesSizeNoTag(final int length) { 869 return computeRawVarint32Size(length) + length; 870 } 871 872 /** 873 * Compute the number of bytes that would be needed to encode a 874 * {@code uint32} field. 875 */ computeUInt32SizeNoTag(final int value)876 public static int computeUInt32SizeNoTag(final int value) { 877 return computeRawVarint32Size(value); 878 } 879 880 /** 881 * Compute the number of bytes that would be needed to encode an enum field. 882 * Caller is responsible for converting the enum value to its numeric value. 883 */ computeEnumSizeNoTag(final int value)884 public static int computeEnumSizeNoTag(final int value) { 885 return computeRawVarint32Size(value); 886 } 887 888 /** 889 * Compute the number of bytes that would be needed to encode an 890 * {@code sfixed32} field. 891 */ computeSFixed32SizeNoTag(final int value)892 public static int computeSFixed32SizeNoTag(final int value) { 893 return LITTLE_ENDIAN_32_SIZE; 894 } 895 896 /** 897 * Compute the number of bytes that would be needed to encode an 898 * {@code sfixed64} field. 899 */ computeSFixed64SizeNoTag(final long value)900 public static int computeSFixed64SizeNoTag(final long value) { 901 return LITTLE_ENDIAN_64_SIZE; 902 } 903 904 /** 905 * Compute the number of bytes that would be needed to encode an 906 * {@code sint32} field. 907 */ computeSInt32SizeNoTag(final int value)908 public static int computeSInt32SizeNoTag(final int value) { 909 return computeRawVarint32Size(encodeZigZag32(value)); 910 } 911 912 /** 913 * Compute the number of bytes that would be needed to encode an 914 * {@code sint64} field. 915 */ computeSInt64SizeNoTag(final long value)916 public static int computeSInt64SizeNoTag(final long value) { 917 return computeRawVarint64Size(encodeZigZag64(value)); 918 } 919 920 // ================================================================= 921 922 /** 923 * If writing to a flat array, return the space left in the array. 924 * Otherwise, throws {@code UnsupportedOperationException}. 925 */ spaceLeft()926 public int spaceLeft() { 927 return buffer.remaining(); 928 } 929 930 /** 931 * Verifies that {@link #spaceLeft()} returns zero. It's common to create 932 * a byte array that is exactly big enough to hold a message, then write to 933 * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} 934 * after writing verifies that the message was actually as big as expected, 935 * which can help catch bugs. 936 */ checkNoSpaceLeft()937 public void checkNoSpaceLeft() { 938 if (spaceLeft() != 0) { 939 throw new IllegalStateException( 940 "Did not write as much data as expected."); 941 } 942 } 943 944 /** 945 * Returns the position within the internal buffer. 946 */ position()947 public int position() { 948 return buffer.position(); 949 } 950 951 /** 952 * Resets the position within the internal buffer to zero. 953 * 954 * @see #position 955 * @see #spaceLeft 956 */ reset()957 public void reset() { 958 buffer.clear(); 959 } 960 961 /** 962 * If you create a CodedOutputStream around a simple flat array, you must 963 * not attempt to write more bytes than the array has space. Otherwise, 964 * this exception will be thrown. 965 */ 966 public static class OutOfSpaceException extends IOException { 967 private static final long serialVersionUID = -6947486886997889499L; 968 OutOfSpaceException(int position, int limit)969 OutOfSpaceException(int position, int limit) { 970 super("CodedOutputStream was writing to a flat byte array and ran " + 971 "out of space (pos " + position + " limit " + limit + ")."); 972 } 973 } 974 975 /** Write a single byte. */ writeRawByte(final byte value)976 public void writeRawByte(final byte value) throws IOException { 977 if (!buffer.hasRemaining()) { 978 // We're writing to a single buffer. 979 throw new OutOfSpaceException(buffer.position(), buffer.limit()); 980 } 981 982 buffer.put(value); 983 } 984 985 /** Write a single byte, represented by an integer value. */ writeRawByte(final int value)986 public void writeRawByte(final int value) throws IOException { 987 writeRawByte((byte) value); 988 } 989 990 /** Write an array of bytes. */ writeRawBytes(final byte[] value)991 public void writeRawBytes(final byte[] value) throws IOException { 992 writeRawBytes(value, 0, value.length); 993 } 994 995 /** Write part of an array of bytes. */ writeRawBytes(final byte[] value, int offset, int length)996 public void writeRawBytes(final byte[] value, int offset, int length) 997 throws IOException { 998 if (buffer.remaining() >= length) { 999 buffer.put(value, offset, length); 1000 } else { 1001 // We're writing to a single buffer. 1002 throw new OutOfSpaceException(buffer.position(), buffer.limit()); 1003 } 1004 } 1005 1006 /** Encode and write a tag. */ writeTag(final int fieldNumber, final int wireType)1007 public void writeTag(final int fieldNumber, final int wireType) 1008 throws IOException { 1009 writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType)); 1010 } 1011 1012 /** Compute the number of bytes that would be needed to encode a tag. */ computeTagSize(final int fieldNumber)1013 public static int computeTagSize(final int fieldNumber) { 1014 return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0)); 1015 } 1016 1017 /** 1018 * Encode and write a varint. {@code value} is treated as 1019 * unsigned, so it won't be sign-extended if negative. 1020 */ writeRawVarint32(int value)1021 public void writeRawVarint32(int value) throws IOException { 1022 while (true) { 1023 if ((value & ~0x7F) == 0) { 1024 writeRawByte(value); 1025 return; 1026 } else { 1027 writeRawByte((value & 0x7F) | 0x80); 1028 value >>>= 7; 1029 } 1030 } 1031 } 1032 1033 /** 1034 * Compute the number of bytes that would be needed to encode a varint. 1035 * {@code value} is treated as unsigned, so it won't be sign-extended if 1036 * negative. 1037 */ computeRawVarint32Size(final int value)1038 public static int computeRawVarint32Size(final int value) { 1039 if ((value & (0xffffffff << 7)) == 0) return 1; 1040 if ((value & (0xffffffff << 14)) == 0) return 2; 1041 if ((value & (0xffffffff << 21)) == 0) return 3; 1042 if ((value & (0xffffffff << 28)) == 0) return 4; 1043 return 5; 1044 } 1045 1046 /** Encode and write a varint. */ writeRawVarint64(long value)1047 public void writeRawVarint64(long value) throws IOException { 1048 while (true) { 1049 if ((value & ~0x7FL) == 0) { 1050 writeRawByte((int)value); 1051 return; 1052 } else { 1053 writeRawByte(((int)value & 0x7F) | 0x80); 1054 value >>>= 7; 1055 } 1056 } 1057 } 1058 1059 /** Compute the number of bytes that would be needed to encode a varint. */ computeRawVarint64Size(final long value)1060 public static int computeRawVarint64Size(final long value) { 1061 if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; 1062 if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; 1063 if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; 1064 if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; 1065 if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; 1066 if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; 1067 if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; 1068 if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; 1069 if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; 1070 return 10; 1071 } 1072 1073 /** Write a little-endian 32-bit integer. */ writeRawLittleEndian32(final int value)1074 public void writeRawLittleEndian32(final int value) throws IOException { 1075 if (buffer.remaining() < 4) { 1076 throw new OutOfSpaceException(buffer.position(), buffer.limit()); 1077 } 1078 buffer.putInt(value); 1079 } 1080 1081 public static final int LITTLE_ENDIAN_32_SIZE = 4; 1082 1083 /** Write a little-endian 64-bit integer. */ writeRawLittleEndian64(final long value)1084 public void writeRawLittleEndian64(final long value) throws IOException { 1085 if (buffer.remaining() < 8) { 1086 throw new OutOfSpaceException(buffer.position(), buffer.limit()); 1087 } 1088 buffer.putLong(value); 1089 } 1090 1091 public static final int LITTLE_ENDIAN_64_SIZE = 8; 1092 1093 /** 1094 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 1095 * into values that can be efficiently encoded with varint. (Otherwise, 1096 * negative values must be sign-extended to 64 bits to be varint encoded, 1097 * thus always taking 10 bytes on the wire.) 1098 * 1099 * @param n A signed 32-bit integer. 1100 * @return An unsigned 32-bit integer, stored in a signed int because 1101 * Java has no explicit unsigned support. 1102 */ encodeZigZag32(final int n)1103 public static int encodeZigZag32(final int n) { 1104 // Note: the right-shift must be arithmetic 1105 return (n << 1) ^ (n >> 31); 1106 } 1107 1108 /** 1109 * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 1110 * into values that can be efficiently encoded with varint. (Otherwise, 1111 * negative values must be sign-extended to 64 bits to be varint encoded, 1112 * thus always taking 10 bytes on the wire.) 1113 * 1114 * @param n A signed 64-bit integer. 1115 * @return An unsigned 64-bit integer, stored in a signed int because 1116 * Java has no explicit unsigned support. 1117 */ encodeZigZag64(final long n)1118 public static long encodeZigZag64(final long n) { 1119 // Note: the right-shift must be arithmetic 1120 return (n << 1) ^ (n >> 63); 1121 } 1122 computeFieldSize(int number, int type, Object object)1123 static int computeFieldSize(int number, int type, Object object) { 1124 switch (type) { 1125 case InternalNano.TYPE_BOOL: 1126 return computeBoolSize(number, (Boolean) object); 1127 case InternalNano.TYPE_BYTES: 1128 return computeBytesSize(number, (byte[]) object); 1129 case InternalNano.TYPE_STRING: 1130 return computeStringSize(number, (String) object); 1131 case InternalNano.TYPE_FLOAT: 1132 return computeFloatSize(number, (Float) object); 1133 case InternalNano.TYPE_DOUBLE: 1134 return computeDoubleSize(number, (Double) object); 1135 case InternalNano.TYPE_ENUM: 1136 return computeEnumSize(number, (Integer) object); 1137 case InternalNano.TYPE_FIXED32: 1138 return computeFixed32Size(number, (Integer) object); 1139 case InternalNano.TYPE_INT32: 1140 return computeInt32Size(number, (Integer) object); 1141 case InternalNano.TYPE_UINT32: 1142 return computeUInt32Size(number, (Integer) object); 1143 case InternalNano.TYPE_SINT32: 1144 return computeSInt32Size(number, (Integer) object); 1145 case InternalNano.TYPE_SFIXED32: 1146 return computeSFixed32Size(number, (Integer) object); 1147 case InternalNano.TYPE_INT64: 1148 return computeInt64Size(number, (Long) object); 1149 case InternalNano.TYPE_UINT64: 1150 return computeUInt64Size(number, (Long) object); 1151 case InternalNano.TYPE_SINT64: 1152 return computeSInt64Size(number, (Long) object); 1153 case InternalNano.TYPE_FIXED64: 1154 return computeFixed64Size(number, (Long) object); 1155 case InternalNano.TYPE_SFIXED64: 1156 return computeSFixed64Size(number, (Long) object); 1157 case InternalNano.TYPE_MESSAGE: 1158 return computeMessageSize(number, (MessageNano) object); 1159 case InternalNano.TYPE_GROUP: 1160 return computeGroupSize(number, (MessageNano) object); 1161 default: 1162 throw new IllegalArgumentException("Unknown type: " + type); 1163 } 1164 } 1165 writeField(int number, int type, Object value)1166 void writeField(int number, int type, Object value) 1167 throws IOException { 1168 switch (type) { 1169 case InternalNano.TYPE_DOUBLE: 1170 Double doubleValue = (Double) value; 1171 writeDouble(number, doubleValue); 1172 break; 1173 case InternalNano.TYPE_FLOAT: 1174 Float floatValue = (Float) value; 1175 writeFloat(number, floatValue); 1176 break; 1177 case InternalNano.TYPE_INT64: 1178 Long int64Value = (Long) value; 1179 writeInt64(number, int64Value); 1180 break; 1181 case InternalNano.TYPE_UINT64: 1182 Long uint64Value = (Long) value; 1183 writeUInt64(number, uint64Value); 1184 break; 1185 case InternalNano.TYPE_INT32: 1186 Integer int32Value = (Integer) value; 1187 writeInt32(number, int32Value); 1188 break; 1189 case InternalNano.TYPE_FIXED64: 1190 Long fixed64Value = (Long) value; 1191 writeFixed64(number, fixed64Value); 1192 break; 1193 case InternalNano.TYPE_FIXED32: 1194 Integer fixed32Value = (Integer) value; 1195 writeFixed32(number, fixed32Value); 1196 break; 1197 case InternalNano.TYPE_BOOL: 1198 Boolean boolValue = (Boolean) value; 1199 writeBool(number, boolValue); 1200 break; 1201 case InternalNano.TYPE_STRING: 1202 String stringValue = (String) value; 1203 writeString(number, stringValue); 1204 break; 1205 case InternalNano.TYPE_BYTES: 1206 byte[] bytesValue = (byte[]) value; 1207 writeBytes(number, bytesValue); 1208 break; 1209 case InternalNano.TYPE_UINT32: 1210 Integer uint32Value = (Integer) value; 1211 writeUInt32(number, uint32Value); 1212 break; 1213 case InternalNano.TYPE_ENUM: 1214 Integer enumValue = (Integer) value; 1215 writeEnum(number, enumValue); 1216 break; 1217 case InternalNano.TYPE_SFIXED32: 1218 Integer sfixed32Value = (Integer) value; 1219 writeSFixed32(number, sfixed32Value); 1220 break; 1221 case InternalNano.TYPE_SFIXED64: 1222 Long sfixed64Value = (Long) value; 1223 writeSFixed64(number, sfixed64Value); 1224 break; 1225 case InternalNano.TYPE_SINT32: 1226 Integer sint32Value = (Integer) value; 1227 writeSInt32(number, sint32Value); 1228 break; 1229 case InternalNano.TYPE_SINT64: 1230 Long sint64Value = (Long) value; 1231 writeSInt64(number, sint64Value); 1232 break; 1233 case InternalNano.TYPE_MESSAGE: 1234 MessageNano messageValue = (MessageNano) value; 1235 writeMessage(number, messageValue); 1236 break; 1237 case InternalNano.TYPE_GROUP: 1238 MessageNano groupValue = (MessageNano) value; 1239 writeGroup(number, groupValue); 1240 break; 1241 default: 1242 throw new IOException("Unknown type: " + type); 1243 } 1244 } 1245 1246 } 1247