diff options
Diffstat (limited to 'java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java')
-rw-r--r-- | java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java new file mode 100644 index 00000000..4c822348 --- /dev/null +++ b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java @@ -0,0 +1,263 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.google.protobuf; + +import static com.google.protobuf.Internal.checkNotNull; + +import java.nio.ByteBuffer; + +/** + * A buffer that was allocated by a {@link BufferAllocator}. For every buffer, it is guaranteed that + * at least one of {@link #hasArray()} or {@link #hasNioBuffer()} will be {@code true}. + */ +@ExperimentalApi +public abstract class AllocatedBuffer { + /** + * Indicates whether this buffer contains a backing {@link ByteBuffer} (i.e. it is safe to call + * {@link #nioBuffer()}). + */ + public abstract boolean hasNioBuffer(); + + /** + * Indicates whether this buffer contains a backing array (i.e. it is safe to call {@link + * #array()}). + */ + public abstract boolean hasArray(); + + /** + * Returns the {@link ByteBuffer} that backs this buffer <i>(optional operation)</i>. + * + * <p>Call {@link #hasNioBuffer()} before invoking this method in order to ensure that this buffer + * has a backing {@link ByteBuffer}. + * + * @return The {@link ByteBuffer} that backs this buffer + * @throws UnsupportedOperationException If this buffer is not backed by a {@link ByteBuffer}. + */ + public abstract ByteBuffer nioBuffer(); + + /** + * Returns the byte array that backs this buffer <i>(optional operation)</i>. + * + * <p>Call {@link #hasArray()} before invoking this method in order to ensure that this buffer has + * an accessible backing array. + * + * @return The array that backs this buffer + * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only + * @throws UnsupportedOperationException If this buffer is not backed by an accessible array + */ + public abstract byte[] array(); + + /** + * Returns the offset within this buffer's backing array of the first element of the buffer + * <i>(optional operation)</i>. + * + * <p>If this buffer is backed by an array then {@link #position()} corresponds to the array index + * {@link #position()} {@code +} {@link #arrayOffset()}. + * + * <p>Invoke the {@link #hasArray hasArray} method before invoking this method in order to ensure + * that this buffer has an accessible backing array. + * + * @return The offset within this buffer's array of the first element of the buffer + * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only + * @throws UnsupportedOperationException If this buffer is not backed by an accessible array + */ + public abstract int arrayOffset(); + + /** + * Returns this buffer's position. + * + * @return The position of this buffer + */ + public abstract int position(); + + /** + * Sets this buffer's position. + * + * @param position The new position value; must be non-negative and no larger than the current + * limit + * @return This buffer + * @throws IllegalArgumentException If the preconditions on {@code position} do not hold + */ + public abstract AllocatedBuffer position(int position); + + /** + * Returns this buffer's limit. + * + * @return The limit of this buffer + */ + public abstract int limit(); + + /** + * Returns the number of elements between the current {@link #position()} and the {@link #limit()} + * . + * + * @return The number of elements remaining in this buffer + */ + public abstract int remaining(); + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer + * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code 0}, {@link + * #position()} == {@code 0} and {@link #limit()} equal to the length of {@code bytes}. + */ + public static AllocatedBuffer wrap(byte[] bytes) { + return wrapNoCheck(bytes, 0, bytes.length); + } + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer + * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code offset}, {@link + * #position()} == {@code 0} and {@link #limit()} == {@code length}. + */ + public static AllocatedBuffer wrap(final byte[] bytes, final int offset, final int length) { + if (offset < 0 || length < 0 || (offset + length) > bytes.length) { + throw new IndexOutOfBoundsException( + String.format("bytes.length=%d, offset=%d, lenght=%d", bytes.length, offset, length)); + } + + return wrapNoCheck(bytes, offset, length); + } + + /** + * Creates a new {@link AllocatedBuffer} that is backed by the given {@link ByteBuffer}. The + * returned buffer will have {@link #hasNioBuffer} == {@code true}. + */ + public static AllocatedBuffer wrap(final ByteBuffer buffer) { + checkNotNull(buffer, "buffer"); + + return new AllocatedBuffer() { + + @Override + public boolean hasNioBuffer() { + return true; + } + + @Override + public ByteBuffer nioBuffer() { + return buffer; + } + + @Override + public boolean hasArray() { + return buffer.hasArray(); + } + + @Override + public byte[] array() { + return buffer.array(); + } + + @Override + public int arrayOffset() { + return buffer.arrayOffset(); + } + + @Override + public int position() { + return buffer.position(); + } + + @Override + public AllocatedBuffer position(int position) { + buffer.position(position); + return this; + } + + @Override + public int limit() { + return buffer.limit(); + } + + @Override + public int remaining() { + return buffer.remaining(); + } + }; + } + + private static AllocatedBuffer wrapNoCheck( + final byte[] bytes, final int offset, final int length) { + return new AllocatedBuffer() { + // Relative to offset. + private int position; + + @Override + public boolean hasNioBuffer() { + return false; + } + + @Override + public ByteBuffer nioBuffer() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasArray() { + return true; + } + + @Override + public byte[] array() { + return bytes; + } + + @Override + public int arrayOffset() { + return offset; + } + + @Override + public int position() { + return position; + } + + @Override + public AllocatedBuffer position(int position) { + if (position < 0 || position > length) { + throw new IllegalArgumentException("Invalid position: " + position); + } + this.position = position; + return this; + } + + @Override + public int limit() { + // Relative to offset. + return length; + } + + @Override + public int remaining() { + return length - position; + } + }; + } +} |