1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 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; 32 33 import java.io.IOException; 34 import java.lang.reflect.Method; 35 import java.nio.ByteBuffer; 36 import java.nio.charset.Charset; 37 import java.util.AbstractList; 38 import java.util.AbstractMap; 39 import java.util.AbstractSet; 40 import java.util.Arrays; 41 import java.util.Iterator; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.RandomAccess; 45 import java.util.Set; 46 47 /** 48 * The classes contained within are used internally by the Protocol Buffer library and generated 49 * message implementations. They are public only because those generated messages do not reside in 50 * the {@code protobuf} package. Others should not use this class directly. 51 * 52 * @author kenton@google.com (Kenton Varda) 53 */ 54 public final class Internal { 55 Internal()56 private Internal() {} 57 58 static final Charset UTF_8 = Charset.forName("UTF-8"); 59 static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); 60 61 /** Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. */ checkNotNull(T obj)62 static <T> T checkNotNull(T obj) { 63 if (obj == null) { 64 throw new NullPointerException(); 65 } 66 return obj; 67 } 68 69 /** Throws an appropriate {@link NullPointerException} if the given objects is {@code null}. */ checkNotNull(T obj, String message)70 static <T> T checkNotNull(T obj, String message) { 71 if (obj == null) { 72 throw new NullPointerException(message); 73 } 74 return obj; 75 } 76 77 /** 78 * Helper called by generated code to construct default values for string fields. 79 * 80 * <p>The protocol compiler does not actually contain a UTF-8 decoder -- it just pushes 81 * UTF-8-encoded text around without touching it. The one place where this presents a problem is 82 * when generating Java string literals. Unicode characters in the string literal would normally 83 * need to be encoded using a Unicode escape sequence, which would require decoding them. To get 84 * around this, protoc instead embeds the UTF-8 bytes into the generated code and leaves it to the 85 * runtime library to decode them. 86 * 87 * <p>It gets worse, though. If protoc just generated a byte array, like: new byte[] {0x12, 0x34, 88 * 0x56, 0x78} Java actually generates *code* which allocates an array and then fills in each 89 * value. This is much less efficient than just embedding the bytes directly into the bytecode. To 90 * get around this, we need another work-around. String literals are embedded directly, so protoc 91 * actually generates a string literal corresponding to the bytes. The easiest way to do this is 92 * to use the ISO-8859-1 character set, which corresponds to the first 256 characters of the 93 * Unicode range. Protoc can then use good old CEscape to generate the string. 94 * 95 * <p>So we have a string literal which represents a set of bytes which represents another string. 96 * This function -- stringDefaultValue -- converts from the generated string to the string we 97 * actually want. The generated code calls this automatically. 98 */ stringDefaultValue(String bytes)99 public static String stringDefaultValue(String bytes) { 100 return new String(bytes.getBytes(ISO_8859_1), UTF_8); 101 } 102 103 /** 104 * Helper called by generated code to construct default values for bytes fields. 105 * 106 * <p>This is a lot like {@link #stringDefaultValue}, but for bytes fields. In this case we only 107 * need the second of the two hacks -- allowing us to embed raw bytes as a string literal with 108 * ISO-8859-1 encoding. 109 */ bytesDefaultValue(String bytes)110 public static ByteString bytesDefaultValue(String bytes) { 111 return ByteString.copyFrom(bytes.getBytes(ISO_8859_1)); 112 } 113 /** 114 * Helper called by generated code to construct default values for bytes fields. 115 * 116 * <p>This is like {@link #bytesDefaultValue}, but returns a byte array. 117 */ byteArrayDefaultValue(String bytes)118 public static byte[] byteArrayDefaultValue(String bytes) { 119 return bytes.getBytes(ISO_8859_1); 120 } 121 122 /** 123 * Helper called by generated code to construct default values for bytes fields. 124 * 125 * <p>This is like {@link #bytesDefaultValue}, but returns a ByteBuffer. 126 */ byteBufferDefaultValue(String bytes)127 public static ByteBuffer byteBufferDefaultValue(String bytes) { 128 return ByteBuffer.wrap(byteArrayDefaultValue(bytes)); 129 } 130 131 /** 132 * Create a new ByteBuffer and copy all the content of {@code source} ByteBuffer to the new 133 * ByteBuffer. The new ByteBuffer's limit and capacity will be source.capacity(), and its position 134 * will be 0. Note that the state of {@code source} ByteBuffer won't be changed. 135 */ copyByteBuffer(ByteBuffer source)136 public static ByteBuffer copyByteBuffer(ByteBuffer source) { 137 // Make a duplicate of the source ByteBuffer and read data from the 138 // duplicate. This is to avoid affecting the source ByteBuffer's state. 139 ByteBuffer temp = source.duplicate(); 140 // We want to copy all the data in the source ByteBuffer, not just the 141 // remaining bytes. 142 temp.clear(); 143 ByteBuffer result = ByteBuffer.allocate(temp.capacity()); 144 result.put(temp); 145 result.clear(); 146 return result; 147 } 148 149 /** 150 * Helper called by generated code to determine if a byte array is a valid UTF-8 encoded string 151 * such that the original bytes can be converted to a String object and then back to a byte array 152 * round tripping the bytes without loss. More precisely, returns {@code true} whenever: 153 * 154 * <pre>{@code 155 * Arrays.equals(byteString.toByteArray(), 156 * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8")) 157 * }</pre> 158 * 159 * <p>This method rejects "overlong" byte sequences, as well as 3-byte sequences that would map to 160 * a surrogate character, in accordance with the restricted definition of UTF-8 introduced in 161 * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's JDK has been modified to also 162 * reject "overlong" byte sequences, but currently (2011) still accepts 3-byte surrogate character 163 * byte sequences. 164 * 165 * <p>See the Unicode Standard,<br> 166 * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br> 167 * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>. 168 * 169 * <p>As of 2011-02, this method simply returns the result of {@link ByteString#isValidUtf8()}. 170 * Calling that method directly is preferred. 171 * 172 * @param byteString the string to check 173 * @return whether the byte array is round trippable 174 */ isValidUtf8(ByteString byteString)175 public static boolean isValidUtf8(ByteString byteString) { 176 return byteString.isValidUtf8(); 177 } 178 179 /** Like {@link #isValidUtf8(ByteString)} but for byte arrays. */ isValidUtf8(byte[] byteArray)180 public static boolean isValidUtf8(byte[] byteArray) { 181 return Utf8.isValidUtf8(byteArray); 182 } 183 184 /** Helper method to get the UTF-8 bytes of a string. */ toByteArray(String value)185 public static byte[] toByteArray(String value) { 186 return value.getBytes(UTF_8); 187 } 188 189 /** Helper method to convert a byte array to a string using UTF-8 encoding. */ toStringUtf8(byte[] bytes)190 public static String toStringUtf8(byte[] bytes) { 191 return new String(bytes, UTF_8); 192 } 193 194 /** 195 * Interface for an enum value or value descriptor, to be used in FieldSet. The lite library 196 * stores enum values directly in FieldSets but the full library stores EnumValueDescriptors in 197 * order to better support reflection. 198 */ 199 public interface EnumLite { getNumber()200 int getNumber(); 201 } 202 203 /** 204 * Interface for an object which maps integers to {@link EnumLite}s. {@link 205 * Descriptors.EnumDescriptor} implements this interface by mapping numbers to {@link 206 * Descriptors.EnumValueDescriptor}s. Additionally, every generated enum type has a static method 207 * internalGetValueMap() which returns an implementation of this type that maps numbers to enum 208 * values. 209 */ 210 public interface EnumLiteMap<T extends EnumLite> { findValueByNumber(int number)211 T findValueByNumber(int number); 212 } 213 214 /** Interface for an object which verifies integers are in range. */ 215 public interface EnumVerifier { isInRange(int number)216 boolean isInRange(int number); 217 } 218 219 /** 220 * Helper method for implementing {@link Message#hashCode()} for longs. 221 * 222 * @see Long#hashCode() 223 */ hashLong(long n)224 public static int hashLong(long n) { 225 return (int) (n ^ (n >>> 32)); 226 } 227 228 /** 229 * Helper method for implementing {@link Message#hashCode()} for booleans. 230 * 231 * @see Boolean#hashCode() 232 */ hashBoolean(boolean b)233 public static int hashBoolean(boolean b) { 234 return b ? 1231 : 1237; 235 } 236 237 /** 238 * Helper method for implementing {@link Message#hashCode()} for enums. 239 * 240 * <p>This is needed because {@link java.lang.Enum#hashCode()} is final, but we need to use the 241 * field number as the hash code to ensure compatibility between statically and dynamically 242 * generated enum objects. 243 */ hashEnum(EnumLite e)244 public static int hashEnum(EnumLite e) { 245 return e.getNumber(); 246 } 247 248 /** Helper method for implementing {@link Message#hashCode()} for enum lists. */ hashEnumList(List<? extends EnumLite> list)249 public static int hashEnumList(List<? extends EnumLite> list) { 250 int hash = 1; 251 for (EnumLite e : list) { 252 hash = 31 * hash + hashEnum(e); 253 } 254 return hash; 255 } 256 257 /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ equals(List<byte[]> a, List<byte[]> b)258 public static boolean equals(List<byte[]> a, List<byte[]> b) { 259 if (a.size() != b.size()) return false; 260 for (int i = 0; i < a.size(); ++i) { 261 if (!Arrays.equals(a.get(i), b.get(i))) { 262 return false; 263 } 264 } 265 return true; 266 } 267 268 /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ hashCode(List<byte[]> list)269 public static int hashCode(List<byte[]> list) { 270 int hash = 1; 271 for (byte[] bytes : list) { 272 hash = 31 * hash + hashCode(bytes); 273 } 274 return hash; 275 } 276 277 /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ hashCode(byte[] bytes)278 public static int hashCode(byte[] bytes) { 279 // The hash code for a byte array should be the same as the hash code for a 280 // ByteString with the same content. This is to ensure that the generated 281 // hashCode() method will return the same value as the pure reflection 282 // based hashCode() method. 283 return Internal.hashCode(bytes, 0, bytes.length); 284 } 285 286 /** Helper method for implementing {@link LiteralByteString#hashCode()}. */ hashCode(byte[] bytes, int offset, int length)287 static int hashCode(byte[] bytes, int offset, int length) { 288 // The hash code for a byte array should be the same as the hash code for a 289 // ByteString with the same content. This is to ensure that the generated 290 // hashCode() method will return the same value as the pure reflection 291 // based hashCode() method. 292 int h = Internal.partialHash(length, bytes, offset, length); 293 return h == 0 ? 1 : h; 294 } 295 296 /** Helper method for continuously hashing bytes. */ partialHash(int h, byte[] bytes, int offset, int length)297 static int partialHash(int h, byte[] bytes, int offset, int length) { 298 for (int i = offset; i < offset + length; i++) { 299 h = h * 31 + bytes[i]; 300 } 301 return h; 302 } 303 304 /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ equalsByteBuffer(ByteBuffer a, ByteBuffer b)305 public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) { 306 if (a.capacity() != b.capacity()) { 307 return false; 308 } 309 // ByteBuffer.equals() will only compare the remaining bytes, but we want to 310 // compare all the content. 311 return a.duplicate().clear().equals(b.duplicate().clear()); 312 } 313 314 /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ equalsByteBuffer(List<ByteBuffer> a, List<ByteBuffer> b)315 public static boolean equalsByteBuffer(List<ByteBuffer> a, List<ByteBuffer> b) { 316 if (a.size() != b.size()) { 317 return false; 318 } 319 for (int i = 0; i < a.size(); ++i) { 320 if (!equalsByteBuffer(a.get(i), b.get(i))) { 321 return false; 322 } 323 } 324 return true; 325 } 326 327 /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ hashCodeByteBuffer(List<ByteBuffer> list)328 public static int hashCodeByteBuffer(List<ByteBuffer> list) { 329 int hash = 1; 330 for (ByteBuffer bytes : list) { 331 hash = 31 * hash + hashCodeByteBuffer(bytes); 332 } 333 return hash; 334 } 335 336 private static final int DEFAULT_BUFFER_SIZE = 4096; 337 338 /** Helper method for implementing {@link Message#hashCode()} for bytes field. */ hashCodeByteBuffer(ByteBuffer bytes)339 public static int hashCodeByteBuffer(ByteBuffer bytes) { 340 if (bytes.hasArray()) { 341 // Fast path. 342 int h = partialHash(bytes.capacity(), bytes.array(), bytes.arrayOffset(), bytes.capacity()); 343 return h == 0 ? 1 : h; 344 } else { 345 // Read the data into a temporary byte array before calculating the 346 // hash value. 347 final int bufferSize = 348 bytes.capacity() > DEFAULT_BUFFER_SIZE ? DEFAULT_BUFFER_SIZE : bytes.capacity(); 349 final byte[] buffer = new byte[bufferSize]; 350 final ByteBuffer duplicated = bytes.duplicate(); 351 duplicated.clear(); 352 int h = bytes.capacity(); 353 while (duplicated.remaining() > 0) { 354 final int length = 355 duplicated.remaining() <= bufferSize ? duplicated.remaining() : bufferSize; 356 duplicated.get(buffer, 0, length); 357 h = partialHash(h, buffer, 0, length); 358 } 359 return h == 0 ? 1 : h; 360 } 361 } 362 363 @SuppressWarnings("unchecked") getDefaultInstance(Class<T> clazz)364 public static <T extends MessageLite> T getDefaultInstance(Class<T> clazz) { 365 try { 366 Method method = clazz.getMethod("getDefaultInstance"); 367 return (T) method.invoke(method); 368 } catch (Exception e) { 369 throw new RuntimeException("Failed to get default instance for " + clazz, e); 370 } 371 } 372 373 374 /** An empty byte array constant used in generated code. */ 375 public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; 376 377 /** An empty byte array constant used in generated code. */ 378 public static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.wrap(EMPTY_BYTE_ARRAY); 379 380 /** An empty coded input stream constant used in generated code. */ 381 public static final CodedInputStream EMPTY_CODED_INPUT_STREAM = 382 CodedInputStream.newInstance(EMPTY_BYTE_ARRAY); 383 384 385 /** Helper method to merge two MessageLite instances. */ mergeMessage(Object destination, Object source)386 static Object mergeMessage(Object destination, Object source) { 387 return ((MessageLite) destination).toBuilder().mergeFrom((MessageLite) source).buildPartial(); 388 } 389 390 /** 391 * Provides an immutable view of {@code List<T>} around a {@code List<F>}. 392 * 393 * <p>Protobuf internal. Used in protobuf generated code only. 394 */ 395 public static class ListAdapter<F, T> extends AbstractList<T> { 396 /** Convert individual elements of the List from F to T. */ 397 public interface Converter<F, T> { convert(F from)398 T convert(F from); 399 } 400 401 private final List<F> fromList; 402 private final Converter<F, T> converter; 403 ListAdapter(List<F> fromList, Converter<F, T> converter)404 public ListAdapter(List<F> fromList, Converter<F, T> converter) { 405 this.fromList = fromList; 406 this.converter = converter; 407 } 408 409 @Override get(int index)410 public T get(int index) { 411 return converter.convert(fromList.get(index)); 412 } 413 414 @Override size()415 public int size() { 416 return fromList.size(); 417 } 418 } 419 420 /** Wrap around a {@code Map<K, RealValue>} and provide a {@code Map<K, V>} interface. */ 421 public static class MapAdapter<K, V, RealValue> extends AbstractMap<K, V> { 422 /** An interface used to convert between two types. */ 423 public interface Converter<A, B> { doForward(A object)424 B doForward(A object); 425 doBackward(B object)426 A doBackward(B object); 427 } 428 newEnumConverter( final EnumLiteMap<T> enumMap, final T unrecognizedValue)429 public static <T extends EnumLite> Converter<Integer, T> newEnumConverter( 430 final EnumLiteMap<T> enumMap, final T unrecognizedValue) { 431 return new Converter<Integer, T>() { 432 @Override 433 public T doForward(Integer value) { 434 T result = enumMap.findValueByNumber(value); 435 return result == null ? unrecognizedValue : result; 436 } 437 438 @Override 439 public Integer doBackward(T value) { 440 return value.getNumber(); 441 } 442 }; 443 } 444 445 private final Map<K, RealValue> realMap; 446 private final Converter<RealValue, V> valueConverter; 447 MapAdapter(Map<K, RealValue> realMap, Converter<RealValue, V> valueConverter)448 public MapAdapter(Map<K, RealValue> realMap, Converter<RealValue, V> valueConverter) { 449 this.realMap = realMap; 450 this.valueConverter = valueConverter; 451 } 452 453 @SuppressWarnings("unchecked") 454 @Override get(Object key)455 public V get(Object key) { 456 RealValue result = realMap.get(key); 457 if (result == null) { 458 return null; 459 } 460 return valueConverter.doForward(result); 461 } 462 463 @Override put(K key, V value)464 public V put(K key, V value) { 465 RealValue oldValue = realMap.put(key, valueConverter.doBackward(value)); 466 if (oldValue == null) { 467 return null; 468 } 469 return valueConverter.doForward(oldValue); 470 } 471 472 @Override entrySet()473 public Set<java.util.Map.Entry<K, V>> entrySet() { 474 return new SetAdapter(realMap.entrySet()); 475 } 476 477 private class SetAdapter extends AbstractSet<Map.Entry<K, V>> { 478 private final Set<Map.Entry<K, RealValue>> realSet; 479 SetAdapter(Set<Map.Entry<K, RealValue>> realSet)480 public SetAdapter(Set<Map.Entry<K, RealValue>> realSet) { 481 this.realSet = realSet; 482 } 483 484 @Override iterator()485 public Iterator<java.util.Map.Entry<K, V>> iterator() { 486 return new IteratorAdapter(realSet.iterator()); 487 } 488 489 @Override size()490 public int size() { 491 return realSet.size(); 492 } 493 } 494 495 private class IteratorAdapter implements Iterator<Map.Entry<K, V>> { 496 private final Iterator<Map.Entry<K, RealValue>> realIterator; 497 IteratorAdapter(Iterator<Map.Entry<K, RealValue>> realIterator)498 public IteratorAdapter(Iterator<Map.Entry<K, RealValue>> realIterator) { 499 this.realIterator = realIterator; 500 } 501 502 @Override hasNext()503 public boolean hasNext() { 504 return realIterator.hasNext(); 505 } 506 507 @Override next()508 public java.util.Map.Entry<K, V> next() { 509 return new EntryAdapter(realIterator.next()); 510 } 511 512 @Override remove()513 public void remove() { 514 realIterator.remove(); 515 } 516 } 517 518 private class EntryAdapter implements Map.Entry<K, V> { 519 private final Map.Entry<K, RealValue> realEntry; 520 EntryAdapter(Map.Entry<K, RealValue> realEntry)521 public EntryAdapter(Map.Entry<K, RealValue> realEntry) { 522 this.realEntry = realEntry; 523 } 524 525 @Override getKey()526 public K getKey() { 527 return realEntry.getKey(); 528 } 529 530 @Override getValue()531 public V getValue() { 532 return valueConverter.doForward(realEntry.getValue()); 533 } 534 535 @Override setValue(V value)536 public V setValue(V value) { 537 RealValue oldValue = realEntry.setValue(valueConverter.doBackward(value)); 538 if (oldValue == null) { 539 return null; 540 } 541 return valueConverter.doForward(oldValue); 542 } 543 544 @Override equals(Object o)545 public boolean equals(Object o) { 546 if (o == this) { 547 return true; 548 } 549 if (!(o instanceof Map.Entry)) { 550 return false; 551 } 552 @SuppressWarnings("unchecked") 553 Map.Entry<?, ?> other = (Map.Entry<?, ?>) o; 554 return getKey().equals(other.getKey()) && getValue().equals(getValue()); 555 } 556 557 @Override hashCode()558 public int hashCode() { 559 return realEntry.hashCode(); 560 } 561 } 562 } 563 564 /** 565 * Extends {@link List} to add the capability to make the list immutable and inspect if it is 566 * modifiable. 567 * 568 * <p>All implementations must support efficient random access. 569 */ 570 public static interface ProtobufList<E> extends List<E>, RandomAccess { 571 572 /** 573 * Makes this list immutable. All subsequent modifications will throw an {@link 574 * UnsupportedOperationException}. 575 */ 576 void makeImmutable(); 577 578 /** 579 * Returns whether this list can be modified via the publicly accessible {@link List} methods. 580 */ 581 boolean isModifiable(); 582 583 /** Returns a mutable clone of this list with the specified capacity. */ 584 ProtobufList<E> mutableCopyWithCapacity(int capacity); 585 } 586 587 /** 588 * A {@link java.util.List} implementation that avoids boxing the elements into Integers if 589 * possible. Does not support null elements. 590 */ 591 public static interface IntList extends ProtobufList<Integer> { 592 593 /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ 594 int getInt(int index); 595 596 /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ 597 void addInt(int element); 598 599 /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ 600 int setInt(int index, int element); 601 602 /** Returns a mutable clone of this list with the specified capacity. */ 603 @Override 604 IntList mutableCopyWithCapacity(int capacity); 605 } 606 607 /** 608 * A {@link java.util.List} implementation that avoids boxing the elements into Booleans if 609 * possible. Does not support null elements. 610 */ 611 public static interface BooleanList extends ProtobufList<Boolean> { 612 613 /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ 614 boolean getBoolean(int index); 615 616 /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ 617 void addBoolean(boolean element); 618 619 /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ 620 boolean setBoolean(int index, boolean element); 621 622 /** Returns a mutable clone of this list with the specified capacity. */ 623 @Override 624 BooleanList mutableCopyWithCapacity(int capacity); 625 } 626 627 /** 628 * A {@link java.util.List} implementation that avoids boxing the elements into Longs if possible. 629 * Does not support null elements. 630 */ 631 public static interface LongList extends ProtobufList<Long> { 632 633 /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ 634 long getLong(int index); 635 636 /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ 637 void addLong(long element); 638 639 /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ 640 long setLong(int index, long element); 641 642 /** Returns a mutable clone of this list with the specified capacity. */ 643 @Override 644 LongList mutableCopyWithCapacity(int capacity); 645 } 646 647 /** 648 * A {@link java.util.List} implementation that avoids boxing the elements into Doubles if 649 * possible. Does not support null elements. 650 */ 651 public static interface DoubleList extends ProtobufList<Double> { 652 653 /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ 654 double getDouble(int index); 655 656 /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ 657 void addDouble(double element); 658 659 /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ 660 double setDouble(int index, double element); 661 662 /** Returns a mutable clone of this list with the specified capacity. */ 663 @Override 664 DoubleList mutableCopyWithCapacity(int capacity); 665 } 666 667 /** 668 * A {@link java.util.List} implementation that avoids boxing the elements into Floats if 669 * possible. Does not support null elements. 670 */ 671 public static interface FloatList extends ProtobufList<Float> { 672 673 /** Like {@link #get(int)} but more efficient in that it doesn't box the returned value. */ 674 float getFloat(int index); 675 676 /** Like {@link #add(Object)} but more efficient in that it doesn't box the element. */ 677 void addFloat(float element); 678 679 /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */ 680 float setFloat(int index, float element); 681 682 /** Returns a mutable clone of this list with the specified capacity. */ 683 @Override 684 FloatList mutableCopyWithCapacity(int capacity); 685 } 686 687 } 688