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
31package com.google.protobuf;
32
33import java.io.ByteArrayInputStream;
34import java.io.ByteArrayOutputStream;
35import java.io.IOException;
36import java.io.InputStream;
37import java.io.InvalidObjectException;
38import java.io.ObjectInputStream;
39import java.io.OutputStream;
40import java.io.Serializable;
41import java.io.UnsupportedEncodingException;
42import java.nio.ByteBuffer;
43import java.nio.charset.Charset;
44import java.nio.charset.UnsupportedCharsetException;
45import java.util.ArrayList;
46import java.util.Arrays;
47import java.util.Collection;
48import java.util.Collections;
49import java.util.Iterator;
50import java.util.List;
51import 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 */
68public 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 noticable 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     */
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
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
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,
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   */
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
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     */
213    byte nextByte();
214  }
215
216  /**
217   * Gets the number of bytes.
218   *
219   * @return size in bytes
220   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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.
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   */
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   */
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   */
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.
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   */
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   */
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   */
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   */
619  public abstract void copyTo(ByteBuffer target);
620
621  /**
622   * Copies bytes to a {@code byte[]}.
623   *
624   * @return copied bytes
625   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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   */
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
814    protected final int getTreeDepth() {
815      return 0;
816    }
817
818    @Override
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     */
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
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   */
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   */
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   */
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   */
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     */
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
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
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     */
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     */
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     */
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     */
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     */
1044    public synchronized void reset() {
1045      flushedBuffers.clear();
1046      flushedBuffersTotalBytes = 0;
1047      bufferPos = 0;
1048    }
1049
1050    @Override
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     */
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     */
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   */
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
1122    private CodedBuilder(int size) {
1123      buffer = new byte[size];
1124      output = CodedOutputStream.newInstance(buffer);
1125    }
1126
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
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   */
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   */
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   */
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   */
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   */
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   */
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
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     */
1252    LiteralByteString(byte[] bytes) {
1253      this.bytes = bytes;
1254    }
1255
1256    @Override
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
1265    public int size() {
1266      return bytes.length;
1267    }
1268
1269    // =================================================================
1270    // ByteString -> substring
1271
1272    @Override
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
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
1296    public final void copyTo(ByteBuffer target) {
1297      target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
1298    }
1299
1300    @Override
1301    public final ByteBuffer asReadOnlyByteBuffer() {
1302      return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
1303    }
1304
1305    @Override
1306    public final List<ByteBuffer> asReadOnlyByteBufferList() {
1307      return Collections.singletonList(asReadOnlyByteBuffer());
1308    }
1309
1310    @Override
1311    public final void writeTo(OutputStream outputStream) throws IOException {
1312      outputStream.write(toByteArray());
1313    }
1314
1315    @Override
1316    final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
1317        throws IOException {
1318      outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
1319    }
1320
1321    @Override
1322    final void writeTo(ByteOutput output) throws IOException {
1323      output.writeLazy(bytes, getOffsetIntoBytes(), size());
1324    }
1325
1326    @Override
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
1335    public final boolean isValidUtf8() {
1336      int offset = getOffsetIntoBytes();
1337      return Utf8.isValidUtf8(bytes, offset, offset + size());
1338    }
1339
1340    @Override
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
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
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
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
1429    public final InputStream newInput() {
1430      return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
1431    }
1432
1433    @Override
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     */
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     */
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
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
1511    public int size() {
1512      return bytesLength;
1513    }
1514
1515    @Override
1516    protected int getOffsetIntoBytes() {
1517      return bytesOffset;
1518    }
1519
1520    // =================================================================
1521    // ByteString -> byte[]
1522
1523    @Override
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
1535    Object writeReplace() {
1536      return ByteString.wrap(toByteArray());
1537    }
1538
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