Class ByteString

  • All Implemented Interfaces:
    Iterable<Byte>

    @CheckReturnValue
    public abstract class ByteString
    extends Object
    implements Iterable<Byte>
    Immutable sequence of bytes. Provides conversions to and from byte[], String, ByteBuffer, InputStream, OutputStream. Also provides a conversion to CodedInputStream.

    Like String, the contents of a ByteString can never be observed to change, not even in the presence of a data race or incorrect API usage in the client code.

    Substring is supported by sharing the reference to the immutable underlying bytes. Concatenation is likewise supported without copying (long strings) by building a tree of pieces in RopeByteString.

    • Field Detail

      • EMPTY

        public static final ByteString EMPTY
        Empty ByteString.
    • Method Detail

      • byteAt

        public abstract byte byteAt​(int index)
        Gets the byte at the given index. This method should be used only for random access to individual bytes. To access bytes sequentially, use the ByteString.ByteIterator returned by iterator(), and call substringNoCopy(int, int) first if necessary.
        Parameters:
        index - index of byte
        Returns:
        the value
        Throws:
        IndexOutOfBoundsException - index < 0 or index >= size
      • size

        public abstract int size()
        Gets the number of bytes.
        Returns:
        size in bytes
      • isEmpty

        public final boolean isEmpty()
        Returns true if the size is 0, false otherwise.
        Returns:
        true if this is zero bytes long
      • empty

        public static final ByteString empty()
        Returns an empty ByteString of size 0.
      • unsignedLexicographicalComparator

        public static Comparator<ByteString> unsignedLexicographicalComparator()
        Returns a Comparator which compares ByteString-s lexicographically as sequences of unsigned bytes (i.e. values between 0 and 255, inclusive).

        For example, (byte) -1 is considered to be greater than (byte) 1 because it is interpreted as an unsigned value, 255:

        • `-1` -> 0b11111111 (two's complement) -> 255
        • `1` -> 0b00000001 -> 1
      • substring

        public final ByteString substring​(int beginIndex)
        Return the substring from beginIndex, inclusive, to the end of the string.
        Parameters:
        beginIndex - start at this index
        Returns:
        substring
        Throws:
        IndexOutOfBoundsException - if beginIndex < 0 or beginIndex > size().
      • substring

        public abstract ByteString substring​(int beginIndex,
                                             int endIndex)
        Return the substring from beginIndex, inclusive, to endIndex, exclusive.
        Parameters:
        beginIndex - start at this index
        endIndex - the last character is the one before this index
        Returns:
        substring
        Throws:
        IndexOutOfBoundsException - if beginIndex < 0, endIndex > size(), or beginIndex > endIndex.
      • substringNoCopy

        public final ByteString substringNoCopy​(int beginIndex)
        Return the substring from beginIndex, inclusive, to the end of the string. Unlike substring(int) this method tries to avoid copies of the underlying data where possible, but may still copy in some situations.
        Parameters:
        beginIndex - start at this index
        Returns:
        substring sharing underlying data
        Throws:
        IndexOutOfBoundsException - if beginIndex < 0 or beginIndex > size().
      • substringNoCopy

        public abstract ByteString substringNoCopy​(int beginIndex,
                                                   int endIndex)
        Return the substring from beginIndex, inclusive, to endIndex, exclusive. Unlike substring(int, int) this method tries to avoid copies of the underlying data where possible, but may still copy in some situations.
        Parameters:
        beginIndex - start at this index
        endIndex - the last character is the one before this index
        Returns:
        substring sharing underlying data
        Throws:
        IndexOutOfBoundsException - if beginIndex < 0, endIndex > size(), or beginIndex > endIndex.
      • startsWith

        public final boolean startsWith​(ByteString prefix)
        Tests if this bytestring starts with the specified prefix. Similar to String.startsWith(String)
        Parameters:
        prefix - the prefix.
        Returns:
        true if the byte sequence represented by the argument is a prefix of the byte sequence represented by this string; false otherwise.
      • endsWith

        public final boolean endsWith​(ByteString suffix)
        Tests if this bytestring ends with the specified suffix. Similar to String.endsWith(String)
        Parameters:
        suffix - the suffix.
        Returns:
        true if the byte sequence represented by the argument is a suffix of the byte sequence represented by this string; false otherwise.
      • fromHex

        public static ByteString fromHex​(@CompileTimeConstant
                                         String hexString)
        Returns a ByteString from a hexadecimal String.
        Parameters:
        hexString - String of hexadecimal digits to create ByteString from.
        Throws:
        NumberFormatException - if the hexString does not contain a parsable hex String.
      • copyFrom

        public static ByteString copyFrom​(byte[] bytes,
                                          int offset,
                                          int size)
        Copies the given bytes into a ByteString.
        Parameters:
        bytes - source array
        offset - offset in source array
        size - number of bytes to copy
        Returns:
        new ByteString
        Throws:
        IndexOutOfBoundsException - if offset or size are out of bounds
      • copyFrom

        public static ByteString copyFrom​(byte[] bytes)
        Copies the given bytes into a ByteString.
        Parameters:
        bytes - to copy
        Returns:
        new ByteString
      • copyFrom

        public static ByteString copyFrom​(ByteBuffer bytes,
                                          int size)
        Copies the next size bytes from a java.nio.ByteBuffer into a ByteString.
        Parameters:
        bytes - source buffer
        size - number of bytes to copy
        Returns:
        new ByteString
        Throws:
        IndexOutOfBoundsException - if size > bytes.remaining()
      • copyFrom

        public static ByteString copyFrom​(ByteBuffer bytes)
        Copies the remaining bytes from a java.nio.ByteBuffer into a ByteString.
        Parameters:
        bytes - sourceBuffer
        Returns:
        new ByteString
      • copyFromUtf8

        public static ByteString copyFromUtf8​(String text)
        Encodes text into a sequence of UTF-8 bytes and returns the result as a ByteString.
        Parameters:
        text - source string
        Returns:
        new ByteString
      • readFrom

        public static ByteString readFrom​(InputStream streamToDrain)
                                   throws IOException
        Completely reads the given stream's bytes into a ByteString, blocking if necessary until all bytes are read through to the end of the stream.

        Performance notes: The returned ByteString is an immutable tree of byte arrays ("chunks") of the stream data. The first chunk is small, with subsequent chunks each being double the size, up to 8K.

        Each byte read from the input stream will be copied twice to ensure that the resulting ByteString is truly immutable.

        Parameters:
        streamToDrain - The source stream, which is read completely but not closed.
        Returns:
        A new ByteString which is made up of chunks of various sizes, depending on the behavior of the underlying stream.
        Throws:
        IOException - if there is a problem reading the underlying stream
        IllegalArgumentException - if the stream supplies more than Integer.MAX_VALUE bytes
      • readFrom

        public static ByteString readFrom​(InputStream streamToDrain,
                                          int chunkSize)
                                   throws IOException
        Completely reads the given stream's bytes into a ByteString, blocking if necessary until all bytes are read through to the end of the stream.

        Performance notes: The returned ByteString is an immutable tree of byte arrays ("chunks") of the stream data. The chunkSize parameter sets the size of these byte arrays.

        Each byte read from the input stream will be copied twice to ensure that the resulting ByteString is truly immutable.

        Parameters:
        streamToDrain - The source stream, which is read completely but not closed.
        chunkSize - The size of the chunks in which to read the stream.
        Returns:
        A new ByteString which is made up of chunks of the given size.
        Throws:
        IOException - if there is a problem reading the underlying stream
        IllegalArgumentException - if the stream supplies more than Integer.MAX_VALUE bytes
      • readFrom

        public static ByteString readFrom​(InputStream streamToDrain,
                                          int minChunkSize,
                                          int maxChunkSize)
                                   throws IOException
        Helper method that takes the chunk size range as a parameter.
        Parameters:
        streamToDrain - the source stream, which is read completely but not closed
        minChunkSize - the minimum size of the chunks in which to read the stream
        maxChunkSize - the maximum size of the chunks in which to read the stream
        Returns:
        a new ByteString which is made up of chunks within the given size range
        Throws:
        IOException - if there is a problem reading the underlying stream
        IllegalArgumentException - if the stream supplies more than Integer.MAX_VALUE bytes
      • concat

        public final ByteString concat​(ByteString other)
        Concatenate the given ByteString to this one. Short concatenations, of total size smaller than CONCATENATE_BY_COPY_SIZE, are produced by copying the underlying bytes (as per Rope.java, BAP95 . In general, the concatenate involves no copying.
        Parameters:
        other - string to concatenate
        Returns:
        a new ByteString instance
        Throws:
        IllegalArgumentException - if the combined size of the two byte strings exceeds Integer.MAX_VALUE
      • copyFrom

        public static ByteString copyFrom​(Iterable<ByteString> byteStrings)
        Concatenates all byte strings in the iterable and returns the result. This is designed to run in O(list size), not O(total bytes).

        The returned ByteString is not necessarily a unique object. If the list is empty, the returned object is the singleton empty ByteString. If the list has only one element, that ByteString will be returned without copying.

        Parameters:
        byteStrings - strings to be concatenated
        Returns:
        new ByteString
        Throws:
        IllegalArgumentException - if the combined size of the byte strings exceeds Integer.MAX_VALUE
      • copyTo

        public void copyTo​(byte[] target,
                           int offset)
        Copies bytes into a buffer at the given offset.

        To copy a subset of bytes, you call this method on the return value of substring(int, int). Example: byteString.substring(start, end).copyTo(target, offset)

        Parameters:
        target - buffer to copy into
        offset - in the target buffer
        Throws:
        IndexOutOfBoundsException - if the offset is negative or too large
      • copyToInternal

        protected abstract void copyToInternal​(byte[] target,
                                               int sourceOffset,
                                               int targetOffset,
                                               int numberToCopy)
        Internal (package private) implementation of copyTo(byte[],int,int,int). It assumes that all error checking has already been performed and that numberToCopy > 0.
      • copyTo

        public abstract void copyTo​(ByteBuffer target)
        Copies bytes into a ByteBuffer.

        To copy a subset of bytes, you call this method on the return value of substring(int, int). Example: byteString.substringNoCopy(start, end).copyTo(target)

        Parameters:
        target - ByteBuffer to copy into.
        Throws:
        ReadOnlyBufferException - if the target is read-only
        BufferOverflowException - if the target's remaining() space is not large enough to hold the data.
      • toByteArray

        public final byte[] toByteArray()
        Copies bytes to a byte[].
        Returns:
        copied bytes
      • writeTo

        public abstract void writeTo​(OutputStream out)
                              throws IOException
        Writes a copy of the contents of this byte string to the specified output stream argument.
        Parameters:
        out - the output stream to which to write the data.
        Throws:
        IOException - if an I/O error occurs.
      • asReadOnlyByteBuffer

        public abstract ByteBuffer asReadOnlyByteBuffer()
        Constructs a read-only java.nio.ByteBuffer whose content is equal to the contents of this byte string. The result uses the same backing array as the byte string, if possible.
        Returns:
        wrapped bytes
      • asReadOnlyByteBufferList

        public abstract List<ByteBuffer> asReadOnlyByteBufferList()
        Constructs a list of read-only java.nio.ByteBuffer objects such that the concatenation of their contents is equal to the contents of this byte string. The result uses the same backing arrays as the byte string.

        By returning a list, implementations of this method may be able to avoid copying even when there are multiple backing arrays.

        Returns:
        a list of wrapped bytes
      • toStringInternal

        protected abstract String toStringInternal​(String charsetName)
                                            throws UnsupportedEncodingException
        Constructs a new String by decoding the bytes using the specified charset name.
        Parameters:
        charsetName - charset name to use for decoding
        Returns:
        new string
        Throws:
        UnsupportedEncodingException - if the charset is not supported
      • toStringUtf8

        public final String toStringUtf8()
        Constructs a new String by decoding the bytes as UTF-8.
        Returns:
        new string using UTF-8 encoding
      • isValidUtf8

        public abstract boolean isValidUtf8()
        Tells whether this ByteString represents a well-formed UTF-8 byte sequence, such that the original bytes can be converted to a String object and then round tripped back to bytes without loss.

        More precisely, returns true whenever:

        
         Arrays.equals(byteString.toByteArray(), new String(byteString.toByteArray(), UTF_8).getBytes(UTF_8))
         

        This method returns false for "overlong" byte sequences, as well as for 3-byte sequences that would map to a surrogate character, in accordance with the restricted definition of UTF-8 introduced in Unicode 3.1. Note that the UTF-8 decoder included in Oracle's JDK has been modified to also reject "overlong" byte sequences, but (as of 2011) still accepts 3-byte surrogate character byte sequences.

        See the Unicode Standard, Table 3-6 UTF-8 Bit Distribution, and Table 3-7 Well Formed UTF-8 Byte Sequences.

        Returns:
        whether the bytes in this ByteString are a well-formed UTF-8 byte sequence
      • equals

        public final boolean equals​(Object o)
        Description copied from class: Object
        Indicates whether some other object is "equal to" this one.

        The equals method implements an equivalence relation on non-null object references:

        • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
        • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
        • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
        • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
        • For any non-null reference value x, x.equals(null) should return false.

        The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

        Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

        Overrides:
        equals in class Object
        Parameters:
        o - the reference object with which to compare.
        Returns:
        true if this object is the same as the obj argument; false otherwise.
        See Also:
        Object.hashCode(), HashMap
      • equalsInternal

        protected abstract boolean equalsInternal​(ByteString other)
        Internal portion of the equals check: as a precondition the caller has already checked most fast properties that are common (including reference identity, null, size, cached hash codes if available) are the same. This method is when we need to check the actual string contents from there.
      • getTreeDepth

        protected abstract int getTreeDepth()
        Return the depth of the tree representing this ByteString, if any, whose root is this node. If this is a leaf node, return 0.
        Returns:
        tree depth or zero
      • isBalanced

        protected abstract boolean isBalanced()
        Return true if this ByteString is literal (a leaf node) or a flat-enough tree in the sense of RopeByteString.
        Returns:
        true if the tree is flat enough
      • peekCachedHashCode

        protected final int peekCachedHashCode()
        Return the cached hash code if available.
        Returns:
        value of cached hash code or 0 if not computed yet
      • partialHash

        protected abstract int partialHash​(int h,
                                           int offset,
                                           int length)
        Compute the hash across the value bytes starting with the given hash, and return the result. This is used to compute the hash across strings represented as a set of pieces by allowing the hash computation to be continued from piece to piece.
        Parameters:
        h - starting hash value
        offset - offset into this value to start looking at data values
        length - number of data values to include in the hash computation
        Returns:
        ending hash value
      • toString

        public final String toString()
        Description copied from class: Object
        Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

        The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

         getClass().getName() + '@' + Integer.toHexString(hashCode())
         
        Overrides:
        toString in class Object
        Returns:
        a string representation of the object.