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