View Javadoc
1   /*
2    * Copyright 2021 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.buffer.api;
17  
18  import io.netty5.util.Resource;
19  import io.netty5.util.Send;
20  
21  import java.nio.ByteBuffer;
22  import java.nio.charset.Charset;
23  
24  /**
25   * The {@code CompositeBuffer} is a concrete {@link Buffer} implementation that make a number of other buffers appear
26   * as one. A composite buffer behaves the same as a normal, non-composite buffer in every way, so you normally don't
27   * need to handle them specially.
28   * <p>
29   * A composite buffer is constructed using one of the {@code compose} methods:
30   * <ul>
31   *     <li>
32   *         {@link BufferAllocator#compose(Iterable)} creates a composite buffer from the buffers that are sent to it via
33   *         the passed in send objects. Since {@link Send#receive()} transfers ownership, the resulting composite buffer
34   *         will have ownership, because it is guaranteed that there are no other references to its constituent buffers.
35   *     </li>
36   *     <li>
37   *         {@link BufferAllocator#compose(Send)} creates a composite buffer with a single component.
38   *         Since {@link Send#receive()} transfers ownership, the resulting composite buffer
39   *         will have ownership, because it is guaranteed that there are no other references to its constituent buffer.
40   *     </li>
41   *     <li>
42   *         {@link BufferAllocator#compose()} creates an empty, zero capacity, composite buffer. Such empty buffers may
43   *         change their {@linkplain #readOnly() read-only} states when they gain their first component.
44   *     </li>
45   * </ul>
46   * Composite buffers can later be extended with internally allocated components, with {@link #ensureWritable(int)},
47   * or with externally allocated buffers, using {@link #extendWith(Send)}.
48   *
49   * <h3>How buffers compose</h3>
50   *
51   * A buffer can be thought of as having three distinct regions, in order:
52   * <ol>
53   *     <li>Memory that have been read.</li>
54   *     <li>Memory that is readable.</li>
55   *     <li>Memory that can be written to.</li>
56   * </ol>
57   *
58   * A composite buffer must present itself similarly, but may be composed of buffers where their offsets don't line up,
59   * and thus end up producing "gaps" in the composite buffer.
60   * The solution is that the composite buffer hide these gaps from view.
61   * <p>
62   * For example, if we compose two buffers that both have non-zero read-offset, then the composite buffer will get the
63   * read-offset of the first buffer, followed by a concatenation of the readable memory from both.
64   * Similarly, the write-offset of the composite buffer will come from the last buffer with a non-zero write-offset,
65   * and any writable memory prior to the last readable memory region will be hidden:
66   *
67   * <pre>
68   *     First buffer                Second buffer
69   *      +----------------------+    +--------------------+
70   *     0|    |r/o      |w/o    |   0|    |r/o     |w/o   |
71   *      +----+---------+-------+    +----+--------+------+
72   *       \    \         \  ,____________/   ,___________/
73   *        \    \         \/                /
74   *         +----+---------+--------+------+
75   *        0|    |r/o      :        |w/o   |  Composite buffer
76   *         +------------------------------+
77   * </pre>
78   *
79   * Components in the middle can have both their end-regions hidden in the same way, so only their readable memory is
80   * included in the composite buffer.
81   * Buffers that consist entirely of memory that has already been read, or memory that is writable, can also concatenate
82   * onto those regions at the ends.
83   * The final capacity of the composite buffer, will be the sum of all the visible regions.
84   * <p>
85   * Reads and writes to the composite buffer that modifies the read or write offsets, will also modify the relevant
86   * offsets in the constituent buffers.
87   *
88   * <h3>Constituent buffer requirements</h3>
89   *
90   * The buffers that are being composed must all have the same writability.
91   * Either all components must be {@linkplain Buffer#readOnly() read-only}, or they must all be writable.
92   * <p>
93   * It is not a requirement that the buffers have the same size.
94   * <p>
95   * It is not a requirement that the buffers are allocated by this allocator, but if
96   * {@link Buffer#ensureWritable(int)} is called on the composed buffer, and the composed buffer needs to be
97   * expanded, then this allocator instance will be used for allocation the extra memory.
98   *
99   * <h3>Ownership and Send</h3>
100  *
101  * {@linkplain Resource#send() Sending} a composite buffer implies sending all of its constituent buffers.
102  * For sending to be possible, both the composite buffer itself, and all of its constituent buffers, must be in a
103  * state that permits them being sent. This should be the case by default, as it shouldn't be possible to create
104  * composite buffers that can't be sent.
105  */
106 public interface CompositeBuffer extends Buffer {
107 
108     /**
109      * Create an empty composite buffer, that has no components. The buffer can be extended with components using either
110      * {@link #ensureWritable(int)} or {@link #extendWith(Send)}.
111      *
112      * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
113      * {@link #ensureWritable(int)} calls.
114      * @return A composite buffer that has no components, and has a capacity of zero.
115      */
116     static CompositeBuffer compose(BufferAllocator allocator) {
117         return DefaultCompositeBuffer.compose(allocator);
118     }
119 
120     /**
121      * Check if the given buffer is a composite buffer or not.
122      * @param composite The buffer to check.
123      * @return {@code true} if the given buffer was created with {@link BufferAllocator#compose()},
124      * {@link BufferAllocator#compose(Send)} or {@link BufferAllocator#compose(Iterable)}, {@code false} otherwise.
125      */
126     static boolean isComposite(Buffer composite) {
127         return composite instanceof CompositeBuffer;
128     }
129 
130     /**
131      * Extend this composite buffer with the given extension buffer.
132      * This works as if the extension had originally been included at the end of the list of constituent buffers when
133      * the composite buffer was created.
134      * The extension buffer is added to the end of this composite buffer, which is modified in-place.
135      *
136      * @see BufferAllocator#compose(Send)
137      * @param extension The buffer to extend the composite buffer with.
138      * @return This composite buffer instance.
139      */
140     CompositeBuffer extendWith(Send<Buffer> extension);
141 
142     /**
143      * Split this buffer at a component boundary that is less than or equal to the given offset.
144      * <p>
145      * This method behaves the same as {@link #split(int)}, except no components are split.
146      *
147      * @param splitOffset The maximum split offset. The real split offset will be at a component boundary that is less
148      *                   than or equal to this offset.
149      * @return A new buffer with independent and exclusive ownership over the bytes from the beginning to a component
150      * boundary less than or equal to the given offset of this buffer.
151      */
152     CompositeBuffer splitComponentsFloor(int splitOffset);
153 
154     /**
155      * Split this buffer at a component boundary that is greater than or equal to the given offset.
156      * <p>
157      * This method behaves the same as {@link #split(int)}, except no components are split.
158      *
159      * @param splitOffset The minimum split offset. The real split offset will be at a component boundary that is
160      *                   greater than or equal to this offset.
161      * @return A new buffer with independent and exclusive ownership over the bytes from the beginning to a component
162      * boundary greater than or equal to the given offset of this buffer.
163      */
164     CompositeBuffer splitComponentsCeil(int splitOffset);
165 
166     /**
167      * Break a composite buffer into its constituent components.
168      * <p>
169      * This "consumes" the composite buffer, leaving the composite buffer instance as if it had been closed.
170      * The buffers in the returned array are not closed, and become owned by the caller.
171      *
172      * @return An array of the constituent buffer components.
173      */
174     Buffer[] decomposeBuffer();
175 
176     @Override
177     CompositeBuffer readerOffset(int offset);
178 
179     @Override
180     CompositeBuffer writerOffset(int offset);
181 
182     @Override
183     default CompositeBuffer skipReadableBytes(int delta) {
184         return (CompositeBuffer) Buffer.super.skipReadableBytes(delta);
185     }
186 
187     @Override
188     default CompositeBuffer skipWritableBytes(int delta) {
189         return (CompositeBuffer) Buffer.super.skipWritableBytes(delta);
190     }
191 
192     @Override
193     CompositeBuffer fill(byte value);
194 
195     @Override
196     CompositeBuffer makeReadOnly();
197 
198     @Override
199     default CompositeBuffer writeBytes(Buffer source) {
200         return (CompositeBuffer) Buffer.super.writeBytes(source);
201     }
202 
203     @Override
204     default CompositeBuffer writeBytes(byte[] source) {
205         return (CompositeBuffer) Buffer.super.writeBytes(source);
206     }
207 
208     @Override
209     default CompositeBuffer writeBytes(byte[] source, int srcPos, int length) {
210         return (CompositeBuffer) Buffer.super.writeBytes(source, srcPos, length);
211     }
212 
213     @Override
214     default CompositeBuffer writeCharSequence(CharSequence source, Charset charset) {
215         return (CompositeBuffer) Buffer.super.writeCharSequence(source, charset);
216     }
217 
218     @Override
219     default CompositeBuffer readBytes(byte[] destination, int destPos, int length) {
220         return (CompositeBuffer) Buffer.super.readBytes(destination, destPos, length);
221     }
222 
223     @Override
224     default CompositeBuffer writeBoolean(boolean value) {
225         return (CompositeBuffer) Buffer.super.writeBoolean(value);
226     }
227 
228     @Override
229     default CompositeBuffer setBoolean(int woff, boolean value) {
230         return (CompositeBuffer) Buffer.super.setBoolean(woff, value);
231     }
232 
233     @Override
234     default CompositeBuffer writeBytes(ByteBuffer source) {
235         return (CompositeBuffer) Buffer.super.writeBytes(source);
236     }
237 
238     @Override
239     default CompositeBuffer readBytes(ByteBuffer destination) {
240         return (CompositeBuffer) Buffer.super.readBytes(destination);
241     }
242 
243     @Override
244     default CompositeBuffer resetOffsets() {
245         return (CompositeBuffer) Buffer.super.resetOffsets();
246     }
247 
248     @Override
249     default CompositeBuffer ensureWritable(int size) {
250         return (CompositeBuffer) Buffer.super.ensureWritable(size);
251     }
252 
253     @Override
254     CompositeBuffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction);
255 
256     @Override
257     default CompositeBuffer copy() {
258         return (CompositeBuffer) Buffer.super.copy();
259     }
260 
261     @Override
262     default CompositeBuffer copy(int offset, int length) {
263         return (CompositeBuffer) Buffer.super.copy(offset, length);
264     }
265 
266     @Override
267     CompositeBuffer copy(int offset, int length, boolean readOnly);
268 
269     @Override
270     default CompositeBuffer split() {
271         return (CompositeBuffer) Buffer.super.split();
272     }
273 
274     @Override
275     CompositeBuffer split(int splitOffset);
276 
277     @Override
278     CompositeBuffer compact();
279 
280     @Override
281     CompositeBuffer writeByte(byte value);
282 
283     @Override
284     CompositeBuffer setByte(int woff, byte value);
285 
286     @Override
287     CompositeBuffer writeUnsignedByte(int value);
288 
289     @Override
290     CompositeBuffer setUnsignedByte(int woff, int value);
291 
292     @Override
293     CompositeBuffer writeChar(char value);
294 
295     @Override
296     CompositeBuffer setChar(int woff, char value);
297 
298     @Override
299     CompositeBuffer writeShort(short value);
300 
301     @Override
302     CompositeBuffer setShort(int woff, short value);
303 
304     @Override
305     CompositeBuffer writeUnsignedShort(int value);
306 
307     @Override
308     CompositeBuffer setUnsignedShort(int woff, int value);
309 
310     @Override
311     CompositeBuffer writeMedium(int value);
312 
313     @Override
314     CompositeBuffer setMedium(int woff, int value);
315 
316     @Override
317     CompositeBuffer writeUnsignedMedium(int value);
318 
319     @Override
320     CompositeBuffer setUnsignedMedium(int woff, int value);
321 
322     @Override
323     CompositeBuffer writeInt(int value);
324 
325     @Override
326     CompositeBuffer setInt(int woff, int value);
327 
328     @Override
329     CompositeBuffer writeUnsignedInt(long value);
330 
331     @Override
332     CompositeBuffer setUnsignedInt(int woff, long value);
333 
334     @Override
335     CompositeBuffer writeFloat(float value);
336 
337     @Override
338     CompositeBuffer setFloat(int woff, float value);
339 
340     @Override
341     CompositeBuffer writeLong(long value);
342 
343     @Override
344     CompositeBuffer setLong(int woff, long value);
345 
346     @Override
347     CompositeBuffer writeDouble(double value);
348 
349     @Override
350     CompositeBuffer setDouble(int woff, double value);
351 
352     @Override
353     CompositeBuffer implicitCapacityLimit(int limit);
354 }