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.lang.reflect.Array; 35 import java.util.ArrayList; 36 import 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 */ 46 public 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 = InternalNano.TYPE_DOUBLE; 59 public static final int TYPE_FLOAT = InternalNano.TYPE_FLOAT; 60 public static final int TYPE_INT64 = InternalNano.TYPE_INT64; 61 public static final int TYPE_UINT64 = InternalNano.TYPE_UINT64; 62 public static final int TYPE_INT32 = InternalNano.TYPE_INT32; 63 public static final int TYPE_FIXED64 = InternalNano.TYPE_FIXED64; 64 public static final int TYPE_FIXED32 = InternalNano.TYPE_FIXED32; 65 public static final int TYPE_BOOL = InternalNano.TYPE_BOOL; 66 public static final int TYPE_STRING = InternalNano.TYPE_STRING; 67 public static final int TYPE_GROUP = InternalNano.TYPE_GROUP; 68 public static final int TYPE_MESSAGE = InternalNano.TYPE_MESSAGE; 69 public static final int TYPE_BYTES = InternalNano.TYPE_BYTES; 70 public static final int TYPE_UINT32 = InternalNano.TYPE_UINT32; 71 public static final int TYPE_ENUM = InternalNano.TYPE_ENUM; 72 public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32; 73 public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64; 74 public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32; 75 public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64; 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 * @deprecated use {@link #createMessageTyped(int, Class, long)} instead. 83 */ 84 @Deprecated 85 public static <M extends ExtendableMessageNano<M>, T extends MessageNano> createMessageTyped(int type, Class<T> clazz, int tag)86 Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) { 87 return new Extension<M, T>(type, clazz, tag, false); 88 } 89 90 // Note: these create...() methods take a long for the tag parameter, 91 // because tags are represented as unsigned ints, and these values exist 92 // in generated code as long values. However, they can fit in 32-bits, so 93 // it's safe to cast them to int without loss of precision. 94 95 /** 96 * Creates an {@code Extension} of the given message type and tag number. 97 * Should be used by the generated code only. 98 * 99 * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} 100 */ 101 public static <M extends ExtendableMessageNano<M>, T extends MessageNano> createMessageTyped(int type, Class<T> clazz, long tag)102 Extension<M, T> createMessageTyped(int type, Class<T> clazz, long tag) { 103 return new Extension<M, T>(type, clazz, (int) tag, false); 104 } 105 106 /** 107 * Creates a repeated {@code Extension} of the given message type and tag number. 108 * Should be used by the generated code only. 109 * 110 * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} 111 */ 112 public static <M extends ExtendableMessageNano<M>, T extends MessageNano> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag)113 Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag) { 114 return new Extension<M, T[]>(type, clazz, (int) tag, true); 115 } 116 117 /** 118 * Creates an {@code Extension} of the given primitive type and tag number. 119 * Should be used by the generated code only. 120 * 121 * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} 122 * @param clazz the boxed Java type of this extension 123 */ 124 public static <M extends ExtendableMessageNano<M>, T> createPrimitiveTyped(int type, Class<T> clazz, long tag)125 Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, long tag) { 126 return new PrimitiveExtension<M, T>(type, clazz, (int) tag, false, 0, 0); 127 } 128 129 /** 130 * Creates a repeated {@code Extension} of the given primitive type and tag number. 131 * Should be used by the generated code only. 132 * 133 * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} 134 * @param clazz the Java array type of this extension, with an unboxed component type 135 */ 136 public static <M extends ExtendableMessageNano<M>, T> createRepeatedPrimitiveTyped( int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag)137 Extension<M, T> createRepeatedPrimitiveTyped( 138 int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag) { 139 return new PrimitiveExtension<M, T>(type, clazz, (int) tag, true, 140 (int) nonPackedTag, (int) packedTag); 141 } 142 143 /** 144 * Protocol Buffer type of this extension; one of the {@code TYPE_} constants. 145 */ 146 protected final int type; 147 148 /** 149 * Java type of this extension. For a singular extension, this is the boxed Java type for the 150 * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose 151 * component type is the unboxed Java type for {@link #type}. For example, for a singular 152 * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a 153 * repeated {@code int32} extension, this equals {@code int[].class}. 154 */ 155 protected final Class<T> clazz; 156 157 /** 158 * Tag number of this extension. The data should be viewed as an unsigned 32-bit value. 159 */ 160 public final int tag; 161 162 /** 163 * Whether this extension is repeated. 164 */ 165 protected final boolean repeated; 166 Extension(int type, Class<T> clazz, int tag, boolean repeated)167 private Extension(int type, Class<T> clazz, int tag, boolean repeated) { 168 this.type = type; 169 this.clazz = clazz; 170 this.tag = tag; 171 this.repeated = repeated; 172 } 173 174 /** 175 * Returns the value of this extension stored in the given list of unknown fields, or 176 * {@code null} if no unknown fields matches this extension. 177 * 178 * @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag 179 * that matches this Extension's tag. 180 * 181 */ getValueFrom(List<UnknownFieldData> unknownFields)182 final T getValueFrom(List<UnknownFieldData> unknownFields) { 183 if (unknownFields == null) { 184 return null; 185 } 186 return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields); 187 } 188 getRepeatedValueFrom(List<UnknownFieldData> unknownFields)189 private T getRepeatedValueFrom(List<UnknownFieldData> unknownFields) { 190 // For repeated extensions, read all matching unknown fields in their original order. 191 List<Object> resultList = new ArrayList<Object>(); 192 for (int i = 0; i < unknownFields.size(); i++) { 193 UnknownFieldData data = unknownFields.get(i); 194 if (data.bytes.length != 0) { 195 readDataInto(data, resultList); 196 } 197 } 198 199 int resultSize = resultList.size(); 200 if (resultSize == 0) { 201 return null; 202 } else { 203 T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize)); 204 for (int i = 0; i < resultSize; i++) { 205 Array.set(result, i, resultList.get(i)); 206 } 207 return result; 208 } 209 } 210 getSingularValueFrom(List<UnknownFieldData> unknownFields)211 private T getSingularValueFrom(List<UnknownFieldData> unknownFields) { 212 // For singular extensions, get the last piece of data stored under this extension. 213 if (unknownFields.isEmpty()) { 214 return null; 215 } 216 UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1); 217 return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes))); 218 } 219 readData(CodedInputByteBufferNano input)220 protected Object readData(CodedInputByteBufferNano input) { 221 // This implementation is for message/group extensions. 222 Class<?> messageType = repeated ? clazz.getComponentType() : clazz; 223 try { 224 switch (type) { 225 case TYPE_GROUP: 226 MessageNano group = (MessageNano) messageType.newInstance(); 227 input.readGroup(group, WireFormatNano.getTagFieldNumber(tag)); 228 return group; 229 case TYPE_MESSAGE: 230 MessageNano message = (MessageNano) messageType.newInstance(); 231 input.readMessage(message); 232 return message; 233 default: 234 throw new IllegalArgumentException("Unknown type " + type); 235 } 236 } catch (InstantiationException e) { 237 throw new IllegalArgumentException( 238 "Error creating instance of class " + messageType, e); 239 } catch (IllegalAccessException e) { 240 throw new IllegalArgumentException( 241 "Error creating instance of class " + messageType, e); 242 } catch (IOException e) { 243 throw new IllegalArgumentException("Error reading extension field", e); 244 } 245 } 246 readDataInto(UnknownFieldData data, List<Object> resultList)247 protected void readDataInto(UnknownFieldData data, List<Object> resultList) { 248 // This implementation is for message/group extensions. 249 resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); 250 } 251 writeTo(Object value, CodedOutputByteBufferNano output)252 void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException { 253 if (repeated) { 254 writeRepeatedData(value, output); 255 } else { 256 writeSingularData(value, output); 257 } 258 } 259 writeSingularData(Object value, CodedOutputByteBufferNano out)260 protected void writeSingularData(Object value, CodedOutputByteBufferNano out) { 261 // This implementation is for message/group extensions. 262 try { 263 out.writeRawVarint32(tag); 264 switch (type) { 265 case TYPE_GROUP: 266 MessageNano groupValue = (MessageNano) value; 267 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 268 out.writeGroupNoTag(groupValue); 269 // The endgroup tag must be included in the data payload. 270 out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); 271 break; 272 case TYPE_MESSAGE: 273 MessageNano messageValue = (MessageNano) value; 274 out.writeMessageNoTag(messageValue); 275 break; 276 default: 277 throw new IllegalArgumentException("Unknown type " + type); 278 } 279 } catch (IOException e) { 280 // Should not happen 281 throw new IllegalStateException(e); 282 } 283 } 284 writeRepeatedData(Object array, CodedOutputByteBufferNano output)285 protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { 286 // This implementation is for non-packed extensions. 287 int arrayLength = Array.getLength(array); 288 for (int i = 0; i < arrayLength; i++) { 289 Object element = Array.get(array, i); 290 if (element != null) { 291 writeSingularData(element, output); 292 } 293 } 294 } 295 computeSerializedSize(Object value)296 int computeSerializedSize(Object value) { 297 if (repeated) { 298 return computeRepeatedSerializedSize(value); 299 } else { 300 return computeSingularSerializedSize(value); 301 } 302 } 303 computeRepeatedSerializedSize(Object array)304 protected int computeRepeatedSerializedSize(Object array) { 305 // This implementation is for non-packed extensions. 306 int size = 0; 307 int arrayLength = Array.getLength(array); 308 for (int i = 0; i < arrayLength; i++) { 309 Object element = Array.get(array, i); 310 if (element != null) { 311 size += computeSingularSerializedSize(Array.get(array, i)); 312 } 313 } 314 return size; 315 } 316 computeSingularSerializedSize(Object value)317 protected int computeSingularSerializedSize(Object value) { 318 // This implementation is for message/group extensions. 319 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 320 switch (type) { 321 case TYPE_GROUP: 322 MessageNano groupValue = (MessageNano) value; 323 return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue); 324 case TYPE_MESSAGE: 325 MessageNano messageValue = (MessageNano) value; 326 return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue); 327 default: 328 throw new IllegalArgumentException("Unknown type " + type); 329 } 330 } 331 332 /** 333 * Represents an extension of a primitive (including enum) type. If there is no primitive 334 * extensions, this subclass will be removable by ProGuard. 335 */ 336 private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T> 337 extends Extension<M, T> { 338 339 /** 340 * Tag of a piece of non-packed data from the wire compatible with this extension. 341 */ 342 private final int nonPackedTag; 343 344 /** 345 * Tag of a piece of packed data from the wire compatible with this extension. 346 * 0 if the type of this extension is not packable. 347 */ 348 private final int packedTag; 349 PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated, int nonPackedTag, int packedTag)350 public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated, 351 int nonPackedTag, int packedTag) { 352 super(type, clazz, tag, repeated); 353 this.nonPackedTag = nonPackedTag; 354 this.packedTag = packedTag; 355 } 356 357 @Override readData(CodedInputByteBufferNano input)358 protected Object readData(CodedInputByteBufferNano input) { 359 try { 360 return input.readPrimitiveField(type); 361 } catch (IOException e) { 362 throw new IllegalArgumentException("Error reading extension field", e); 363 } 364 } 365 366 @Override readDataInto(UnknownFieldData data, List<Object> resultList)367 protected void readDataInto(UnknownFieldData data, List<Object> resultList) { 368 // This implementation is for primitive typed extensions, 369 // which can read both packed and non-packed data. 370 if (data.tag == nonPackedTag) { 371 resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); 372 } else { 373 CodedInputByteBufferNano buffer = 374 CodedInputByteBufferNano.newInstance(data.bytes); 375 try { 376 buffer.pushLimit(buffer.readRawVarint32()); // length limit 377 } catch (IOException e) { 378 throw new IllegalArgumentException("Error reading extension field", e); 379 } 380 while (!buffer.isAtEnd()) { 381 resultList.add(readData(buffer)); 382 } 383 } 384 } 385 386 @Override writeSingularData(Object value, CodedOutputByteBufferNano output)387 protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) { 388 try { 389 output.writeRawVarint32(tag); 390 switch (type) { 391 case TYPE_DOUBLE: 392 Double doubleValue = (Double) value; 393 output.writeDoubleNoTag(doubleValue); 394 break; 395 case TYPE_FLOAT: 396 Float floatValue = (Float) value; 397 output.writeFloatNoTag(floatValue); 398 break; 399 case TYPE_INT64: 400 Long int64Value = (Long) value; 401 output.writeInt64NoTag(int64Value); 402 break; 403 case TYPE_UINT64: 404 Long uint64Value = (Long) value; 405 output.writeUInt64NoTag(uint64Value); 406 break; 407 case TYPE_INT32: 408 Integer int32Value = (Integer) value; 409 output.writeInt32NoTag(int32Value); 410 break; 411 case TYPE_FIXED64: 412 Long fixed64Value = (Long) value; 413 output.writeFixed64NoTag(fixed64Value); 414 break; 415 case TYPE_FIXED32: 416 Integer fixed32Value = (Integer) value; 417 output.writeFixed32NoTag(fixed32Value); 418 break; 419 case TYPE_BOOL: 420 Boolean boolValue = (Boolean) value; 421 output.writeBoolNoTag(boolValue); 422 break; 423 case TYPE_STRING: 424 String stringValue = (String) value; 425 output.writeStringNoTag(stringValue); 426 break; 427 case TYPE_BYTES: 428 byte[] bytesValue = (byte[]) value; 429 output.writeBytesNoTag(bytesValue); 430 break; 431 case TYPE_UINT32: 432 Integer uint32Value = (Integer) value; 433 output.writeUInt32NoTag(uint32Value); 434 break; 435 case TYPE_ENUM: 436 Integer enumValue = (Integer) value; 437 output.writeEnumNoTag(enumValue); 438 break; 439 case TYPE_SFIXED32: 440 Integer sfixed32Value = (Integer) value; 441 output.writeSFixed32NoTag(sfixed32Value); 442 break; 443 case TYPE_SFIXED64: 444 Long sfixed64Value = (Long) value; 445 output.writeSFixed64NoTag(sfixed64Value); 446 break; 447 case TYPE_SINT32: 448 Integer sint32Value = (Integer) value; 449 output.writeSInt32NoTag(sint32Value); 450 break; 451 case TYPE_SINT64: 452 Long sint64Value = (Long) value; 453 output.writeSInt64NoTag(sint64Value); 454 break; 455 default: 456 throw new IllegalArgumentException("Unknown type " + type); 457 } 458 } catch (IOException e) { 459 // Should not happen 460 throw new IllegalStateException(e); 461 } 462 } 463 464 @Override writeRepeatedData(Object array, CodedOutputByteBufferNano output)465 protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { 466 if (tag == nonPackedTag) { 467 // Use base implementation for non-packed data 468 super.writeRepeatedData(array, output); 469 } else if (tag == packedTag) { 470 // Packed. Note that the array element type is guaranteed to be primitive, so there 471 // won't be any null elements, so no null check in this block. 472 int arrayLength = Array.getLength(array); 473 int dataSize = computePackedDataSize(array); 474 475 try { 476 output.writeRawVarint32(tag); 477 output.writeRawVarint32(dataSize); 478 switch (type) { 479 case TYPE_BOOL: 480 for (int i = 0; i < arrayLength; i++) { 481 output.writeBoolNoTag(Array.getBoolean(array, i)); 482 } 483 break; 484 case TYPE_FIXED32: 485 for (int i = 0; i < arrayLength; i++) { 486 output.writeFixed32NoTag(Array.getInt(array, i)); 487 } 488 break; 489 case TYPE_SFIXED32: 490 for (int i = 0; i < arrayLength; i++) { 491 output.writeSFixed32NoTag(Array.getInt(array, i)); 492 } 493 break; 494 case TYPE_FLOAT: 495 for (int i = 0; i < arrayLength; i++) { 496 output.writeFloatNoTag(Array.getFloat(array, i)); 497 } 498 break; 499 case TYPE_FIXED64: 500 for (int i = 0; i < arrayLength; i++) { 501 output.writeFixed64NoTag(Array.getLong(array, i)); 502 } 503 break; 504 case TYPE_SFIXED64: 505 for (int i = 0; i < arrayLength; i++) { 506 output.writeSFixed64NoTag(Array.getLong(array, i)); 507 } 508 break; 509 case TYPE_DOUBLE: 510 for (int i = 0; i < arrayLength; i++) { 511 output.writeDoubleNoTag(Array.getDouble(array, i)); 512 } 513 break; 514 case TYPE_INT32: 515 for (int i = 0; i < arrayLength; i++) { 516 output.writeInt32NoTag(Array.getInt(array, i)); 517 } 518 break; 519 case TYPE_SINT32: 520 for (int i = 0; i < arrayLength; i++) { 521 output.writeSInt32NoTag(Array.getInt(array, i)); 522 } 523 break; 524 case TYPE_UINT32: 525 for (int i = 0; i < arrayLength; i++) { 526 output.writeUInt32NoTag(Array.getInt(array, i)); 527 } 528 break; 529 case TYPE_INT64: 530 for (int i = 0; i < arrayLength; i++) { 531 output.writeInt64NoTag(Array.getLong(array, i)); 532 } 533 break; 534 case TYPE_SINT64: 535 for (int i = 0; i < arrayLength; i++) { 536 output.writeSInt64NoTag(Array.getLong(array, i)); 537 } 538 break; 539 case TYPE_UINT64: 540 for (int i = 0; i < arrayLength; i++) { 541 output.writeUInt64NoTag(Array.getLong(array, i)); 542 } 543 break; 544 case TYPE_ENUM: 545 for (int i = 0; i < arrayLength; i++) { 546 output.writeEnumNoTag(Array.getInt(array, i)); 547 } 548 break; 549 default: 550 throw new IllegalArgumentException("Unpackable type " + type); 551 } 552 } catch (IOException e) { 553 // Should not happen. 554 throw new IllegalStateException(e); 555 } 556 } else { 557 throw new IllegalArgumentException("Unexpected repeated extension tag " + tag 558 + ", unequal to both non-packed variant " + nonPackedTag 559 + " and packed variant " + packedTag); 560 } 561 } 562 computePackedDataSize(Object array)563 private int computePackedDataSize(Object array) { 564 int dataSize = 0; 565 int arrayLength = Array.getLength(array); 566 switch (type) { 567 case TYPE_BOOL: 568 // Bools are stored as int32 but just as 0 or 1, so 1 byte each. 569 dataSize = arrayLength; 570 break; 571 case TYPE_FIXED32: 572 case TYPE_SFIXED32: 573 case TYPE_FLOAT: 574 dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE; 575 break; 576 case TYPE_FIXED64: 577 case TYPE_SFIXED64: 578 case TYPE_DOUBLE: 579 dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE; 580 break; 581 case TYPE_INT32: 582 for (int i = 0; i < arrayLength; i++) { 583 dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag( 584 Array.getInt(array, i)); 585 } 586 break; 587 case TYPE_SINT32: 588 for (int i = 0; i < arrayLength; i++) { 589 dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag( 590 Array.getInt(array, i)); 591 } 592 break; 593 case TYPE_UINT32: 594 for (int i = 0; i < arrayLength; i++) { 595 dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag( 596 Array.getInt(array, i)); 597 } 598 break; 599 case TYPE_INT64: 600 for (int i = 0; i < arrayLength; i++) { 601 dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag( 602 Array.getLong(array, i)); 603 } 604 break; 605 case TYPE_SINT64: 606 for (int i = 0; i < arrayLength; i++) { 607 dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag( 608 Array.getLong(array, i)); 609 } 610 break; 611 case TYPE_UINT64: 612 for (int i = 0; i < arrayLength; i++) { 613 dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag( 614 Array.getLong(array, i)); 615 } 616 break; 617 case TYPE_ENUM: 618 for (int i = 0; i < arrayLength; i++) { 619 dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag( 620 Array.getInt(array, i)); 621 } 622 break; 623 default: 624 throw new IllegalArgumentException("Unexpected non-packable type " + type); 625 } 626 return dataSize; 627 } 628 629 @Override computeRepeatedSerializedSize(Object array)630 protected int computeRepeatedSerializedSize(Object array) { 631 if (tag == nonPackedTag) { 632 // Use base implementation for non-packed data 633 return super.computeRepeatedSerializedSize(array); 634 } else if (tag == packedTag) { 635 // Packed. 636 int dataSize = computePackedDataSize(array); 637 int payloadSize = 638 dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize); 639 return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag); 640 } else { 641 throw new IllegalArgumentException("Unexpected repeated extension tag " + tag 642 + ", unequal to both non-packed variant " + nonPackedTag 643 + " and packed variant " + packedTag); 644 } 645 } 646 647 @Override computeSingularSerializedSize(Object value)648 protected final int computeSingularSerializedSize(Object value) { 649 int fieldNumber = WireFormatNano.getTagFieldNumber(tag); 650 switch (type) { 651 case TYPE_DOUBLE: 652 Double doubleValue = (Double) value; 653 return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue); 654 case TYPE_FLOAT: 655 Float floatValue = (Float) value; 656 return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue); 657 case TYPE_INT64: 658 Long int64Value = (Long) value; 659 return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value); 660 case TYPE_UINT64: 661 Long uint64Value = (Long) value; 662 return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value); 663 case TYPE_INT32: 664 Integer int32Value = (Integer) value; 665 return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value); 666 case TYPE_FIXED64: 667 Long fixed64Value = (Long) value; 668 return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value); 669 case TYPE_FIXED32: 670 Integer fixed32Value = (Integer) value; 671 return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value); 672 case TYPE_BOOL: 673 Boolean boolValue = (Boolean) value; 674 return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue); 675 case TYPE_STRING: 676 String stringValue = (String) value; 677 return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue); 678 case TYPE_BYTES: 679 byte[] bytesValue = (byte[]) value; 680 return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue); 681 case TYPE_UINT32: 682 Integer uint32Value = (Integer) value; 683 return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value); 684 case TYPE_ENUM: 685 Integer enumValue = (Integer) value; 686 return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue); 687 case TYPE_SFIXED32: 688 Integer sfixed32Value = (Integer) value; 689 return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber, 690 sfixed32Value); 691 case TYPE_SFIXED64: 692 Long sfixed64Value = (Long) value; 693 return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber, 694 sfixed64Value); 695 case TYPE_SINT32: 696 Integer sint32Value = (Integer) value; 697 return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value); 698 case TYPE_SINT64: 699 Long sint64Value = (Long) value; 700 return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value); 701 default: 702 throw new IllegalArgumentException("Unknown type " + type); 703 } 704 } 705 } 706 } 707