• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ByteArrayInputStream;
34 import java.io.ByteArrayOutputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InvalidObjectException;
38 import java.io.ObjectInputStream;
39 import java.io.OutputStream;
40 import java.io.Serializable;
41 import java.io.UnsupportedEncodingException;
42 import java.nio.ByteBuffer;
43 import java.nio.charset.Charset;
44 import java.nio.charset.UnsupportedCharsetException;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.NoSuchElementException;
52 
53 /**
54  * Immutable sequence of bytes.  Substring is supported by sharing the reference
55  * to the immutable underlying bytes, as with {@link String}.  Concatenation is
56  * likewise supported without copying (long strings) by building a tree of
57  * pieces in {@link RopeByteString}.
58  * <p>
59  * Like {@link String}, the contents of a {@link ByteString} can never be
60  * observed to change, not even in the presence of a data race or incorrect
61  * API usage in the client code.
62  *
63  * @author crazybob@google.com Bob Lee
64  * @author kenton@google.com Kenton Varda
65  * @author carlanton@google.com Carl Haverl
66  * @author martinrb@google.com Martin Buchholz
67  */
68 public abstract class ByteString implements Iterable<Byte>, Serializable {
69 
70   /**
71    * When two strings to be concatenated have a combined length shorter than
72    * this, we just copy their bytes on {@link #concat(ByteString)}.
73    * The trade-off is copy size versus the overhead of creating tree nodes
74    * in {@link RopeByteString}.
75    */
76   static final int CONCATENATE_BY_COPY_SIZE = 128;
77 
78   /**
79    * When copying an InputStream into a ByteString with .readFrom(),
80    * the chunks in the underlying rope start at 256 bytes, but double
81    * each iteration up to 8192 bytes.
82    */
83   static final int MIN_READ_FROM_CHUNK_SIZE = 0x100;  // 256b
84   static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000;  // 8k
85 
86   /**
87    * Empty {@code ByteString}.
88    */
89   public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
90 
91   /**
92    * An interface to efficiently copy {@code byte[]}.
93    *
94    * <p>One of the noticeable costs of copying a byte[] into a new array using
95    * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown
96    * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this
97    * expensive nullification and provide substantial performance gain. Unfortunately this does not
98    * hold on Android runtimes and could make the copy slightly slower due to additional code in
99    * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier
100    * for Hotspot and Android runtimes.
101    */
102   private interface ByteArrayCopier {
103     /**
104      * Copies the specified range of the specified array into a new array
105      */
copyFrom(byte[] bytes, int offset, int size)106     byte[] copyFrom(byte[] bytes, int offset, int size);
107   }
108 
109   /** Implementation of {@code ByteArrayCopier} which uses {@link System#arraycopy}. */
110   private static final class SystemByteArrayCopier implements ByteArrayCopier {
111     @Override
copyFrom(byte[] bytes, int offset, int size)112     public byte[] copyFrom(byte[] bytes, int offset, int size) {
113       byte[] copy = new byte[size];
114       System.arraycopy(bytes, offset, copy, 0, size);
115       return copy;
116     }
117   }
118 
119   /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfRange}. */
120   private static final class ArraysByteArrayCopier implements ByteArrayCopier {
121     @Override
copyFrom(byte[] bytes, int offset, int size)122     public byte[] copyFrom(byte[] bytes, int offset, int size) {
123       return Arrays.copyOfRange(bytes, offset, offset + size);
124     }
125   }
126 
127   private static final ByteArrayCopier byteArrayCopier;
128   static {
129     boolean isAndroid = true;
130     try {
131       Class.forName("android.content.Context");
132     } catch (ClassNotFoundException e) {
133       isAndroid = false;
134     }
135 
136     byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
137   }
138 
139   /**
140    * Cached hash value. Intentionally accessed via a data race, which
141    * is safe because of the Java Memory Model's "no out-of-thin-air values"
142    * guarantees for ints. A value of 0 implies that the hash has not been set.
143    */
144   private int hash = 0;
145 
146   // This constructor is here to prevent subclassing outside of this package,
ByteString()147   ByteString() {}
148 
149   /**
150    * Gets the byte at the given index. This method should be used only for
151    * random access to individual bytes. To access bytes sequentially, use the
152    * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
153    * #substring(int, int)} first if necessary.
154    *
155    * @param index index of byte
156    * @return the value
157    * @throws IndexOutOfBoundsException {@code index < 0 or index >= size}
158    */
byteAt(int index)159   public abstract byte byteAt(int index);
160 
161   /**
162    * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
163    * To avoid auto-boxing, you may get the iterator manually and call
164    * {@link ByteIterator#nextByte()}.
165    *
166    * @return the iterator
167    */
168   @Override
iterator()169   public final ByteIterator iterator() {
170     return new ByteIterator() {
171       private int position = 0;
172       private final int limit = size();
173 
174       @Override
175       public boolean hasNext() {
176         return position < limit;
177       }
178 
179       @Override
180       public Byte next() {
181         // Boxing calls Byte.valueOf(byte), which does not instantiate.
182         return nextByte();
183       }
184 
185       @Override
186       public byte nextByte() {
187         try {
188           return byteAt(position++);
189         } catch (IndexOutOfBoundsException e) {
190           throw new NoSuchElementException(e.getMessage());
191         }
192       }
193 
194       @Override
195       public void remove() {
196         throw new UnsupportedOperationException();
197       }
198     };
199   }
200 
201   /**
202    * This interface extends {@code Iterator<Byte>}, so that we can return an
203    * unboxed {@code byte}.
204    */
205   public interface ByteIterator extends Iterator<Byte> {
206     /**
207      * An alternative to {@link Iterator#next()} that returns an
208      * unboxed primitive {@code byte}.
209      *
210      * @return the next {@code byte} in the iteration
211      * @throws NoSuchElementException if the iteration has no more elements
212      */
nextByte()213     byte nextByte();
214   }
215 
216   /**
217    * Gets the number of bytes.
218    *
219    * @return size in bytes
220    */
size()221   public abstract int size();
222 
223   /**
224    * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
225    *
226    * @return true if this is zero bytes long
227    */
isEmpty()228   public final boolean isEmpty() {
229     return size() == 0;
230   }
231 
232   // =================================================================
233   // ByteString -> substring
234 
235   /**
236    * Return the substring from {@code beginIndex}, inclusive, to the end of the
237    * string.
238    *
239    * @param beginIndex start at this index
240    * @return substring sharing underlying data
241    * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
242    *     {@code beginIndex > size()}.
243    */
substring(int beginIndex)244   public final ByteString substring(int beginIndex) {
245     return substring(beginIndex, size());
246   }
247 
248   /**
249    * Return the substring from {@code beginIndex}, inclusive, to {@code
250    * endIndex}, exclusive.
251    *
252    * @param beginIndex start at this index
253    * @param endIndex   the last character is the one before this index
254    * @return substring sharing underlying data
255    * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
256    *     {@code endIndex > size()}, or {@code beginIndex > endIndex}.
257    */
substring(int beginIndex, int endIndex)258   public abstract ByteString substring(int beginIndex, int endIndex);
259 
260   /**
261    * Tests if this bytestring starts with the specified prefix.
262    * Similar to {@link String#startsWith(String)}
263    *
264    * @param prefix the prefix.
265    * @return <code>true</code> if the byte sequence represented by the
266    *         argument is a prefix of the byte sequence represented by
267    *         this string; <code>false</code> otherwise.
268    */
startsWith(ByteString prefix)269   public final boolean startsWith(ByteString prefix) {
270     return size() >= prefix.size() &&
271            substring(0, prefix.size()).equals(prefix);
272   }
273 
274   /**
275    * Tests if this bytestring ends with the specified suffix.
276    * Similar to {@link String#endsWith(String)}
277    *
278    * @param suffix the suffix.
279    * @return <code>true</code> if the byte sequence represented by the
280    *         argument is a suffix of the byte sequence represented by
281    *         this string; <code>false</code> otherwise.
282    */
endsWith(ByteString suffix)283   public final boolean endsWith(ByteString suffix) {
284     return size() >= suffix.size() &&
285         substring(size() - suffix.size()).equals(suffix);
286   }
287 
288   // =================================================================
289   // byte[] -> ByteString
290 
291   /**
292    * Copies the given bytes into a {@code ByteString}.
293    *
294    * @param bytes source array
295    * @param offset offset in source array
296    * @param size number of bytes to copy
297    * @return new {@code ByteString}
298    */
copyFrom(byte[] bytes, int offset, int size)299   public static ByteString copyFrom(byte[] bytes, int offset, int size) {
300     return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
301   }
302 
303   /**
304    * Copies the given bytes into a {@code ByteString}.
305    *
306    * @param bytes to copy
307    * @return new {@code ByteString}
308    */
copyFrom(byte[] bytes)309   public static ByteString copyFrom(byte[] bytes) {
310     return copyFrom(bytes, 0, bytes.length);
311   }
312 
313   /**
314    * Wraps the given bytes into a {@code ByteString}. Intended for internal only
315    * usage to force a classload of ByteString before LiteralByteString.
316    */
wrap(byte[] bytes)317   static ByteString wrap(byte[] bytes) {
318     // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
319     return new LiteralByteString(bytes);
320   }
321 
322   /**
323    * Wraps the given bytes into a {@code ByteString}. Intended for internal only
324    * usage to force a classload of ByteString before BoundedByteString and
325    * LiteralByteString.
326    */
wrap(byte[] bytes, int offset, int length)327   static ByteString wrap(byte[] bytes, int offset, int length) {
328     return new BoundedByteString(bytes, offset, length);
329   }
330 
331   /**
332    * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
333    * a {@code ByteString}.
334    *
335    * @param bytes source buffer
336    * @param size number of bytes to copy
337    * @return new {@code ByteString}
338    */
copyFrom(ByteBuffer bytes, int size)339   public static ByteString copyFrom(ByteBuffer bytes, int size) {
340     byte[] copy = new byte[size];
341     bytes.get(copy);
342     return new LiteralByteString(copy);
343   }
344 
345   /**
346    * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
347    * a {@code ByteString}.
348    *
349    * @param bytes sourceBuffer
350    * @return new {@code ByteString}
351    */
copyFrom(ByteBuffer bytes)352   public static ByteString copyFrom(ByteBuffer bytes) {
353     return copyFrom(bytes, bytes.remaining());
354   }
355 
356   /**
357    * Encodes {@code text} into a sequence of bytes using the named charset
358    * and returns the result as a {@code ByteString}.
359    *
360    * @param text source string
361    * @param charsetName encoding to use
362    * @return new {@code ByteString}
363    * @throws UnsupportedEncodingException if the encoding isn't found
364    */
copyFrom(String text, String charsetName)365   public static ByteString copyFrom(String text, String charsetName)
366       throws UnsupportedEncodingException {
367     return new LiteralByteString(text.getBytes(charsetName));
368   }
369 
370   /**
371    * Encodes {@code text} into a sequence of bytes using the named charset
372    * and returns the result as a {@code ByteString}.
373    *
374    * @param text source string
375    * @param charset encode using this charset
376    * @return new {@code ByteString}
377    */
copyFrom(String text, Charset charset)378   public static ByteString copyFrom(String text, Charset charset) {
379     return new LiteralByteString(text.getBytes(charset));
380   }
381 
382   /**
383    * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
384    * result as a {@code ByteString}.
385    *
386    * @param text source string
387    * @return new {@code ByteString}
388    */
copyFromUtf8(String text)389   public static ByteString copyFromUtf8(String text) {
390     return new LiteralByteString(text.getBytes(Internal.UTF_8));
391   }
392 
393   // =================================================================
394   // InputStream -> ByteString
395 
396   /**
397    * Completely reads the given stream's bytes into a
398    * {@code ByteString}, blocking if necessary until all bytes are
399    * read through to the end of the stream.
400    *
401    * <b>Performance notes:</b> The returned {@code ByteString} is an
402    * immutable tree of byte arrays ("chunks") of the stream data.  The
403    * first chunk is small, with subsequent chunks each being double
404    * the size, up to 8K.
405    *
406    * <p>Each byte read from the input stream will be copied twice to ensure
407    * that the resulting ByteString is truly immutable.
408    *
409    * @param streamToDrain The source stream, which is read completely
410    *     but not closed.
411    * @return A new {@code ByteString} which is made up of chunks of
412    *     various sizes, depending on the behavior of the underlying
413    *     stream.
414    * @throws IOException IOException is thrown if there is a problem
415    *     reading the underlying stream.
416    */
readFrom(InputStream streamToDrain)417   public static ByteString readFrom(InputStream streamToDrain)
418       throws IOException {
419     return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
420   }
421 
422   /**
423    * Completely reads the given stream's bytes into a
424    * {@code ByteString}, blocking if necessary until all bytes are
425    * read through to the end of the stream.
426    *
427    * <b>Performance notes:</b> The returned {@code ByteString} is an
428    * immutable tree of byte arrays ("chunks") of the stream data.  The
429    * chunkSize parameter sets the size of these byte arrays.
430    *
431    * <p>Each byte read from the input stream will be copied twice to ensure
432    * that the resulting ByteString is truly immutable.
433    *
434    * @param streamToDrain The source stream, which is read completely
435    *     but not closed.
436    * @param chunkSize The size of the chunks in which to read the
437    *     stream.
438    * @return A new {@code ByteString} which is made up of chunks of
439    *     the given size.
440    * @throws IOException IOException is thrown if there is a problem
441    *     reading the underlying stream.
442    */
readFrom(InputStream streamToDrain, int chunkSize)443   public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
444       throws IOException {
445     return readFrom(streamToDrain, chunkSize, chunkSize);
446   }
447 
448   // Helper method that takes the chunk size range as a parameter.
readFrom(InputStream streamToDrain, int minChunkSize, int maxChunkSize)449   public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
450       int maxChunkSize) throws IOException {
451     Collection<ByteString> results = new ArrayList<ByteString>();
452 
453     // copy the inbound bytes into a list of chunks; the chunk size
454     // grows exponentially to support both short and long streams.
455     int chunkSize = minChunkSize;
456     while (true) {
457       ByteString chunk = readChunk(streamToDrain, chunkSize);
458       if (chunk == null) {
459         break;
460       }
461       results.add(chunk);
462       chunkSize = Math.min(chunkSize * 2, maxChunkSize);
463     }
464 
465     return ByteString.copyFrom(results);
466   }
467 
468   /**
469    * Blocks until a chunk of the given size can be made from the
470    * stream, or EOF is reached.  Calls read() repeatedly in case the
471    * given stream implementation doesn't completely fill the given
472    * buffer in one read() call.
473    *
474    * @return A chunk of the desired size, or else a chunk as large as
475    * was available when end of stream was reached. Returns null if the
476    * given stream had no more data in it.
477    */
readChunk(InputStream in, final int chunkSize)478   private static ByteString readChunk(InputStream in, final int chunkSize)
479       throws IOException {
480       final byte[] buf = new byte[chunkSize];
481       int bytesRead = 0;
482       while (bytesRead < chunkSize) {
483         final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
484         if (count == -1) {
485           break;
486         }
487         bytesRead += count;
488       }
489 
490       if (bytesRead == 0) {
491         return null;
492       }
493 
494       // Always make a copy since InputStream could steal a reference to buf.
495       return ByteString.copyFrom(buf, 0, bytesRead);
496   }
497 
498   // =================================================================
499   // Multiple ByteStrings -> One ByteString
500 
501   /**
502    * Concatenate the given {@code ByteString} to this one. Short concatenations,
503    * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
504    * produced by copying the underlying bytes (as per Rope.java, <a
505    * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
506    * BAP95 </a>. In general, the concatenate involves no copying.
507    *
508    * @param other string to concatenate
509    * @return a new {@code ByteString} instance
510    */
concat(ByteString other)511   public final ByteString concat(ByteString other) {
512     if (Integer.MAX_VALUE - size() < other.size()) {
513       throw new IllegalArgumentException("ByteString would be too long: " +
514           size() + "+" + other.size());
515     }
516 
517     return RopeByteString.concatenate(this, other);
518   }
519 
520   /**
521    * Concatenates all byte strings in the iterable and returns the result.
522    * This is designed to run in O(list size), not O(total bytes).
523    *
524    * <p>The returned {@code ByteString} is not necessarily a unique object.
525    * If the list is empty, the returned object is the singleton empty
526    * {@code ByteString}.  If the list has only one element, that
527    * {@code ByteString} will be returned without copying.
528    *
529    * @param byteStrings strings to be concatenated
530    * @return new {@code ByteString}
531    */
copyFrom(Iterable<ByteString> byteStrings)532   public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
533     // Determine the size;
534     final int size;
535     if (!(byteStrings instanceof Collection)) {
536       int tempSize = 0;
537       for (Iterator<ByteString> iter = byteStrings.iterator(); iter.hasNext();
538           iter.next(), ++tempSize) {
539       }
540       size = tempSize;
541     } else {
542       size = ((Collection<ByteString>) byteStrings).size();
543     }
544 
545     if (size == 0) {
546       return EMPTY;
547     }
548 
549     return balancedConcat(byteStrings.iterator(), size);
550   }
551 
552   // Internal function used by copyFrom(Iterable<ByteString>).
553   // Create a balanced concatenation of the next "length" elements from the
554   // iterable.
balancedConcat(Iterator<ByteString> iterator, int length)555   private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
556     assert length >= 1;
557     ByteString result;
558     if (length == 1) {
559       result = iterator.next();
560     } else {
561       int halfLength = length >>> 1;
562       ByteString left = balancedConcat(iterator, halfLength);
563       ByteString right = balancedConcat(iterator, length - halfLength);
564       result = left.concat(right);
565     }
566     return result;
567   }
568 
569   // =================================================================
570   // ByteString -> byte[]
571 
572   /**
573    * Copies bytes into a buffer at the given offset.
574    *
575    * @param target buffer to copy into
576    * @param offset in the target buffer
577    * @throws IndexOutOfBoundsException if the offset is negative or too large
578    */
copyTo(byte[] target, int offset)579   public void copyTo(byte[] target, int offset) {
580     copyTo(target, 0, offset, size());
581   }
582 
583   /**
584    * Copies bytes into a buffer.
585    *
586    * @param target       buffer to copy into
587    * @param sourceOffset offset within these bytes
588    * @param targetOffset offset within the target buffer
589    * @param numberToCopy number of bytes to copy
590    * @throws IndexOutOfBoundsException if an offset or size is negative or too
591    *     large
592    */
copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)593   public final void copyTo(byte[] target, int sourceOffset, int targetOffset,
594       int numberToCopy) {
595     checkRange(sourceOffset, sourceOffset + numberToCopy, size());
596     checkRange(targetOffset, targetOffset + numberToCopy, target.length);
597     if (numberToCopy > 0) {
598       copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
599     }
600   }
601 
602   /**
603    * Internal (package private) implementation of
604    * {@link #copyTo(byte[],int,int,int)}.
605    * It assumes that all error checking has already been performed and that
606    * {@code numberToCopy > 0}.
607    */
copyToInternal(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)608   protected abstract void copyToInternal(byte[] target, int sourceOffset,
609       int targetOffset, int numberToCopy);
610 
611   /**
612    * Copies bytes into a ByteBuffer.
613    *
614    * @param target ByteBuffer to copy into.
615    * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
616    * @throws java.nio.BufferOverflowException if the {@code target}'s
617    *     remaining() space is not large enough to hold the data.
618    */
copyTo(ByteBuffer target)619   public abstract void copyTo(ByteBuffer target);
620 
621   /**
622    * Copies bytes to a {@code byte[]}.
623    *
624    * @return copied bytes
625    */
toByteArray()626   public final byte[] toByteArray() {
627     final int size = size();
628     if (size == 0) {
629       return Internal.EMPTY_BYTE_ARRAY;
630     }
631     byte[] result = new byte[size];
632     copyToInternal(result, 0, 0, size);
633     return result;
634   }
635 
636   /**
637    * Writes a copy of the contents of this byte string to the specified output stream argument.
638    *
639    * @param  out  the output stream to which to write the data.
640    * @throws IOException  if an I/O error occurs.
641    */
writeTo(OutputStream out)642   public abstract void writeTo(OutputStream out) throws IOException;
643 
644   /**
645    * Writes a specified part of this byte string to an output stream.
646    *
647    * @param  out  the output stream to which to write the data.
648    * @param  sourceOffset offset within these bytes
649    * @param  numberToWrite number of bytes to write
650    * @throws IOException  if an I/O error occurs.
651    * @throws IndexOutOfBoundsException if an offset or size is negative or too large
652    */
writeTo(OutputStream out, int sourceOffset, int numberToWrite)653   final void writeTo(OutputStream out, int sourceOffset, int numberToWrite)
654       throws IOException {
655     checkRange(sourceOffset, sourceOffset + numberToWrite, size());
656     if (numberToWrite > 0) {
657       writeToInternal(out, sourceOffset, numberToWrite);
658     }
659   }
660 
661   /**
662    * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes
663    * all error checking has already been done.
664    */
writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)665   abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)
666       throws IOException;
667 
668   /**
669    * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling
670    * this method may result in multiple operations on the target {@link ByteOutput}.
671    *
672    * <p>This method may expose internal backing buffers of the {@link ByteString} to the {@link
673    * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
674    * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
675    *
676    * @param  byteOutput  the output target to receive the bytes
677    * @throws IOException  if an I/O error occurs
678    * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput)
679    */
writeTo(ByteOutput byteOutput)680   abstract void writeTo(ByteOutput byteOutput) throws IOException;
681 
682   /**
683    * Constructs a read-only {@code java.nio.ByteBuffer} whose content
684    * is equal to the contents of this byte string.
685    * The result uses the same backing array as the byte string, if possible.
686    *
687    * @return wrapped bytes
688    */
asReadOnlyByteBuffer()689   public abstract ByteBuffer asReadOnlyByteBuffer();
690 
691   /**
692    * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
693    * such that the concatenation of their contents is equal to the contents
694    * of this byte string.  The result uses the same backing arrays as the
695    * byte string.
696    * <p>
697    * By returning a list, implementations of this method may be able to avoid
698    * copying even when there are multiple backing arrays.
699    *
700    * @return a list of wrapped bytes
701    */
asReadOnlyByteBufferList()702   public abstract List<ByteBuffer> asReadOnlyByteBufferList();
703 
704   /**
705    * Constructs a new {@code String} by decoding the bytes using the
706    * specified charset.
707    *
708    * @param charsetName encode using this charset
709    * @return new string
710    * @throws UnsupportedEncodingException if charset isn't recognized
711    */
toString(String charsetName)712   public final String toString(String charsetName)
713       throws UnsupportedEncodingException {
714     try {
715       return toString(Charset.forName(charsetName));
716     } catch (UnsupportedCharsetException e) {
717       UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName);
718       exception.initCause(e);
719       throw exception;
720     }
721   }
722 
723   /**
724    * Constructs a new {@code String} by decoding the bytes using the
725    * specified charset. Returns the same empty String if empty.
726    *
727    * @param charset encode using this charset
728    * @return new string
729    */
toString(Charset charset)730   public final String toString(Charset charset) {
731     return size() == 0 ? "" : toStringInternal(charset);
732   }
733 
734   /**
735    * Constructs a new {@code String} by decoding the bytes using the
736    * specified charset.
737    *
738    * @param charset encode using this charset
739    * @return new string
740    */
toStringInternal(Charset charset)741   protected abstract String toStringInternal(Charset charset);
742 
743   // =================================================================
744   // UTF-8 decoding
745 
746   /**
747    * Constructs a new {@code String} by decoding the bytes as UTF-8.
748    *
749    * @return new string using UTF-8 encoding
750    */
toStringUtf8()751   public final String toStringUtf8() {
752     return toString(Internal.UTF_8);
753   }
754 
755   /**
756    * Tells whether this {@code ByteString} represents a well-formed UTF-8
757    * byte sequence, such that the original bytes can be converted to a
758    * String object and then round tripped back to bytes without loss.
759    *
760    * <p>More precisely, returns {@code true} whenever: <pre> {@code
761    * Arrays.equals(byteString.toByteArray(),
762    *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
763    * }</pre>
764    *
765    * <p>This method returns {@code false} for "overlong" byte sequences,
766    * as well as for 3-byte sequences that would map to a surrogate
767    * character, in accordance with the restricted definition of UTF-8
768    * introduced in Unicode 3.1.  Note that the UTF-8 decoder included in
769    * Oracle's JDK has been modified to also reject "overlong" byte
770    * sequences, but (as of 2011) still accepts 3-byte surrogate
771    * character byte sequences.
772    *
773    * <p>See the Unicode Standard,<br>
774    * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
775    * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
776    *
777    * @return whether the bytes in this {@code ByteString} are a
778    * well-formed UTF-8 byte sequence
779    */
isValidUtf8()780   public abstract boolean isValidUtf8();
781 
782   /**
783    * Tells whether the given byte sequence is a well-formed, malformed, or
784    * incomplete UTF-8 byte sequence.  This method accepts and returns a partial
785    * state result, allowing the bytes for a complete UTF-8 byte sequence to be
786    * composed from multiple {@code ByteString} segments.
787    *
788    * @param state either {@code 0} (if this is the initial decoding operation)
789    *     or the value returned from a call to a partial decoding method for the
790    *     previous bytes
791    * @param offset offset of the first byte to check
792    * @param length number of bytes to check
793    *
794    * @return {@code -1} if the partial byte sequence is definitely malformed,
795    * {@code 0} if it is well-formed (no additional input needed), or, if the
796    * byte sequence is "incomplete", i.e. apparently terminated in the middle of
797    * a character, an opaque integer "state" value containing enough information
798    * to decode the character when passed to a subsequent invocation of a
799    * partial decoding method.
800    */
partialIsValidUtf8(int state, int offset, int length)801   protected abstract int partialIsValidUtf8(int state, int offset, int length);
802 
803   // =================================================================
804   // equals() and hashCode()
805 
806   @Override
807   public abstract boolean equals(Object o);
808 
809   /**
810    * Base class for leaf {@link ByteString}s (i.e. non-ropes).
811    */
812   abstract static class LeafByteString extends ByteString {
813     @Override
getTreeDepth()814     protected final int getTreeDepth() {
815       return 0;
816     }
817 
818     @Override
isBalanced()819     protected final boolean isBalanced() {
820       return true;
821     }
822 
823     /**
824      * Check equality of the substring of given length of this object starting at
825      * zero with another {@code ByteString} substring starting at offset.
826      *
827      * @param other  what to compare a substring in
828      * @param offset offset into other
829      * @param length number of bytes to compare
830      * @return true for equality of substrings, else false.
831      */
equalsRange(ByteString other, int offset, int length)832     abstract boolean equalsRange(ByteString other, int offset, int length);
833   }
834 
835   /**
836    * Compute the hashCode using the traditional algorithm from {@link
837    * ByteString}.
838    *
839    * @return hashCode value
840    */
841   @Override
hashCode()842   public final int hashCode() {
843     int h = hash;
844 
845     if (h == 0) {
846       int size = size();
847       h = partialHash(size, 0, size);
848       if (h == 0) {
849         h = 1;
850       }
851       hash = h;
852     }
853     return h;
854   }
855 
856   // =================================================================
857   // Input stream
858 
859   /**
860    * Creates an {@code InputStream} which can be used to read the bytes.
861    * <p>
862    * The {@link InputStream} returned by this method is guaranteed to be
863    * completely non-blocking.  The method {@link InputStream#available()}
864    * returns the number of bytes remaining in the stream. The methods
865    * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
866    * and {@link InputStream#skip(long)} will read/skip as many bytes as are
867    * available.  The method {@link InputStream#markSupported()} returns
868    * {@code true}.
869    * <p>
870    * The methods in the returned {@link InputStream} might <b>not</b> be
871    * thread safe.
872    *
873    * @return an input stream that returns the bytes of this byte string.
874    */
newInput()875   public abstract InputStream newInput();
876 
877   /**
878    * Creates a {@link CodedInputStream} which can be used to read the bytes.
879    * Using this is often more efficient than creating a {@link CodedInputStream}
880    * that wraps the result of {@link #newInput()}.
881    *
882    * @return stream based on wrapped data
883    */
newCodedInput()884   public abstract CodedInputStream newCodedInput();
885 
886   // =================================================================
887   // Output stream
888 
889   /**
890    * Creates a new {@link Output} with the given initial capacity. Call {@link
891    * Output#toByteString()} to create the {@code ByteString} instance.
892    * <p>
893    * A {@link ByteString.Output} offers the same functionality as a
894    * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
895    * rather than a {@code byte} array.
896    *
897    * @param initialCapacity estimate of number of bytes to be written
898    * @return {@code OutputStream} for building a {@code ByteString}
899    */
newOutput(int initialCapacity)900   public static Output newOutput(int initialCapacity) {
901     return new Output(initialCapacity);
902   }
903 
904   /**
905    * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
906    * the {@code ByteString} instance.
907    * <p>
908    * A {@link ByteString.Output} offers the same functionality as a
909    * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
910    * rather than a {@code byte array}.
911    *
912    * @return {@code OutputStream} for building a {@code ByteString}
913    */
newOutput()914   public static Output newOutput() {
915     return new Output(CONCATENATE_BY_COPY_SIZE);
916   }
917 
918   /**
919    * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
920    * create the {@code ByteString} instance.
921    */
922   public static final class Output extends OutputStream {
923     // Implementation note.
924     // The public methods of this class must be synchronized.  ByteStrings
925     // are guaranteed to be immutable.  Without some sort of locking, it could
926     // be possible for one thread to call toByteSring(), while another thread
927     // is still modifying the underlying byte array.
928 
929     private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
930     // argument passed by user, indicating initial capacity.
931     private final int initialCapacity;
932     // ByteStrings to be concatenated to create the result
933     private final ArrayList<ByteString> flushedBuffers;
934     // Total number of bytes in the ByteStrings of flushedBuffers
935     private int flushedBuffersTotalBytes;
936     // Current buffer to which we are writing
937     private byte[] buffer;
938     // Location in buffer[] to which we write the next byte.
939     private int bufferPos;
940 
941     /**
942      * Creates a new ByteString output stream with the specified
943      * initial capacity.
944      *
945      * @param initialCapacity  the initial capacity of the output stream.
946      */
Output(int initialCapacity)947     Output(int initialCapacity) {
948       if (initialCapacity < 0) {
949         throw new IllegalArgumentException("Buffer size < 0");
950       }
951       this.initialCapacity = initialCapacity;
952       this.flushedBuffers = new ArrayList<ByteString>();
953       this.buffer = new byte[initialCapacity];
954     }
955 
956     @Override
write(int b)957     public synchronized void write(int b) {
958       if (bufferPos == buffer.length) {
959         flushFullBuffer(1);
960       }
961       buffer[bufferPos++] = (byte)b;
962     }
963 
964     @Override
write(byte[] b, int offset, int length)965     public synchronized void write(byte[] b, int offset, int length)  {
966       if (length <= buffer.length - bufferPos) {
967         // The bytes can fit into the current buffer.
968         System.arraycopy(b, offset, buffer, bufferPos, length);
969         bufferPos += length;
970       } else {
971         // Use up the current buffer
972         int copySize  = buffer.length - bufferPos;
973         System.arraycopy(b, offset, buffer, bufferPos, copySize);
974         offset += copySize;
975         length -= copySize;
976         // Flush the buffer, and get a new buffer at least big enough to cover
977         // what we still need to output
978         flushFullBuffer(length);
979         System.arraycopy(b, offset, buffer, 0 /* count */, length);
980         bufferPos = length;
981       }
982     }
983 
984     /**
985      * Creates a byte string. Its size is the current size of this output
986      * stream and its output has been copied to it.
987      *
988      * @return  the current contents of this output stream, as a byte string.
989      */
toByteString()990     public synchronized ByteString toByteString() {
991       flushLastBuffer();
992       return ByteString.copyFrom(flushedBuffers);
993     }
994 
995     /**
996      * Implement java.util.Arrays.copyOf() for jdk 1.5.
997      */
copyArray(byte[] buffer, int length)998     private byte[] copyArray(byte[] buffer, int length) {
999       byte[] result = new byte[length];
1000       System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
1001       return result;
1002     }
1003 
1004     /**
1005      * Writes the complete contents of this byte array output stream to
1006      * the specified output stream argument.
1007      *
1008      * @param out the output stream to which to write the data.
1009      * @throws IOException  if an I/O error occurs.
1010      */
writeTo(OutputStream out)1011     public void writeTo(OutputStream out) throws IOException {
1012       ByteString[] cachedFlushBuffers;
1013       byte[] cachedBuffer;
1014       int cachedBufferPos;
1015       synchronized (this) {
1016         // Copy the information we need into local variables so as to hold
1017         // the lock for as short a time as possible.
1018         cachedFlushBuffers =
1019             flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
1020         cachedBuffer = buffer;
1021         cachedBufferPos = bufferPos;
1022       }
1023       for (ByteString byteString : cachedFlushBuffers) {
1024         byteString.writeTo(out);
1025       }
1026 
1027       out.write(copyArray(cachedBuffer, cachedBufferPos));
1028     }
1029 
1030     /**
1031      * Returns the current size of the output stream.
1032      *
1033      * @return  the current size of the output stream
1034      */
size()1035     public synchronized int size() {
1036       return flushedBuffersTotalBytes + bufferPos;
1037     }
1038 
1039     /**
1040      * Resets this stream, so that all currently accumulated output in the
1041      * output stream is discarded. The output stream can be used again,
1042      * reusing the already allocated buffer space.
1043      */
reset()1044     public synchronized void reset() {
1045       flushedBuffers.clear();
1046       flushedBuffersTotalBytes = 0;
1047       bufferPos = 0;
1048     }
1049 
1050     @Override
toString()1051     public String toString() {
1052       return String.format("<ByteString.Output@%s size=%d>",
1053           Integer.toHexString(System.identityHashCode(this)), size());
1054     }
1055 
1056     /**
1057      * Internal function used by writers.  The current buffer is full, and the
1058      * writer needs a new buffer whose size is at least the specified minimum
1059      * size.
1060      */
flushFullBuffer(int minSize)1061     private void flushFullBuffer(int minSize)  {
1062       flushedBuffers.add(new LiteralByteString(buffer));
1063       flushedBuffersTotalBytes += buffer.length;
1064       // We want to increase our total capacity by 50%, but as a minimum,
1065       // the new buffer should also at least be >= minSize and
1066       // >= initial Capacity.
1067       int newSize = Math.max(initialCapacity,
1068           Math.max(minSize, flushedBuffersTotalBytes >>> 1));
1069       buffer = new byte[newSize];
1070       bufferPos = 0;
1071     }
1072 
1073     /**
1074      * Internal function used by {@link #toByteString()}. The current buffer may
1075      * or may not be full, but it needs to be flushed.
1076      */
flushLastBuffer()1077     private void flushLastBuffer()  {
1078       if (bufferPos < buffer.length) {
1079         if (bufferPos > 0) {
1080           byte[] bufferCopy = copyArray(buffer, bufferPos);
1081           flushedBuffers.add(new LiteralByteString(bufferCopy));
1082         }
1083         // We reuse this buffer for further writes.
1084       } else {
1085         // Buffer is completely full.  Huzzah.
1086         flushedBuffers.add(new LiteralByteString(buffer));
1087         // 99% of the time, we're not going to use this OutputStream again.
1088         // We set buffer to an empty byte stream so that we're handling this
1089         // case without wasting space.  In the rare case that more writes
1090         // *do* occur, this empty buffer will be flushed and an appropriately
1091         // sized new buffer will be created.
1092         buffer = EMPTY_BYTE_ARRAY;
1093       }
1094       flushedBuffersTotalBytes += bufferPos;
1095       bufferPos = 0;
1096     }
1097   }
1098 
1099   /**
1100    * Constructs a new {@code ByteString} builder, which allows you to
1101    * efficiently construct a {@code ByteString} by writing to a {@link
1102    * CodedOutputStream}. Using this is much more efficient than calling {@code
1103    * newOutput()} and wrapping that in a {@code CodedOutputStream}.
1104    *
1105    * <p>This is package-private because it's a somewhat confusing interface.
1106    * Users can call {@link Message#toByteString()} instead of calling this
1107    * directly.
1108    *
1109    * @param size The target byte size of the {@code ByteString}.  You must write
1110    *     exactly this many bytes before building the result.
1111    * @return the builder
1112    */
newCodedBuilder(int size)1113   static CodedBuilder newCodedBuilder(int size) {
1114     return new CodedBuilder(size);
1115   }
1116 
1117   /** See {@link ByteString#newCodedBuilder(int)}. */
1118   static final class CodedBuilder {
1119     private final CodedOutputStream output;
1120     private final byte[] buffer;
1121 
CodedBuilder(int size)1122     private CodedBuilder(int size) {
1123       buffer = new byte[size];
1124       output = CodedOutputStream.newInstance(buffer);
1125     }
1126 
build()1127     public ByteString build() {
1128       output.checkNoSpaceLeft();
1129 
1130       // We can be confident that the CodedOutputStream will not modify the
1131       // underlying bytes anymore because it already wrote all of them.  So,
1132       // no need to make a copy.
1133       return new LiteralByteString(buffer);
1134     }
1135 
getCodedOutput()1136     public CodedOutputStream getCodedOutput() {
1137       return output;
1138     }
1139   }
1140 
1141   // =================================================================
1142   // Methods {@link RopeByteString} needs on instances, which aren't part of the
1143   // public API.
1144 
1145   /**
1146    * Return the depth of the tree representing this {@code ByteString}, if any,
1147    * whose root is this node. If this is a leaf node, return 0.
1148    *
1149    * @return tree depth or zero
1150    */
getTreeDepth()1151   protected abstract int getTreeDepth();
1152 
1153   /**
1154    * Return {@code true} if this ByteString is literal (a leaf node) or a
1155    * flat-enough tree in the sense of {@link RopeByteString}.
1156    *
1157    * @return true if the tree is flat enough
1158    */
isBalanced()1159   protected abstract boolean isBalanced();
1160 
1161   /**
1162    * Return the cached hash code if available.
1163    *
1164    * @return value of cached hash code or 0 if not computed yet
1165    */
peekCachedHashCode()1166   protected final int peekCachedHashCode() {
1167     return hash;
1168   }
1169 
1170   /**
1171    * Compute the hash across the value bytes starting with the given hash, and
1172    * return the result.  This is used to compute the hash across strings
1173    * represented as a set of pieces by allowing the hash computation to be
1174    * continued from piece to piece.
1175    *
1176    * @param h starting hash value
1177    * @param offset offset into this value to start looking at data values
1178    * @param length number of data values to include in the hash computation
1179    * @return ending hash value
1180    */
partialHash(int h, int offset, int length)1181   protected abstract int partialHash(int h, int offset, int length);
1182 
1183   /**
1184    * Checks that the given index falls within the specified array size.
1185    *
1186    * @param index the index position to be tested
1187    * @param size the length of the array
1188    * @throws IndexOutOfBoundsException if the index does not fall within the array.
1189    */
checkIndex(int index, int size)1190   static void checkIndex(int index, int size) {
1191     if ((index | (size - (index + 1))) < 0) {
1192       if (index < 0) {
1193         throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
1194       }
1195       throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size);
1196     }
1197   }
1198 
1199   /**
1200    * Checks that the given range falls within the bounds of an array
1201    *
1202    * @param startIndex the start index of the range (inclusive)
1203    * @param endIndex the end index of the range (exclusive)
1204    * @param size the size of the array.
1205    * @return the length of the range.
1206    * @throws IndexOutOfBoundsException some or all of the range falls outside of the array.
1207    */
checkRange(int startIndex, int endIndex, int size)1208   static int checkRange(int startIndex, int endIndex, int size) {
1209     final int length = endIndex - startIndex;
1210     if ((startIndex | endIndex | length | (size - endIndex)) < 0) {
1211       if (startIndex < 0) {
1212         throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0");
1213       }
1214       if (endIndex < startIndex) {
1215         throw new IndexOutOfBoundsException(
1216             "Beginning index larger than ending index: " + startIndex + ", " + endIndex);
1217       }
1218       // endIndex >= size
1219       throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size);
1220     }
1221     return length;
1222   }
1223 
1224   @Override
toString()1225   public final String toString() {
1226     return String.format("<ByteString@%s size=%d>",
1227         Integer.toHexString(System.identityHashCode(this)), size());
1228   }
1229 
1230   /**
1231    * This class implements a {@link com.google.protobuf.ByteString} backed by a
1232    * single array of bytes, contiguous in memory. It supports substring by
1233    * pointing to only a sub-range of the underlying byte array, meaning that a
1234    * substring will reference the full byte-array of the string it's made from,
1235    * exactly as with {@link String}.
1236    *
1237    * @author carlanton@google.com (Carl Haverl)
1238    */
1239   // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1240   // static initializer loads LiteralByteString and another thread loads LiteralByteString.
1241   private static class LiteralByteString extends ByteString.LeafByteString {
1242     private static final long serialVersionUID = 1L;
1243 
1244     protected final byte[] bytes;
1245 
1246     /**
1247      * Creates a {@code LiteralByteString} backed by the given array, without
1248      * copying.
1249      *
1250      * @param bytes array to wrap
1251      */
LiteralByteString(byte[] bytes)1252     LiteralByteString(byte[] bytes) {
1253       this.bytes = bytes;
1254     }
1255 
1256     @Override
byteAt(int index)1257     public byte byteAt(int index) {
1258       // Unlike most methods in this class, this one is a direct implementation
1259       // ignoring the potential offset because we need to do range-checking in the
1260       // substring case anyway.
1261       return bytes[index];
1262     }
1263 
1264     @Override
size()1265     public int size() {
1266       return bytes.length;
1267     }
1268 
1269     // =================================================================
1270     // ByteString -> substring
1271 
1272     @Override
substring(int beginIndex, int endIndex)1273     public final ByteString substring(int beginIndex, int endIndex) {
1274       final int length = checkRange(beginIndex, endIndex, size());
1275 
1276       if (length == 0) {
1277         return ByteString.EMPTY;
1278       }
1279 
1280       return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
1281     }
1282 
1283     // =================================================================
1284     // ByteString -> byte[]
1285 
1286     @Override
copyToInternal( byte[] target, int sourceOffset, int targetOffset, int numberToCopy)1287     protected void copyToInternal(
1288         byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
1289       // Optimized form, not for subclasses, since we don't call
1290       // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
1291       // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
1292       System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
1293     }
1294 
1295     @Override
copyTo(ByteBuffer target)1296     public final void copyTo(ByteBuffer target) {
1297       target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
1298     }
1299 
1300     @Override
asReadOnlyByteBuffer()1301     public final ByteBuffer asReadOnlyByteBuffer() {
1302       return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
1303     }
1304 
1305     @Override
asReadOnlyByteBufferList()1306     public final List<ByteBuffer> asReadOnlyByteBufferList() {
1307       return Collections.singletonList(asReadOnlyByteBuffer());
1308     }
1309 
1310     @Override
writeTo(OutputStream outputStream)1311     public final void writeTo(OutputStream outputStream) throws IOException {
1312       outputStream.write(toByteArray());
1313     }
1314 
1315     @Override
writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)1316     final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
1317         throws IOException {
1318       outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
1319     }
1320 
1321     @Override
writeTo(ByteOutput output)1322     final void writeTo(ByteOutput output) throws IOException {
1323       output.writeLazy(bytes, getOffsetIntoBytes(), size());
1324     }
1325 
1326     @Override
toStringInternal(Charset charset)1327     protected final String toStringInternal(Charset charset) {
1328       return new String(bytes, getOffsetIntoBytes(), size(), charset);
1329     }
1330 
1331     // =================================================================
1332     // UTF-8 decoding
1333 
1334     @Override
isValidUtf8()1335     public final boolean isValidUtf8() {
1336       int offset = getOffsetIntoBytes();
1337       return Utf8.isValidUtf8(bytes, offset, offset + size());
1338     }
1339 
1340     @Override
partialIsValidUtf8(int state, int offset, int length)1341     protected final int partialIsValidUtf8(int state, int offset, int length) {
1342       int index = getOffsetIntoBytes() + offset;
1343       return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
1344     }
1345 
1346     // =================================================================
1347     // equals() and hashCode()
1348 
1349     @Override
equals(Object other)1350     public final boolean equals(Object other) {
1351       if (other == this) {
1352         return true;
1353       }
1354       if (!(other instanceof ByteString)) {
1355         return false;
1356       }
1357 
1358       if (size() != ((ByteString) other).size()) {
1359         return false;
1360       }
1361       if (size() == 0) {
1362         return true;
1363       }
1364 
1365       if (other instanceof LiteralByteString) {
1366         LiteralByteString otherAsLiteral = (LiteralByteString) other;
1367         // If we know the hash codes and they are not equal, we know the byte
1368         // strings are not equal.
1369         int thisHash = peekCachedHashCode();
1370         int thatHash = otherAsLiteral.peekCachedHashCode();
1371         if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
1372           return false;
1373         }
1374 
1375         return equalsRange((LiteralByteString) other, 0, size());
1376       } else {
1377         // RopeByteString and NioByteString.
1378         return other.equals(this);
1379       }
1380     }
1381 
1382     /**
1383      * Check equality of the substring of given length of this object starting at
1384      * zero with another {@code LiteralByteString} substring starting at offset.
1385      *
1386      * @param other  what to compare a substring in
1387      * @param offset offset into other
1388      * @param length number of bytes to compare
1389      * @return true for equality of substrings, else false.
1390      */
1391     @Override
equalsRange(ByteString other, int offset, int length)1392     final boolean equalsRange(ByteString other, int offset, int length) {
1393       if (length > other.size()) {
1394         throw new IllegalArgumentException("Length too large: " + length + size());
1395       }
1396       if (offset + length > other.size()) {
1397         throw new IllegalArgumentException(
1398             "Ran off end of other: " + offset + ", " + length + ", " + other.size());
1399       }
1400 
1401       if (other instanceof LiteralByteString) {
1402         LiteralByteString lbsOther = (LiteralByteString) other;
1403         byte[] thisBytes = bytes;
1404         byte[] otherBytes = lbsOther.bytes;
1405         int thisLimit = getOffsetIntoBytes() + length;
1406         for (
1407             int thisIndex = getOffsetIntoBytes(),
1408                 otherIndex = lbsOther.getOffsetIntoBytes() + offset;
1409             (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
1410           if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
1411             return false;
1412           }
1413         }
1414         return true;
1415       }
1416 
1417       return other.substring(offset, offset + length).equals(substring(0, length));
1418     }
1419 
1420     @Override
partialHash(int h, int offset, int length)1421     protected final int partialHash(int h, int offset, int length) {
1422       return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length);
1423     }
1424 
1425     // =================================================================
1426     // Input stream
1427 
1428     @Override
newInput()1429     public final InputStream newInput() {
1430       return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
1431     }
1432 
1433     @Override
newCodedInput()1434     public final CodedInputStream newCodedInput() {
1435       // We trust CodedInputStream not to modify the bytes, or to give anyone
1436       // else access to them.
1437       return CodedInputStream.newInstance(
1438           bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */);
1439     }
1440 
1441     // =================================================================
1442     // Internal methods
1443 
1444     /**
1445      * Offset into {@code bytes[]} to use, non-zero for substrings.
1446      *
1447      * @return always 0 for this class
1448      */
getOffsetIntoBytes()1449     protected int getOffsetIntoBytes() {
1450       return 0;
1451     }
1452   }
1453 
1454   /**
1455    * This class is used to represent the substring of a {@link ByteString} over a
1456    * single byte array. In terms of the public API of {@link ByteString}, you end
1457    * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
1458    * ByteString#substring(int, int)}.
1459    *
1460    * <p>This class contains most of the overhead involved in creating a substring
1461    * from a {@link LiteralByteString}.  The overhead involves some range-checking
1462    * and two extra fields.
1463    *
1464    * @author carlanton@google.com (Carl Haverl)
1465    */
1466   // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1467   // static initializer loads LiteralByteString and another thread loads BoundedByteString.
1468   private static final class BoundedByteString extends LiteralByteString {
1469 
1470     private final int bytesOffset;
1471     private final int bytesLength;
1472 
1473     /**
1474      * Creates a {@code BoundedByteString} backed by the sub-range of given array,
1475      * without copying.
1476      *
1477      * @param bytes  array to wrap
1478      * @param offset index to first byte to use in bytes
1479      * @param length number of bytes to use from bytes
1480      * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
1481      *                                  or if {@code offset + length >
1482      *                                  bytes.length}.
1483      */
BoundedByteString(byte[] bytes, int offset, int length)1484     BoundedByteString(byte[] bytes, int offset, int length) {
1485       super(bytes);
1486       checkRange(offset, offset + length, bytes.length);
1487 
1488       this.bytesOffset = offset;
1489       this.bytesLength = length;
1490     }
1491 
1492     /**
1493      * Gets the byte at the given index.
1494      * Throws {@link ArrayIndexOutOfBoundsException}
1495      * for backwards-compatibility reasons although it would more properly be
1496      * {@link IndexOutOfBoundsException}.
1497      *
1498      * @param index index of byte
1499      * @return the value
1500      * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
1501      */
1502     @Override
byteAt(int index)1503     public byte byteAt(int index) {
1504       // We must check the index ourselves as we cannot rely on Java array index
1505       // checking for substrings.
1506       checkIndex(index, size());
1507       return bytes[bytesOffset + index];
1508     }
1509 
1510     @Override
size()1511     public int size() {
1512       return bytesLength;
1513     }
1514 
1515     @Override
getOffsetIntoBytes()1516     protected int getOffsetIntoBytes() {
1517       return bytesOffset;
1518     }
1519 
1520     // =================================================================
1521     // ByteString -> byte[]
1522 
1523     @Override
copyToInternal(byte[] target, int sourceOffset, int targetOffset, int numberToCopy)1524     protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset,
1525         int numberToCopy) {
1526       System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
1527           targetOffset, numberToCopy);
1528     }
1529 
1530     // =================================================================
1531     // Serializable
1532 
1533     private static final long serialVersionUID = 1L;
1534 
writeReplace()1535     Object writeReplace() {
1536       return ByteString.wrap(toByteArray());
1537     }
1538 
readObject(@uppressWarnings"unused") ObjectInputStream in)1539     private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
1540       throw new InvalidObjectException(
1541           "BoundedByteStream instances are not to be serialized directly");
1542     }
1543   }
1544 }
1545