001package org.xbib.elasticsearch.common.bytes;
002
003import org.apache.lucene.util.BytesRef;
004import org.elasticsearch.common.io.stream.StreamInput;
005import org.jboss.netty.buffer.ChannelBuffer;
006
007import java.io.IOException;
008import java.io.OutputStream;
009import java.nio.channels.GatheringByteChannel;
010
011/**
012 * A reference to bytes for our Netty.
013 */
014public interface BytesReference {
015
016    public static class Helper {
017
018        public static boolean bytesEqual(BytesReference a, BytesReference b) {
019            if (a == b) {
020                return true;
021            }
022            if (a.length() != b.length()) {
023                return false;
024            }
025
026            return bytesEquals(a, b);
027        }
028
029        // pkg-private for testing
030        static boolean bytesEquals(BytesReference a, BytesReference b) {
031            assert a.length() == b.length();
032            for (int i = 0, end = a.length(); i < end; ++i) {
033                if (a.get(i) != b.get(i)) {
034                    return false;
035                }
036            }
037
038            return true;
039        }
040
041        // pkg-private for testing
042        static boolean slowBytesEquals(BytesReference a, BytesReference b) {
043            assert a.length() == b.length();
044            for (int i = 0, end = a.length(); i < end; ++i) {
045                if (a.get(i) != b.get(i)) {
046                    return false;
047                }
048            }
049
050            return true;
051        }
052
053        public static int bytesHashCode(BytesReference a) {
054            if (a.hasArray()) {
055                return hashCode(a.array(), a.arrayOffset(), a.length());
056            } else {
057                return slowHashCode(a);
058            }
059        }
060
061        // pkg-private for testing
062        static int hashCode(byte[] array, int offset, int length) {
063            int result = 1;
064            for (int i = offset, end = offset + length; i < end; ++i) {
065                result = 31 * result + array[i];
066            }
067            return result;
068        }
069
070        // pkg-private for testing
071        static int slowHashCode(BytesReference a) {
072            int result = 1;
073            for (int i = 0, end = a.length(); i < end; ++i) {
074                result = 31 * result + a.get(i);
075            }
076            return result;
077        }
078    }
079
080    /**
081     * Returns the byte at the specified index. Need to be between 0 and length.
082     */
083    byte get(int index);
084
085    /**
086     * The length.
087     */
088    int length();
089
090    /**
091     * Slice the bytes from the <tt>from</tt> index up to <tt>length</tt>.
092     */
093    BytesReference slice(int from, int length);
094
095    /**
096     * A stream input of the bytes.
097     */
098    StreamInput streamInput();
099
100    /**
101     * Writes the bytes directly to the output stream.
102     */
103    void writeTo(OutputStream os) throws IOException;
104
105    /**
106     * Writes the bytes directly to the channel.
107     */
108    void writeTo(GatheringByteChannel channel) throws IOException;
109
110    /**
111     * Returns the bytes as a single byte array.
112     */
113    byte[] toBytes();
114
115    /**
116     * Returns the bytes as a byte array, possibly sharing the underlying byte buffer.
117     */
118    BytesArray toBytesArray();
119
120    /**
121     * Returns the bytes copied over as a byte array.
122     */
123    BytesArray copyBytesArray();
124
125    /**
126     * Returns the bytes as a channel buffer.
127     */
128    ChannelBuffer toChannelBuffer();
129
130    /**
131     * Is there an underlying byte array for this bytes reference.
132     */
133    boolean hasArray();
134
135    /**
136     * The underlying byte array (if exists).
137     */
138    byte[] array();
139
140    /**
141     * The offset into the underlying byte array.
142     */
143    int arrayOffset();
144
145    /**
146     * Converts to a string based on utf8.
147     */
148    String toUtf8();
149
150    /**
151     * Converts to Lucene BytesRef.
152     */
153    BytesRef toBytesRef();
154
155    /**
156     * Converts to a copied Lucene BytesRef.
157     */
158    BytesRef copyBytesRef();
159}