31 package com.google.protobuf;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InvalidObjectException;
38 import java.io.ObjectInputStream;
39 import java.io.OutputStream;
40 import java.nio.ByteBuffer;
41 import java.nio.ByteOrder;
42 import java.nio.InvalidMarkException;
43 import java.nio.charset.Charset;
44 import java.util.Collections;
45 import java.util.List;
48 final class NioByteString
extends ByteString.LeafByteString {
49 private final ByteBuffer
buffer;
51 NioByteString(ByteBuffer
buffer) {
52 checkNotNull(
buffer,
"buffer");
55 this.buffer =
buffer.slice().order(ByteOrder.nativeOrder());
62 private Object writeReplace() {
63 return ByteString.copyFrom(
buffer.slice());
67 private void readObject(@SuppressWarnings(
"unused") ObjectInputStream in)
throws IOException {
68 throw new InvalidObjectException(
"NioByteString instances are not to be serialized directly");
74 public byte byteAt(
int index) {
77 }
catch (ArrayIndexOutOfBoundsException e) {
79 }
catch (IndexOutOfBoundsException e) {
80 throw new ArrayIndexOutOfBoundsException(e.getMessage());
85 public byte internalByteAt(
int index) {
97 public ByteString substring(
int beginIndex,
int endIndex) {
99 ByteBuffer slice = slice(beginIndex, endIndex);
100 return new NioByteString(slice);
101 }
catch (ArrayIndexOutOfBoundsException e) {
103 }
catch (IndexOutOfBoundsException e) {
104 throw new ArrayIndexOutOfBoundsException(e.getMessage());
109 protected void copyToInternal(
110 byte[]
target,
int sourceOffset,
int targetOffset,
int numberToCopy) {
111 ByteBuffer slice =
buffer.slice();
112 slice.position(sourceOffset);
113 slice.get(
target, targetOffset, numberToCopy);
117 public void copyTo(ByteBuffer
target) {
122 public void writeTo(OutputStream out)
throws IOException {
123 out.write(toByteArray());
127 boolean equalsRange(ByteString other,
int offset,
int length) {
132 void writeToInternal(OutputStream out,
int sourceOffset,
int numberToWrite)
throws IOException {
136 int bufferOffset =
buffer.arrayOffset() +
buffer.position() + sourceOffset;
137 out.write(
buffer.array(), bufferOffset, numberToWrite);
141 ByteBufferWriter.write(slice(sourceOffset, sourceOffset + numberToWrite), out);
145 void writeTo(ByteOutput
output)
throws IOException {
150 public ByteBuffer asReadOnlyByteBuffer() {
151 return buffer.asReadOnlyBuffer();
155 public List<ByteBuffer> asReadOnlyByteBufferList() {
156 return Collections.singletonList(asReadOnlyByteBuffer());
160 protected String toStringInternal(Charset charset) {
170 bytes = toByteArray();
178 public boolean isValidUtf8() {
179 return Utf8.isValidUtf8(
buffer);
183 protected int partialIsValidUtf8(
int state,
int offset,
int length) {
188 public boolean equals(Object other) {
192 if (!(other instanceof ByteString)) {
195 ByteString otherString = ((ByteString) other);
196 if (
size() != otherString.size()) {
202 if (other instanceof NioByteString) {
205 if (other instanceof RopeByteString) {
206 return other.equals(
this);
208 return buffer.equals(otherString.asReadOnlyByteBuffer());
220 public InputStream newInput() {
221 return new InputStream() {
222 private final ByteBuffer
buf =
buffer.slice();
225 public void mark(
int readlimit) {
230 public boolean markSupported() {
235 public void reset() throws IOException {
238 }
catch (InvalidMarkException e) {
239 throw new IOException(e);
244 public int available() throws IOException {
245 return buf.remaining();
249 public int read() throws IOException {
250 if (!
buf.hasRemaining()) {
253 return buf.get() & 0xFF;
257 public int read(
byte[]
bytes,
int off,
int len)
throws IOException {
258 if (!
buf.hasRemaining()) {
270 public CodedInputStream newCodedInput() {
271 return CodedInputStream.newInstance(
buffer,
true);
281 private ByteBuffer slice(
int beginIndex,
int endIndex) {
282 if (beginIndex <
buffer.position() || endIndex >
buffer.limit() || beginIndex > endIndex) {
283 throw new IllegalArgumentException(
284 String.format(
"Invalid indices [%d, %d]", beginIndex, endIndex));
287 ByteBuffer slice =
buffer.slice();
288 slice.position(beginIndex -
buffer.position());
289 slice.limit(endIndex -
buffer.position());