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