1// Protocol Buffers - Google's data interchange format 2// Copyright 2013 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31package com.google.protobuf.nano; 32 33import java.io.IOException; 34import java.lang.reflect.Array; 35import java.util.ArrayList; 36import java.util.List; 37 38/** 39 * Represents an extension. 40 * 41 * @author bduff@google.com (Brian Duff) 42 * @author maxtroy@google.com (Max Cai) 43 * @param <M> the type of the extendable message this extension is for. 44 * @param <T> the Java type of the extension; see {@link #clazz}. 45 */ 46public class Extension<M extends ExtendableMessageNano<M>, T> { 47 48 /* 49 * Because we typically only define message-typed extensions, the Extension class hierarchy is 50 * designed as follows, to allow a big amount of code in this file to be removed by ProGuard: 51 * 52 * Extension // ready to use for message/group typed extensions 53 * Δ 54 * | 55 * PrimitiveExtension // for primitive/enum typed extensions 56 */ 57 58 public static final int TYPE_DOUBLE = 1; 59 public static final int TYPE_FLOAT = 2; 60 public static final int TYPE_INT64 = 3; 61 public static final int TYPE_UINT64 = 4; 62 public static final int TYPE_INT32 = 5; 63 public static final int TYPE_FIXED64 = 6; 64 public static final int TYPE_FIXED32 = 7; 65 public static final int TYPE_BOOL = 8; 66 public static final int TYPE_STRING = 9; 67 public static final int TYPE_GROUP = 10; 68 public static final int TYPE_MESSAGE = 11; 69 public static final int TYPE_BYTES = 12; 70 public static final int TYPE_UINT32 = 13; 71 public static final int TYPE_ENUM = 14; 72 public static final int TYPE_SFIXED32 = 15; 73 public static final int TYPE_SFIXED64 = 16; 74 public static final int TYPE_SINT32 = 17; 75 public static final int TYPE_SINT64 = 18; 76 77 /** 78 * Creates an {@code Extension} of the given message type and tag number. 79 * Should be used by the generated code only. 80 * 81 * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} 82 */ 83 public static <M extends ExtendableMessageNano<M>, T extends MessageNano> 84 Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) { 85 return new Extension<M, T>(type, clazz, tag, false); 86 } 87 88 /** 89 * Creates a repeated {@code Extension} of the given message type and tag number. 90 * Should be used by the generated code only. 91 * 92 * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} 93 */ 94 public static <M extends ExtendableMessageNano<M>, T extends MessageNano> 95 Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, int tag) { 96 return new Extension<M, T[]>(type, clazz, tag, true); 97 } 98 99 /** 100 * Creates an {@code Extension} of the given primitive type and tag number. 101 * Should be used by the generated code only. 102 * 103 * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} 104 * @param clazz the boxed Java type of this extension 105 */ 106 public static <M extends ExtendableMessageNano<M>, T> 107 Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, int tag) { 108 return new PrimitiveExtension<M, T>(type, clazz, tag, false, 0, 0); 109 } 110 111 /** 112 * Creates a repeated {@code Extension} of the given primitive type and tag number. 113 * Should be used by the generated code only. 114 * 115 * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} 116 * @param clazz the Java array type of this extension, with an unboxed component type 117 */ 118 public static <M extends ExtendableMessageNano<M>, T> 119 Extension<M, T> createRepeatedPrimitiveTyped( 120 int type, Class<T> clazz, int tag, int nonPackedTag, int packedTag) { 121 return new PrimitiveExtension<M, T>(type, clazz, tag, true, nonPackedTag, packedTag); 122 } 123 124 /** 125 * Protocol Buffer type of this extension; one of the {@code TYPE_} constants. 126 */ 127 protected final int type; 128 129 /** 130 * Java type of this extension. For a singular extension, this is the boxed Java type for the 131 * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose 132 * component type is the unboxed Java type for {@link #type}. For example, for a singular 133 * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a 134 * repeated {@code int32} extension, this equals {@code int[].class}. 135 */ 136 protected final Class<T> clazz; 137 138 /** 139 * Tag number of this extension. 140 */ 141 protected final int tag; 142 143 /** 144 * Whether this extension is repeated. 145 */ 146 protected final boolean repeated; 147 148 private Extension(int type, Class<T> clazz, int tag, boolean repeated) { 149 this.type = type; 150 this.clazz = clazz; 151 this.tag = tag; 152 this.repeated = repeated; 153 } 154 155 /** 156 * Returns the value of this extension stored in the given list of unknown fields, or 157 * {@code null} if no unknown fields matches this extension. 158 * 159 * @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag 160 * that matches this Extension's tag. 161 * 162 */ 163 final T getValueFrom(List<UnknownFieldData> unknownFields) { 164 if (unknownFields == null) { 165 return null; 166 } 167 return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields); 168 } 169 170 private T getRepeatedValueFrom(List<UnknownFieldData> unknownFields) { 171 // For repeated extensions, read all matching unknown fields in their original order. 172 List<Object> resultList = new ArrayList<Object>(); 173 for (int i = 0; i < unknownFields.size(); i++) { 174 UnknownFieldData data = unknownFields.get(i); 175 if (data.bytes.length != 0) { 176 readDataInto(data, resultList); 177 } 178 } 179 180 int resultSize = resultList.size(); 181 if (resultSize == 0) { 182 return null; 183 } else { 184 T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize)); 185 for (int i = 0; i < resultSize; i++) { 186 Array.set(result, i, resultList.get(i)); 187 } 188 return result; 189 } 190 } 191 192 private T getSingularValueFrom(List<UnknownFieldData> unknownFields) { 193 // For singular extensions, get the last piece of data stored under this extension. 194 if (unknownFields.isEmpty()) { 195 return null; 196 } 197 UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1); 198 return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes))); 199 } 200 201 protected Object readData(CodedInputByteBufferNano input) { 202 // This implementation is for message/group extensions. 203 Class<?> messageType = repeated ? clazz.getComponentType() : clazz; 204 try { 205 switch (type) { 206 case TYPE_GROUP: 207 MessageNano group = (MessageNano) messageType.newInstance(); 208 input.readGroup(group, WireFormatNano.getTagFieldNumber(tag)); 209 return group; 210 case TYPE_MESSAGE: 211 MessageNano message = (MessageNano) messageType.newInstance(); 212 input.readMessage(message); 213 return message; 214 default: 215 throw new IllegalArgumentException("Unknown type " + type); 216 } 217 } catch (InstantiationException e) { 218 throw new IllegalArgumentException( 219 "Error creating instance of class " + messageType, e); 220 } catch (IllegalAccessException e) { 221 throw new IllegalArgumentException( 222 "Error creating instance of class " + messageType, e); 223 } catch (IOException e) { 224 throw new IllegalArgumentException("Error reading extension field", e); 225 } 226 } 227 228 protected void readDataInto(UnknownFieldData data, List<Object> resultList) { 229 // This implementation is for message/group extensions. 230 resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); 231 } 232 233 void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException { 234 if (repeated) { 235 writeRepeatedData(value, output); 236 } else { 237 writeSingularData(value, output); 238 } 239 } 240 241 protected void writeSingularData(Object value, CodedOutputByteBufferNano out) { 242 // This implementation is for message/group extensions. 243 try { 244 out.writeRawVarint32(tag); 245 switch (type) { 246 case TYPE_GROUP: 247 MessageNano groupValue = (MessageNano) value; 248 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 249 out.writeGroupNoTag(groupValue); 250 // The endgroup tag must be included in the data payload. 251 out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); 252 break; 253 case TYPE_MESSAGE: 254 MessageNano messageValue = (MessageNano) value; 255 out.writeMessageNoTag(messageValue); 256 break; 257 default: 258 throw new IllegalArgumentException("Unknown type " + type); 259 } 260 } catch (IOException e) { 261 // Should not happen 262 throw new IllegalStateException(e); 263 } 264 } 265 266 protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { 267 // This implementation is for non-packed extensions. 268 int arrayLength = Array.getLength(array); 269 for (int i = 0; i < arrayLength; i++) { 270 Object element = Array.get(array, i); 271 if (element != null) { 272 writeSingularData(element, output); 273 } 274 } 275 } 276 277 int computeSerializedSize(Object value) { 278 if (repeated) { 279 return computeRepeatedSerializedSize(value); 280 } else { 281 return computeSingularSerializedSize(value); 282 } 283 } 284 285 protected int computeRepeatedSerializedSize(Object array) { 286 // This implementation is for non-packed extensions. 287 int size = 0; 288 int arrayLength = Array.getLength(array); 289 for (int i = 0; i < arrayLength; i++) { 290 Object element = Array.get(array, i); 291 if (element != null) { 292 size += computeSingularSerializedSize(Array.get(array, i)); 293 } 294 } 295 return size; 296 } 297 298 protected int computeSingularSerializedSize(Object value) { 299 // This implementation is for message/group extensions. 300 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 301 switch (type) { 302 case TYPE_GROUP: 303 MessageNano groupValue = (MessageNano) value; 304 return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue); 305 case TYPE_MESSAGE: 306 MessageNano messageValue = (MessageNano) value; 307 return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue); 308 default: 309 throw new IllegalArgumentException("Unknown type " + type); 310 } 311 } 312 313 /** 314 * Represents an extension of a primitive (including enum) type. If there is no primitive 315 * extensions, this subclass will be removable by ProGuard. 316 */ 317 private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T> 318 extends Extension<M, T> { 319 320 /** 321 * Tag of a piece of non-packed data from the wire compatible with this extension. 322 */ 323 private final int nonPackedTag; 324 325 /** 326 * Tag of a piece of packed data from the wire compatible with this extension. 327 * 0 if the type of this extension is not packable. 328 */ 329 private final int packedTag; 330 331 public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated, 332 int nonPackedTag, int packedTag) { 333 super(type, clazz, tag, repeated); 334 this.nonPackedTag = nonPackedTag; 335 this.packedTag = packedTag; 336 } 337 338 @Override 339 protected Object readData(CodedInputByteBufferNano input) { 340 try { 341 switch (type) { 342 case TYPE_DOUBLE: 343 return input.readDouble(); 344 case TYPE_FLOAT: 345 return input.readFloat(); 346 case TYPE_INT64: 347 return input.readInt64(); 348 case TYPE_UINT64: 349 return input.readUInt64(); 350 case TYPE_INT32: 351 return input.readInt32(); 352 case TYPE_FIXED64: 353 return input.readFixed64(); 354 case TYPE_FIXED32: 355 return input.readFixed32(); 356 case TYPE_BOOL: 357 return input.readBool(); 358 case TYPE_STRING: 359 return input.readString(); 360 case TYPE_BYTES: 361 return input.readBytes(); 362 case TYPE_UINT32: 363 return input.readUInt32(); 364 case TYPE_ENUM: 365 return input.readEnum(); 366 case TYPE_SFIXED32: 367 return input.readSFixed32(); 368 case TYPE_SFIXED64: 369 return input.readSFixed64(); 370 case TYPE_SINT32: 371 return input.readSInt32(); 372 case TYPE_SINT64: 373 return input.readSInt64(); 374 default: 375 throw new IllegalArgumentException("Unknown type " + type); 376 } 377 } catch (IOException e) { 378 throw new IllegalArgumentException("Error reading extension field", e); 379 } 380 } 381 382 @Override 383 protected void readDataInto(UnknownFieldData data, List<Object> resultList) { 384 // This implementation is for primitive typed extensions, 385 // which can read both packed and non-packed data. 386 if (data.tag == nonPackedTag) { 387 resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); 388 } else { 389 CodedInputByteBufferNano buffer = 390 CodedInputByteBufferNano.newInstance(data.bytes); 391 try { 392 buffer.pushLimit(buffer.readRawVarint32()); // length limit 393 } catch (IOException e) { 394 throw new IllegalArgumentException("Error reading extension field", e); 395 } 396 while (!buffer.isAtEnd()) { 397 resultList.add(readData(buffer)); 398 } 399 } 400 } 401 402 @Override 403 protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) { 404 try { 405 output.writeRawVarint32(tag); 406 switch (type) { 407 case TYPE_DOUBLE: 408 Double doubleValue = (Double) value; 409 output.writeDoubleNoTag(doubleValue); 410 break; 411 case TYPE_FLOAT: 412 Float floatValue = (Float) value; 413 output.writeFloatNoTag(floatValue); 414 break; 415 case TYPE_INT64: 416 Long int64Value = (Long) value; 417 output.writeInt64NoTag(int64Value); 418 break; 419 case TYPE_UINT64: 420 Long uint64Value = (Long) value; 421 output.writeUInt64NoTag(uint64Value); 422 break; 423 case TYPE_INT32: 424 Integer int32Value = (Integer) value; 425 output.writeInt32NoTag(int32Value); 426 break; 427 case TYPE_FIXED64: 428 Long fixed64Value = (Long) value; 429 output.writeFixed64NoTag(fixed64Value); 430 break; 431 case TYPE_FIXED32: 432 Integer fixed32Value = (Integer) value; 433 output.writeFixed32NoTag(fixed32Value); 434 break; 435 case TYPE_BOOL: 436 Boolean boolValue = (Boolean) value; 437 output.writeBoolNoTag(boolValue); 438 break; 439 case TYPE_STRING: 440 String stringValue = (String) value; 441 output.writeStringNoTag(stringValue); 442 break; 443 case TYPE_BYTES: 444 byte[] bytesValue = (byte[]) value; 445 output.writeBytesNoTag(bytesValue); 446 break; 447 case TYPE_UINT32: 448 Integer uint32Value = (Integer) value; 449 output.writeUInt32NoTag(uint32Value); 450 break; 451 case TYPE_ENUM: 452 Integer enumValue = (Integer) value; 453 output.writeEnumNoTag(enumValue); 454 break; 455 case TYPE_SFIXED32: 456 Integer sfixed32Value = (Integer) value; 457 output.writeSFixed32NoTag(sfixed32Value); 458 break; 459 case TYPE_SFIXED64: 460 Long sfixed64Value = (Long) value; 461 output.writeSFixed64NoTag(sfixed64Value); 462 break; 463 case TYPE_SINT32: 464 Integer sint32Value = (Integer) value; 465 output.writeSInt32NoTag(sint32Value); 466 break; 467 case TYPE_SINT64: 468 Long sint64Value = (Long) value; 469 output.writeSInt64NoTag(sint64Value); 470 break; 471 default: 472 throw new IllegalArgumentException("Unknown type " + type); 473 } 474 } catch (IOException e) { 475 // Should not happen 476 throw new IllegalStateException(e); 477 } 478 } 479 480 @Override 481 protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { 482 if (tag == nonPackedTag) { 483 // Use base implementation for non-packed data 484 super.writeRepeatedData(array, output); 485 } else if (tag == packedTag) { 486 // Packed. Note that the array element type is guaranteed to be primitive, so there 487 // won't be any null elements, so no null check in this block. 488 int arrayLength = Array.getLength(array); 489 int dataSize = computePackedDataSize(array); 490 491 try { 492 output.writeRawVarint32(tag); 493 output.writeRawVarint32(dataSize); 494 switch (type) { 495 case TYPE_BOOL: 496 for (int i = 0; i < arrayLength; i++) { 497 output.writeBoolNoTag(Array.getBoolean(array, i)); 498 } 499 break; 500 case TYPE_FIXED32: 501 for (int i = 0; i < arrayLength; i++) { 502 output.writeFixed32NoTag(Array.getInt(array, i)); 503 } 504 break; 505 case TYPE_SFIXED32: 506 for (int i = 0; i < arrayLength; i++) { 507 output.writeSFixed32NoTag(Array.getInt(array, i)); 508 } 509 break; 510 case TYPE_FLOAT: 511 for (int i = 0; i < arrayLength; i++) { 512 output.writeFloatNoTag(Array.getFloat(array, i)); 513 } 514 break; 515 case TYPE_FIXED64: 516 for (int i = 0; i < arrayLength; i++) { 517 output.writeFixed64NoTag(Array.getLong(array, i)); 518 } 519 break; 520 case TYPE_SFIXED64: 521 for (int i = 0; i < arrayLength; i++) { 522 output.writeSFixed64NoTag(Array.getLong(array, i)); 523 } 524 break; 525 case TYPE_DOUBLE: 526 for (int i = 0; i < arrayLength; i++) { 527 output.writeDoubleNoTag(Array.getDouble(array, i)); 528 } 529 break; 530 case TYPE_INT32: 531 for (int i = 0; i < arrayLength; i++) { 532 output.writeInt32NoTag(Array.getInt(array, i)); 533 } 534 break; 535 case TYPE_SINT32: 536 for (int i = 0; i < arrayLength; i++) { 537 output.writeSInt32NoTag(Array.getInt(array, i)); 538 } 539 break; 540 case TYPE_UINT32: 541 for (int i = 0; i < arrayLength; i++) { 542 output.writeUInt32NoTag(Array.getInt(array, i)); 543 } 544 break; 545 case TYPE_INT64: 546 for (int i = 0; i < arrayLength; i++) { 547 output.writeInt64NoTag(Array.getLong(array, i)); 548 } 549 break; 550 case TYPE_SINT64: 551 for (int i = 0; i < arrayLength; i++) { 552 output.writeSInt64NoTag(Array.getLong(array, i)); 553 } 554 break; 555 case TYPE_UINT64: 556 for (int i = 0; i < arrayLength; i++) { 557 output.writeUInt64NoTag(Array.getLong(array, i)); 558 } 559 break; 560 case TYPE_ENUM: 561 for (int i = 0; i < arrayLength; i++) { 562 output.writeEnumNoTag(Array.getInt(array, i)); 563 } 564 break; 565 default: 566 throw new IllegalArgumentException("Unpackable type " + type); 567 } 568 } catch (IOException e) { 569 // Should not happen. 570 throw new IllegalStateException(e); 571 } 572 } else { 573 throw new IllegalArgumentException("Unexpected repeated extension tag " + tag 574 + ", unequal to both non-packed variant " + nonPackedTag 575 + " and packed variant " + packedTag); 576 } 577 } 578 579 private int computePackedDataSize(Object array) { 580 int dataSize = 0; 581 int arrayLength = Array.getLength(array); 582 switch (type) { 583 case TYPE_BOOL: 584 // Bools are stored as int32 but just as 0 or 1, so 1 byte each. 585 dataSize = arrayLength; 586 break; 587 case TYPE_FIXED32: 588 case TYPE_SFIXED32: 589 case TYPE_FLOAT: 590 dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE; 591 break; 592 case TYPE_FIXED64: 593 case TYPE_SFIXED64: 594 case TYPE_DOUBLE: 595 dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE; 596 break; 597 case TYPE_INT32: 598 for (int i = 0; i < arrayLength; i++) { 599 dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag( 600 Array.getInt(array, i)); 601 } 602 break; 603 case TYPE_SINT32: 604 for (int i = 0; i < arrayLength; i++) { 605 dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag( 606 Array.getInt(array, i)); 607 } 608 break; 609 case TYPE_UINT32: 610 for (int i = 0; i < arrayLength; i++) { 611 dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag( 612 Array.getInt(array, i)); 613 } 614 break; 615 case TYPE_INT64: 616 for (int i = 0; i < arrayLength; i++) { 617 dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag( 618 Array.getLong(array, i)); 619 } 620 break; 621 case TYPE_SINT64: 622 for (int i = 0; i < arrayLength; i++) { 623 dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag( 624 Array.getLong(array, i)); 625 } 626 break; 627 case TYPE_UINT64: 628 for (int i = 0; i < arrayLength; i++) { 629 dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag( 630 Array.getLong(array, i)); 631 } 632 break; 633 case TYPE_ENUM: 634 for (int i = 0; i < arrayLength; i++) { 635 dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag( 636 Array.getInt(array, i)); 637 } 638 break; 639 default: 640 throw new IllegalArgumentException("Unexpected non-packable type " + type); 641 } 642 return dataSize; 643 } 644 645 @Override 646 protected int computeRepeatedSerializedSize(Object array) { 647 if (tag == nonPackedTag) { 648 // Use base implementation for non-packed data 649 return super.computeRepeatedSerializedSize(array); 650 } else if (tag == packedTag) { 651 // Packed. 652 int dataSize = computePackedDataSize(array); 653 int payloadSize = 654 dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize); 655 return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag); 656 } else { 657 throw new IllegalArgumentException("Unexpected repeated extension tag " + tag 658 + ", unequal to both non-packed variant " + nonPackedTag 659 + " and packed variant " + packedTag); 660 } 661 } 662 663 @Override 664 protected final int computeSingularSerializedSize(Object value) { 665 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 666 switch (type) { 667 case TYPE_DOUBLE: 668 Double doubleValue = (Double) value; 669 return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue); 670 case TYPE_FLOAT: 671 Float floatValue = (Float) value; 672 return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue); 673 case TYPE_INT64: 674 Long int64Value = (Long) value; 675 return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value); 676 case TYPE_UINT64: 677 Long uint64Value = (Long) value; 678 return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value); 679 case TYPE_INT32: 680 Integer int32Value = (Integer) value; 681 return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value); 682 case TYPE_FIXED64: 683 Long fixed64Value = (Long) value; 684 return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value); 685 case TYPE_FIXED32: 686 Integer fixed32Value = (Integer) value; 687 return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value); 688 case TYPE_BOOL: 689 Boolean boolValue = (Boolean) value; 690 return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue); 691 case TYPE_STRING: 692 String stringValue = (String) value; 693 return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue); 694 case TYPE_BYTES: 695 byte[] bytesValue = (byte[]) value; 696 return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue); 697 case TYPE_UINT32: 698 Integer uint32Value = (Integer) value; 699 return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value); 700 case TYPE_ENUM: 701 Integer enumValue = (Integer) value; 702 return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue); 703 case TYPE_SFIXED32: 704 Integer sfixed32Value = (Integer) value; 705 return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber, 706 sfixed32Value); 707 case TYPE_SFIXED64: 708 Long sfixed64Value = (Long) value; 709 return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber, 710 sfixed64Value); 711 case TYPE_SINT32: 712 Integer sint32Value = (Integer) value; 713 return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value); 714 case TYPE_SINT64: 715 Long sint64Value = (Long) value; 716 return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value); 717 default: 718 throw new IllegalArgumentException("Unknown type " + type); 719 } 720 } 721 } 722} 723