001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems, Inc.
015 * Portions copyright 2011-2015 ForgeRock AS.
016 */
017package org.forgerock.opendj.ldap;
018
019import java.io.IOException;
020import java.io.OutputStream;
021import java.nio.BufferOverflowException;
022import java.nio.ByteBuffer;
023import java.nio.CharBuffer;
024import java.nio.charset.CharsetDecoder;
025import java.util.Comparator;
026
027/**
028 * A {@code ByteSequence} is a readable sequence of byte values. This interface
029 * provides uniform, read-only access to many different kinds of byte sequences.
030 */
031public interface ByteSequence extends Comparable<ByteSequence> {
032
033    /** A byte array comparator. */
034    Comparator<byte[]> BYTE_ARRAY_COMPARATOR = new Comparator<byte[]>() {
035        @Override
036        public int compare(final byte[] b1, final byte[] b2) {
037            return ByteString.compareTo(b1, 0, b1.length, b2, 0, b2.length);
038        }
039    };
040
041    /** A ByteSequence comparator. */
042    Comparator<ByteSequence> COMPARATOR = new Comparator<ByteSequence>() {
043        @Override
044        public int compare(final ByteSequence o1, final ByteSequence o2) {
045            return o1.compareTo(o2);
046        }
047    };
048
049    /**
050     * Returns a {@link ByteSequenceReader} which can be used to incrementally
051     * read and decode data from this byte sequence.
052     * <p>
053     * <b>NOTE:</b> any concurrent changes to the underlying byte sequence (if
054     * mutable) may cause subsequent reads to overrun and fail.
055     *
056     * @return The {@link ByteSequenceReader} which can be used to incrementally
057     *         read and decode data from this byte sequence.
058     */
059    ByteSequenceReader asReader();
060
061    /**
062     * Returns the byte value at the specified index.
063     * <p>
064     * An index ranges from zero to {@code length() - 1}. The first byte value
065     * of the sequence is at index zero, the next at index one, and so on, as
066     * for array indexing.
067     *
068     * @param index
069     *            The index of the byte to be returned.
070     * @return The byte value at the specified index.
071     * @throws IndexOutOfBoundsException
072     *             If the index argument is negative or not less than length().
073     */
074    byte byteAt(int index);
075
076    /**
077     * Compares this byte sequence with the specified byte array sub-sequence
078     * for order. Returns a negative integer, zero, or a positive integer
079     * depending on whether this byte sequence is less than, equal to, or
080     * greater than the specified byte array sub-sequence.
081     *
082     * @param bytes
083     *            The byte array to compare.
084     * @param offset
085     *            The offset of the sub-sequence in the byte array to be
086     *            compared; must be non-negative and no larger than
087     *            {@code bytes.length} .
088     * @param length
089     *            The length of the sub-sequence in the byte array to be
090     *            compared; must be non-negative and no larger than
091     *            {@code bytes.length - offset}.
092     * @return A negative integer, zero, or a positive integer depending on
093     *         whether this byte sequence is less than, equal to, or greater
094     *         than the specified byte array sub-sequence.
095     * @throws IndexOutOfBoundsException
096     *             If {@code offset} is negative or if {@code length} is
097     *             negative or if {@code offset + length} is greater than
098     *             {@code bytes.length}.
099     */
100    int compareTo(byte[] bytes, int offset, int length);
101
102    /**
103     * Compares this byte sequence with the specified byte sequence for order.
104     * Returns a negative integer, zero, or a positive integer depending on
105     * whether this byte sequence is less than, equal to, or greater than the
106     * specified object.
107     *
108     * @param o
109     *            The byte sequence to be compared.
110     * @return A negative integer, zero, or a positive integer depending on
111     *         whether this byte sequence is less than, equal to, or greater
112     *         than the specified object.
113     */
114    @Override
115    int compareTo(ByteSequence o);
116
117    /**
118     * Copies the contents of this byte sequence to the provided byte array.
119     * <p>
120     * Copying will stop when either the entire content of this sequence has
121     * been copied or if the end of the provided byte array has been reached.
122     * <p>
123     * An invocation of the form:
124     *
125     * <pre>
126     * src.copyTo(bytes)
127     * </pre>
128     *
129     * Behaves in exactly the same way as the invocation:
130     *
131     * <pre>
132     * src.copyTo(bytes, 0);
133     * </pre>
134     *
135     * @param bytes
136     *            The byte array to which bytes are to be copied.
137     * @return The byte array.
138     */
139    byte[] copyTo(byte[] bytes);
140
141    /**
142     * Copies the contents of this byte sequence to the specified location in
143     * the provided byte array.
144     * <p>
145     * Copying will stop when either the entire content of this sequence has
146     * been copied or if the end of the provided byte array has been reached.
147     * <p>
148     * An invocation of the form:
149     *
150     * <pre>
151     * src.copyTo(bytes, offset)
152     * </pre>
153     *
154     * Behaves in exactly the same way as the invocation:
155     *
156     * <pre>
157     * int len = Math.min(src.length(), bytes.length - offset);
158     * for (int i = 0; i &lt; len; i++)
159     *     bytes[offset + i] = src.get(i);
160     * </pre>
161     *
162     * Except that it is potentially much more efficient.
163     *
164     * @param bytes
165     *            The byte array to which bytes are to be copied.
166     * @param offset
167     *            The offset within the array of the first byte to be written;
168     *            must be non-negative and no larger than bytes.length.
169     * @return The byte array.
170     * @throws IndexOutOfBoundsException
171     *             If {@code offset} is negative.
172     */
173    byte[] copyTo(byte[] bytes, int offset);
174
175    /**
176     * Appends the entire contents of this byte sequence to the provided
177     * {@link ByteStringBuilder}.
178     *
179     * @param builder
180     *            The builder to copy to.
181     * @return The builder.
182     */
183    ByteStringBuilder copyTo(ByteStringBuilder builder);
184
185    /**
186     * Appends the content of this byte sequence to the provided {@link ByteBuffer} starting at it's current position.
187     * The position of the buffer is then incremented by the length of this sequence.
188     *
189     * @param buffer
190     *            The buffer to copy to.
191     *            It must be large enough to receive all bytes.
192     * @return The buffer.
193     * @throws BufferOverflowException
194     *            If there is insufficient space in the provided buffer
195     */
196    ByteBuffer copyTo(ByteBuffer buffer);
197
198    /**
199     * Appends the content of this byte sequence decoded using provided charset decoder to the provided
200     * {@link CharBuffer} starting at it's current position. The position of charBuffer is then incremented by the
201     * length of this sequence.
202     *
203     * @param charBuffer
204     *            The buffer to copy to, if decoding is successful.
205     *            It must be large enough to receive all decoded characters.
206     * @param decoder
207     *            The charset decoder to use for decoding.
208     * @return {@code true} if byte string was successfully decoded and charBuffer is
209     *         large enough to receive the resulting string, {@code false} otherwise
210     */
211    boolean copyTo(CharBuffer charBuffer, CharsetDecoder decoder);
212
213    /**
214     * Copies the entire contents of this byte sequence to the provided
215     * {@code OutputStream}.
216     *
217     * @param stream
218     *            The {@code OutputStream} to copy to.
219     * @return The {@code OutputStream}.
220     * @throws IOException
221     *             If an error occurs while writing to the {@code OutputStream}.
222     */
223    OutputStream copyTo(OutputStream stream) throws IOException;
224
225    /**
226     * Indicates whether the provided byte array sub-sequence is equal to this
227     * byte sequence. In order for it to be considered equal, the provided byte
228     * array sub-sequence must contain the same bytes in the same order.
229     *
230     * @param bytes
231     *            The byte array for which to make the determination.
232     * @param offset
233     *            The offset of the sub-sequence in the byte array to be
234     *            compared; must be non-negative and no larger than
235     *            {@code bytes.length} .
236     * @param length
237     *            The length of the sub-sequence in the byte array to be
238     *            compared; must be non-negative and no larger than
239     *            {@code bytes.length - offset}.
240     * @return {@code true} if the content of the provided byte array
241     *         sub-sequence is equal to that of this byte sequence, or
242     *         {@code false} if not.
243     * @throws IndexOutOfBoundsException
244     *             If {@code offset} is negative or if {@code length} is
245     *             negative or if {@code offset + length} is greater than
246     *             {@code bytes.length}.
247     */
248    boolean equals(byte[] bytes, int offset, int length);
249
250    /**
251     * Indicates whether the provided object is equal to this byte sequence. In
252     * order for it to be considered equal, the provided object must be a byte
253     * sequence containing the same bytes in the same order.
254     *
255     * @param o
256     *            The object for which to make the determination.
257     * @return {@code true} if the provided object is a byte sequence whose
258     *         content is equal to that of this byte sequence, or {@code false}
259     *         if not.
260     */
261    @Override
262    boolean equals(Object o);
263
264    /**
265     * Returns a hash code for this byte sequence. It will be the sum of all of
266     * the bytes contained in the byte sequence.
267     *
268     * @return A hash code for this byte sequence.
269     */
270    @Override
271    int hashCode();
272
273    /**
274     * Returns {@code true} if this byte sequence has a length of zero.
275     *
276     * @return {@code true} if this byte sequence has a length of zero.
277     */
278    boolean isEmpty();
279
280    /**
281     * Returns the length of this byte sequence.
282     *
283     * @return The length of this byte sequence.
284     */
285    int length();
286
287    /**
288     * Returns a new byte sequence that is a subsequence of this byte sequence.
289     * <p>
290     * The subsequence starts with the byte value at the specified {@code start}
291     * index and ends with the byte value at index {@code end - 1}. The length
292     * (in bytes) of the returned sequence is {@code end - start}, so if
293     * {@code start
294     * == end} then an empty sequence is returned.
295     * <p>
296     * <b>NOTE:</b> changes to the underlying byte sequence (if mutable) may
297     * render the returned sub-sequence invalid.
298     *
299     * @param start
300     *            The start index, inclusive.
301     * @param end
302     *            The end index, exclusive.
303     * @return The newly created byte subsequence.
304     * @throws IndexOutOfBoundsException
305     *             If {@code start} or {@code end} are negative, if {@code end}
306     *             is greater than {@code length()}, or if {@code start} is
307     *             greater than {@code end}.
308     */
309    ByteSequence subSequence(int start, int end);
310
311    /**
312     * Tests if this ByteSequence starts with the specified prefix.
313     *
314     * @param prefix
315     *            The prefix.
316     * @return true if the byte sequence represented by the argument is a prefix of the byte sequence represented by
317     *         this ByteSequence; false otherwise. Note also that true will be returned if the argument is an empty
318     *         sequence or is equal to this ByteSequence object as determined by the equals(Object) method.
319     */
320    boolean startsWith(ByteSequence prefix);
321
322    /**
323     * Returns the Base64 encoded string representation of this byte string.
324     *
325     * @return The Base64 encoded string representation of this byte string.
326     * @see ByteString#valueOfBase64(String)
327     */
328    String toBase64String();
329
330    /**
331     * Returns a byte array containing the bytes in this sequence in the same
332     * order as this sequence. The length of the byte array will be the length
333     * of this sequence.
334     * <p>
335     * An invocation of the form:
336     *
337     * <pre>
338     * src.toByteArray()
339     * </pre>
340     *
341     * Behaves in exactly the same way as the invocation:
342     *
343     * <pre>
344     * src.copyTo(new byte[src.length()]);
345     * </pre>
346     *
347     * @return A byte array consisting of exactly this sequence of bytes.
348     */
349    byte[] toByteArray();
350
351    /**
352     * Returns the {@link ByteString} representation of this byte sequence.
353     *
354     * @return The {@link ByteString} representation of this byte sequence.
355     */
356    ByteString toByteString();
357
358    /**
359     * Returns the UTF-8 decoded string representation of this byte sequence. If
360     * UTF-8 decoding fails, the platform's default encoding will be used.
361     *
362     * @return The string representation of this byte sequence.
363     */
364    @Override
365    String toString();
366}