• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import static com.google.protobuf.Internal.checkNotNull;
34 
35 import java.nio.ByteBuffer;
36 
37 /**
38  * A buffer that was allocated by a {@link BufferAllocator}. For every buffer, it is guaranteed that
39  * at least one of {@link #hasArray()} or {@link #hasNioBuffer()} will be {@code true}.
40  */
41 @ExperimentalApi
42 abstract class AllocatedBuffer {
43   /**
44    * Indicates whether this buffer contains a backing {@link ByteBuffer} (i.e. it is safe to call
45    * {@link #nioBuffer()}).
46    */
hasNioBuffer()47   public abstract boolean hasNioBuffer();
48 
49   /**
50    * Indicates whether this buffer contains a backing array (i.e. it is safe to call {@link
51    * #array()}).
52    */
hasArray()53   public abstract boolean hasArray();
54 
55   /**
56    * Returns the {@link ByteBuffer} that backs this buffer <i>(optional operation)</i>.
57    *
58    * <p>Call {@link #hasNioBuffer()} before invoking this method in order to ensure that this buffer
59    * has a backing {@link ByteBuffer}.
60    *
61    * @return The {@link ByteBuffer} that backs this buffer
62    * @throws UnsupportedOperationException If this buffer is not backed by a {@link ByteBuffer}.
63    */
nioBuffer()64   public abstract ByteBuffer nioBuffer();
65 
66   /**
67    * Returns the byte array that backs this buffer <i>(optional operation)</i>.
68    *
69    * <p>Call {@link #hasArray()} before invoking this method in order to ensure that this buffer has
70    * an accessible backing array.
71    *
72    * @return The array that backs this buffer
73    * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only
74    * @throws UnsupportedOperationException If this buffer is not backed by an accessible array
75    */
array()76   public abstract byte[] array();
77 
78   /**
79    * Returns the offset within this buffer's backing array of the first element of the buffer
80    * <i>(optional operation)</i>.
81    *
82    * <p>If this buffer is backed by an array then {@link #position()} corresponds to the array index
83    * {@link #position()} {@code +} {@link #arrayOffset()}.
84    *
85    * <p>Invoke the {@link #hasArray hasArray} method before invoking this method in order to ensure
86    * that this buffer has an accessible backing array.
87    *
88    * @return The offset within this buffer's array of the first element of the buffer
89    * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only
90    * @throws UnsupportedOperationException If this buffer is not backed by an accessible array
91    */
arrayOffset()92   public abstract int arrayOffset();
93 
94   /**
95    * Returns this buffer's position.
96    *
97    * @return The position of this buffer
98    */
position()99   public abstract int position();
100 
101   /**
102    * Sets this buffer's position.
103    *
104    * @param position The new position value; must be non-negative and no larger than the current
105    *     limit
106    * @return This buffer
107    * @throws IllegalArgumentException If the preconditions on {@code position} do not hold
108    */
position(int position)109   public abstract AllocatedBuffer position(int position);
110 
111   /**
112    * Returns this buffer's limit.
113    *
114    * @return The limit of this buffer
115    */
limit()116   public abstract int limit();
117 
118   /**
119    * Returns the number of elements between the current {@link #position()} and the {@link #limit()}
120    * .
121    *
122    * @return The number of elements remaining in this buffer
123    */
remaining()124   public abstract int remaining();
125 
126   /**
127    * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer
128    * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code 0}, {@link
129    * #position()} == {@code 0} and {@link #limit()} equal to the length of {@code bytes}.
130    */
wrap(byte[] bytes)131   public static AllocatedBuffer wrap(byte[] bytes) {
132     return wrapNoCheck(bytes, 0, bytes.length);
133   }
134 
135   /**
136    * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer
137    * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code offset}, {@link
138    * #position()} == {@code 0} and {@link #limit()} == {@code length}.
139    */
wrap(final byte[] bytes, final int offset, final int length)140   public static AllocatedBuffer wrap(final byte[] bytes, final int offset, final int length) {
141     if (offset < 0 || length < 0 || (offset + length) > bytes.length) {
142       throw new IndexOutOfBoundsException(
143           String.format("bytes.length=%d, offset=%d, length=%d", bytes.length, offset, length));
144     }
145 
146     return wrapNoCheck(bytes, offset, length);
147   }
148 
149   /**
150    * Creates a new {@link AllocatedBuffer} that is backed by the given {@link ByteBuffer}. The
151    * returned buffer will have {@link #hasNioBuffer} == {@code true}.
152    */
wrap(final ByteBuffer buffer)153   public static AllocatedBuffer wrap(final ByteBuffer buffer) {
154     checkNotNull(buffer, "buffer");
155 
156     return new AllocatedBuffer() {
157 
158       @Override
159       public boolean hasNioBuffer() {
160         return true;
161       }
162 
163       @Override
164       public ByteBuffer nioBuffer() {
165         return buffer;
166       }
167 
168       @Override
169       public boolean hasArray() {
170         return buffer.hasArray();
171       }
172 
173       @Override
174       public byte[] array() {
175         return buffer.array();
176       }
177 
178       @Override
179       public int arrayOffset() {
180         return buffer.arrayOffset();
181       }
182 
183       @Override
184       public int position() {
185         return buffer.position();
186       }
187 
188       @Override
189       public AllocatedBuffer position(int position) {
190         buffer.position(position);
191         return this;
192       }
193 
194       @Override
195       public int limit() {
196         return buffer.limit();
197       }
198 
199       @Override
200       public int remaining() {
201         return buffer.remaining();
202       }
203     };
204   }
205 
206   private static AllocatedBuffer wrapNoCheck(
207       final byte[] bytes, final int offset, final int length) {
208     return new AllocatedBuffer() {
209       // Relative to offset.
210       private int position;
211 
212       @Override
213       public boolean hasNioBuffer() {
214         return false;
215       }
216 
217       @Override
218       public ByteBuffer nioBuffer() {
219         throw new UnsupportedOperationException();
220       }
221 
222       @Override
223       public boolean hasArray() {
224         return true;
225       }
226 
227       @Override
228       public byte[] array() {
229         return bytes;
230       }
231 
232       @Override
233       public int arrayOffset() {
234         return offset;
235       }
236 
237       @Override
238       public int position() {
239         return position;
240       }
241 
242       @Override
243       public AllocatedBuffer position(int position) {
244         if (position < 0 || position > length) {
245           throw new IllegalArgumentException("Invalid position: " + position);
246         }
247         this.position = position;
248         return this;
249       }
250 
251       @Override
252       public int limit() {
253         // Relative to offset.
254         return length;
255       }
256 
257       @Override
258       public int remaining() {
259         return length - position;
260       }
261     };
262   }
263 }
264