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.buffer.api.ComponentIterator.Next;
19  import io.netty5.buffer.api.internal.Statics;
20  import io.netty5.util.Resource;
21  
22  import java.io.IOException;
23  import java.nio.ByteBuffer;
24  import java.nio.ByteOrder;
25  import java.nio.channels.FileChannel;
26  import java.nio.channels.GatheringByteChannel;
27  import java.nio.channels.ReadableByteChannel;
28  import java.nio.channels.ScatteringByteChannel;
29  import java.nio.channels.WritableByteChannel;
30  import java.nio.charset.Charset;
31  
32  import static io.netty5.util.internal.ObjectUtil.checkPositiveOrZero;
33  
34  /**
35   * A life cycled buffer of memory, with separate reader and writer offsets.
36   * <p>
37   * A buffer is a logically sequential stretch of memory with a certain capacity, an offset for writing,
38   * and an offset for reading.
39   * Buffers may be {@linkplain CompositeBuffer composed} of multiple {@linkplain #countComponents() components},
40   * where each component is a guaranteed contiguous chunk of memory.
41   *
42   * <h3>Creating a buffer</h3>
43   *
44   * Buffers are created by {@linkplain BufferAllocator allocators}, and their {@code allocate} family of methods.
45   * A number of standard allocators exist, and are available through static methods on the {@code BufferAllocator}
46   * interface.
47   *
48   * <h3>Buffer life cycle</h3>
49   *
50   * The buffer has a life cycle, where it is allocated, used, and deallocated.
51   * When the buffer is initially allocated, a pairing {@link #close()} call will deallocate it.
52   * If a buffer is {@linkplain #send() sent} elsewhere, the {@linkplain #close() close} method on the given instance
53   * will become a no-op.
54   * The buffer can be thought of as a view onto memory, and calling {@link #send()} on the buffer will effectively close
55   * that view, and recreate it upon reception at its destination.
56   *
57   * <h3>Thread-safety</h3>
58   *
59   * Buffers are <strong>not</strong> thread-safe.
60   *
61   * <h3>Accessing data</h3>
62   *
63   * Data access methods fall into two classes:
64   * <ol>
65   *     <li>Access that are based on, and updates, the read or write offset positions.</li>
66   *     <ul><li>These accessor methods are typically called {@code readX} or {@code writeX}.</li></ul>
67   *     <li>Access that take offsets as arguments, and do not update read or write offset positions.</li>
68   *     <ul><li>These accessor methods are typically called {@code getX} or {@code setX}.</li></ul>
69   * </ol>
70   *
71   * A buffer contains two mutable offset positions: one for reading and one for writing.
72   * These positions use <a href="https://en.wikipedia.org/wiki/Zero-based_numbering">zero-based indexing</a>,
73   * such that the first byte of data in the buffer is placed at offset {@code 0},
74   * and the last byte in the buffer is at offset {@link #capacity() capacity - 1}.
75   * The {@link #readerOffset()} is the offset into the buffer from which the next read will take place,
76   * and is initially zero.
77   * The reader offset must always be less than or equal to the {@link #writerOffset()}.
78   * The {@link #writerOffset()} is likewise the offset into the buffer where the next write will take place.
79   * The writer offset is also initially zero, and must be less than or equal to the {@linkplain #capacity() capacity}.
80   * <p>
81   * This carves the buffer into three regions, as demonstrated by this diagram:
82   * <pre>
83   *      +-------------------+------------------+------------------+
84   *      | discardable bytes |  readable bytes  |  writable bytes  |
85   *      |                   |     (CONTENT)    |                  |
86   *      +-------------------+------------------+------------------+
87   *      |                   |                  |                  |
88   *      0      <=     readerOffset  <=   writerOffset    <=    capacity
89   * </pre>
90   *
91   * <h3>Byte Order</h3>
92   *
93   * Buffers are always big endian, and this cannot be changed.
94   * Usages that need to get, set, read, or write, little-endian values will have to flip the byte order of the values
95   * they read and write.
96   *
97   * <h3 name="split">Splitting buffers</h3>
98   *
99   * The {@link #split()} method breaks a buffer into two.
100  * The two buffers will share the underlying memory, but their regions will not overlap, ensuring that the memory is
101  * safely shared between the two.
102  * <p>
103  * Splitting a buffer is useful for when you want to hand over a region of a buffer to some other,
104  * perhaps unknown, piece of code, and relinquish your ownership of that buffer region in the process.
105  * Examples include aggregating messages into an accumulator buffer, and sending messages down the pipeline for
106  * further processing, as split buffer regions, once their data has been received in its entirety.
107  *
108  * If you instead wish to temporarily share a region of a buffer, you will have to pass offset and length along with the
109  * buffer, or you will have to make a copy of the region.
110  *
111  * <h3>Buffers as constants</h3>
112  *
113  * Sometimes, the same bit of data will be processed or transmitted over and over again. In such cases, it can be
114  * tempting to allocate and fill a buffer once, and then reuse it.
115  * Such reuse must be done carefully, however, to avoid a number of bugs.
116  * The {@link BufferAllocator} has a {@link BufferAllocator#constBufferSupplier(byte[])} method that solves this, and
117  * prevents these bugs from occurring.
118  */
119 public interface Buffer extends Resource<Buffer>, BufferAccessor {
120     /**
121      * The capacity of this buffer, that is, the maximum number of bytes it can contain.
122      *
123      * @return The capacity in bytes.
124      */
125     int capacity();
126 
127     /**
128      * Get the current reader offset. The next read will happen from this byte offset into the buffer.
129      *
130      * @return The current reader offset.
131      */
132     int readerOffset();
133 
134     /**
135      * Move the reader offset forward by the given delta.
136      *
137      * @param delta to accumulate.
138      * @return This buffer instance.
139      * @throws IndexOutOfBoundsException if the new reader offset is greater than the current
140      * {@link #writerOffset()}.
141      * @throws IllegalArgumentException if the given delta is negative.
142      * @throws BufferClosedException if this buffer is closed.
143      */
144     default Buffer skipReadableBytes(int delta) {
145         checkPositiveOrZero(delta, "delta");
146         readerOffset(readerOffset() + delta);
147         return this;
148     }
149 
150     /**
151      * Set the reader offset. Make the next read happen from the given offset into the buffer.
152      *
153      * @param offset The reader offset to set.
154      * @return This Buffer.
155      * @throws IndexOutOfBoundsException if the specified {@code offset} is less than zero or greater than the current
156      *                                   {@link #writerOffset()}.
157      * @throws BufferClosedException if this buffer is closed.
158      */
159     Buffer readerOffset(int offset);
160 
161     /**
162      * Get the current writer offset. The next write will happen at this byte offset into the buffer.
163      *
164      * @return The current writer offset.
165      */
166     int writerOffset();
167 
168     /**
169      * Move the writer offset to ahead by the given delta.
170      *
171      * @param delta to accumulate.
172      * @return This buffer instance.
173      * @throws IndexOutOfBoundsException if the new writer offset is greater than {@link #capacity()}.
174      * @throws IllegalArgumentException if the given delta is negative.
175      * @throws BufferClosedException if this buffer is closed.
176      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
177      */
178     default Buffer skipWritableBytes(int delta) {
179         checkPositiveOrZero(delta, "delta");
180         writerOffset(writerOffset() + delta);
181         return this;
182     }
183 
184     /**
185      * Set the writer offset. Make the next write happen at the given offset.
186      *
187      * @param offset The writer offset to set.
188      * @return This Buffer.
189      * @throws IndexOutOfBoundsException if the specified {@code offset} is less than the current
190      * {@link #readerOffset()} or greater than {@link #capacity()}.
191      * @throws BufferClosedException if this buffer is closed.
192      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
193      */
194     Buffer writerOffset(int offset);
195 
196     /**
197      * Returns the number of readable bytes which is equal to {@code (writerOffset() - readerOffset())}.
198      */
199     default int readableBytes() {
200         return writerOffset() - readerOffset();
201     }
202 
203     /**
204      * Returns the number of writable bytes which is equal to {@code (capacity() - writerOffset())}.
205      */
206     default int writableBytes() {
207         return capacity() - writerOffset();
208     }
209 
210     /**
211      * Fills the buffer with the given byte value. This method does not respect the {@link #readerOffset()} or {@link
212      * #writerOffset()}, but copies the full capacity of the buffer. The {@link #readerOffset()} and {@link
213      * #writerOffset()} are not modified.
214      *
215      * @param value The byte value to write at every offset in the buffer.
216      * @return This Buffer.
217      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
218      */
219     Buffer fill(byte value);
220 
221     /**
222      * Makes this buffer read-only. This is irreversible.
223      * This operation is also idempotent, so calling this method multiple times on the same buffer makes no difference.
224      *
225      * @return This buffer instance.
226      */
227     Buffer makeReadOnly();
228 
229     /**
230      * Queries if this buffer is read-only or not.
231      *
232      * @return {@code true} if this buffer is read-only, {@code false} otherwise.
233      */
234     boolean readOnly();
235 
236     /**
237      * Queries if this buffer is backed by native memory, or not.
238      *
239      * @return {@code true} if this buffer is backed by native, off-heap, memory. Otherwise, {@code false}, if this
240      * buffer is backed by on-heap memory.
241      */
242     boolean isDirect();
243 
244     /**
245      * Set an upper limit to the implicit capacity growth. Buffer {@code write*} methods may implicitly grow the buffer
246      * capacity instead of throwing a bounds check exception. The implicit capacity limit restricts this growth so the
247      * buffer capacity does not automatically grow beyond the given limit. When the limit is reached, and there is no
248      * more writable space left, then the {@code write*} methods will start throwing exceptions.
249      * <p>
250      * The default limit is the maximum buffer size.
251      * <p>
252      * The limit is carried through {@link #send()} calls, but the buffer instances returned from the various
253      * {@code split} and {@code copy} methods will have the default limit set.
254      * <p>
255      * The limit is not impacted by calls to {@code split} methods on this buffer. In other words, even though
256      * {@code split} methods reduce the capacity of this buffer, the set limit, if any, remains the same.
257      *
258      * @param limit The maximum size this buffers capacity will implicitly grow to via {@code write*} methods.
259      * @return This buffer instance.
260      * @throws IndexOutOfBoundsException if the limit is negative, greater than the maximum buffer size, or if the
261      *                                   {@linkplain #capacity() capacity} is already greater than the given limit.
262      */
263     Buffer implicitCapacityLimit(int limit);
264 
265     /**
266      * Returns the implicit capacity limit of the buffer. If none was set before via {@link #implicitCapacityLimit(int)}
267      * this method will return the default value.
268      *
269      * @return the limit.
270      */
271     int implicitCapacityLimit();
272 
273     /**
274      * Copies the given length of data from this buffer into the given destination array, beginning at the given source
275      * position in this buffer, and the given destination position in the destination array.
276      * <p>
277      * This method does not read or modify the {@linkplain #writerOffset() write offset} or the
278      * {@linkplain #readerOffset() read offset}.
279      *
280      * @param srcPos The byte offset into this buffer from where the copying should start; the byte at this offset in
281      *              this buffer will be copied to the {@code destPos} index in the {@code dest} array.
282      * @param dest The destination byte array.
283      * @param destPos The index into the {@code dest} array from where the copying should start.
284      * @param length The number of bytes to copy.
285      * @throws NullPointerException if the destination array is null.
286      * @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
287      * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
288      * @throws BufferClosedException if this buffer is closed.
289      */
290     void copyInto(int srcPos, byte[] dest, int destPos, int length);
291 
292     /**
293      * Copies the given length of data from this buffer into the given destination byte buffer, beginning at the given
294      * source position in this buffer, and the given destination position in the destination byte buffer.
295      * <p>
296      * This method does not read or modify the {@linkplain #writerOffset() write offset} or the
297      * {@linkplain #readerOffset() read offset}, nor is the position of the destination buffer changed.
298      * <p>
299      * The position and limit of the destination byte buffer are also ignored, and do not influence {@code destPos}
300      * or {@code length}.
301      *
302      * @param srcPos The byte offset into this buffer from where the copying should start; the byte at this offset in
303      *              this buffer will be copied to the {@code destPos} index in the {@code dest} array.
304      * @param dest The destination byte buffer.
305      * @param destPos The index into the {@code dest} array from where the copying should start.
306      * @param length The number of bytes to copy.
307      * @throws NullPointerException if the destination buffer is null.
308      * @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
309      * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
310      * @throws java.nio.ReadOnlyBufferException if the destination buffer is read-only.
311      * @throws BufferClosedException if this buffer is closed.
312      */
313     void copyInto(int srcPos, ByteBuffer dest, int destPos, int length);
314 
315     /**
316      * Copies the given length of data from this buffer into the given destination buffer, beginning at the given
317      * source position in this buffer, and the given destination position in the destination buffer.
318      * <p>
319      * This method does not read or modify the {@linkplain #writerOffset() write offset} or the
320      * {@linkplain #readerOffset() read offset} on this buffer, nor on the destination buffer.
321      * <p>
322      * The read and write offsets of the destination buffer are also ignored, and do not influence {@code destPos}
323      * or {@code length}.
324      *
325      * @param srcPos The byte offset into this buffer from where the copying should start; the byte at this offset in
326      *              this buffer will be copied to the {@code destPos} index in the {@code dest} array.
327      * @param dest The destination buffer.
328      * @param destPos The index into the {@code dest} array from where the copying should start.
329      * @param length The number of bytes to copy.
330      * @throws NullPointerException if the destination buffer is null.
331      * @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
332      * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
333      * @throws BufferReadOnlyException if the destination buffer is read-only.
334      * @throws BufferClosedException if this or the destination buffer is closed.
335      */
336     void copyInto(int srcPos, Buffer dest, int destPos, int length);
337 
338     /**
339      * Read from this buffer and write to the given channel.
340      * The number of bytes actually written to the channel are returned.
341      * No more than the given {@code length} of bytes, or the number of {@linkplain #readableBytes() readable bytes},
342      * will be written to the channel, whichever is smaller.
343      * If the channel has a position, then it will be advanced by the number of bytes written.
344      * The {@linkplain #readerOffset() reader-offset} of this buffer will likewise be advanced by the number of bytes
345      * written.
346      *
347      * @implNote {@linkplain CompositeBuffer composite buffers} may offer an optimized implementation of this method,
348      * if the given channel implements {@link GatheringByteChannel}.
349      *
350      * @param channel The channel to write to.
351      * @param length The maximum number of bytes to write.
352      * @return The actual number of bytes written, possibly zero.
353      * @throws IOException If the write-operation on the channel failed for some reason.
354      */
355     int transferTo(WritableByteChannel channel, int length) throws IOException;
356 
357     /**
358      * Read from the given channel starting from the given position and write to this buffer.
359      * The number of bytes actually read from the channel are returned, or -1 is returned if the channel has reached
360      * the end-of-stream.
361      * No more than the given {@code length} of bytes, or the number of {@linkplain #writableBytes() writable bytes},
362      * will be read from the channel, whichever is smaller.
363      * The channel's position is not modified.
364      * The {@linkplain #writerOffset() writer-offset} of this buffer will likewise be advanced by the number of bytes
365      * read.
366      *
367      * @param channel The channel to read from.
368      * @param position The file position.
369      * @param length The maximum number of bytes to read.
370      * @return The actual number of bytes read, possibly zero, or -1 if the end-of-stream has been reached.
371      * @throws IOException If the read-operation on the channel failed for some reason.
372      */
373     int transferFrom(FileChannel channel, long position, int length) throws IOException;
374 
375     /**
376      * Read from the given channel and write to this buffer.
377      * The number of bytes actually read from the channel are returned, or -1 is returned if the channel has reached
378      * the end-of-stream.
379      * No more than the given {@code length} of bytes, or the number of {@linkplain #writableBytes() writable bytes},
380      * will be read from the channel, whichever is smaller.
381      * If the channel has a position, then it will be advanced by the number of bytes read.
382      * The {@linkplain #writerOffset() writer-offset} of this buffer will likewise be advanced by the number of bytes
383      * read.
384      *
385      * @implNote {@linkplain CompositeBuffer composite buffers} may offer an optimized implementation of this method,
386      * if the given channel implements {@link ScatteringByteChannel}.
387      *
388      * @param channel The channel to read from.
389      * @param length The maximum number of bytes to read.
390      * @return The actual number of bytes read, possibly zero, or -1 if the end-of-stream has been reached.
391      * @throws IOException If the read-operation on the channel failed for some reason.
392      */
393     int transferFrom(ReadableByteChannel channel, int length) throws IOException;
394 
395     /**
396      * Writes into this buffer, all the bytes from the given {@code source} using the passed {@code charset}.
397      * This updates the {@linkplain #writerOffset() write offset} of this buffer.
398      *
399      * @param source {@link CharSequence} to read from.
400      * @param charset {@link Charset} to use for writing.
401      * @return This buffer.
402      */
403     default Buffer writeCharSequence(CharSequence source, Charset charset) {
404         Statics.writeCharSequence(source, this, charset);
405         return this;
406     }
407 
408     /**
409      * Reads a {@link CharSequence} of the passed {@code length} using the passed {@link Charset}.
410      * This updates the {@linkplain #readerOffset()} reader offset} of this buffer.
411      *
412      * @param length of {@link CharSequence} to read.
413      * @param charset of the bytes to be read.
414      * @return {@link CharSequence} read from this buffer.
415      * @throws IndexOutOfBoundsException if the passed {@code length} is more than the {@linkplain #readableBytes()} of
416      * this buffer.
417      */
418     default CharSequence readCharSequence(int length, Charset charset) {
419         return Statics.readCharSequence(this, length, charset);
420     }
421 
422     /**
423      * Writes into this buffer, all the readable bytes from the given buffer.
424      * This updates the {@linkplain #writerOffset() write offset} of this buffer, and the
425      * {@linkplain #readerOffset() reader offset} of the given buffer.
426      *
427      * @param source The buffer to read from.
428      * @return This buffer.
429      * @throws NullPointerException If the source buffer is {@code null}.
430      */
431     default Buffer writeBytes(Buffer source) {
432         int size = source.readableBytes();
433         if (writableBytes() < size && writerOffset() + size <= implicitCapacityLimit()) {
434             ensureWritable(size, 1, false);
435         }
436         int woff = writerOffset();
437         source.copyInto(source.readerOffset(), this, woff, size);
438         source.skipReadableBytes(size);
439         skipWritableBytes(size);
440         return this;
441     }
442 
443     /**
444      * Writes into this buffer, all the bytes from the given byte array.
445      * This updates the {@linkplain #writerOffset() write offset} of this buffer by the length of the array.
446      *
447      * @param source The byte array to read from.
448      * @return This buffer.
449      */
450     default Buffer writeBytes(byte[] source) {
451         return writeBytes(source, 0, source.length);
452     }
453 
454     /**
455      * Writes into this buffer, the given number of bytes from the byte array.
456      * This updates the {@linkplain #writerOffset() write offset} of this buffer by the length argument.
457      *
458      * @param source The byte array to read from.
459      * @param srcPos Position in the {@code source} from where bytes should be written to this buffer.
460      * @param length The number of bytes to copy.
461      * @return This buffer.
462      */
463     default Buffer writeBytes(byte[] source, int srcPos, int length) {
464         if (source.length < srcPos + length) {
465             throw new ArrayIndexOutOfBoundsException();
466         }
467         if (writableBytes() < length && writerOffset() + length <= implicitCapacityLimit()) {
468             ensureWritable(length, 1, false);
469         }
470         int woff = writerOffset();
471         for (int i = 0; i < length; i++) {
472             setByte(woff + i, source[srcPos + i]);
473         }
474         skipWritableBytes(length);
475         return this;
476     }
477 
478     /**
479      * Writes into this buffer from the source {@link ByteBuffer}.
480      * This updates the {@linkplain #writerOffset() write offset} of this buffer and also the position of
481      * the source {@link ByteBuffer}.
482      * <p>
483      * Note: the behaviour is undefined if the given {@link ByteBuffer} is an alias for the memory in this buffer.
484      *
485      * @param source The {@link ByteBuffer} to read from.
486      * @return This buffer.
487      */
488     default Buffer writeBytes(ByteBuffer source) {
489         if (source.hasArray()) {
490             writeBytes(source.array(), source.arrayOffset() + source.position(), source.remaining());
491             source.position(source.limit());
492         } else {
493             int woff = writerOffset();
494             int length = source.remaining();
495             if (writableBytes() < length && woff + length <= implicitCapacityLimit()) {
496                 ensureWritable(length, 1, false);
497             }
498             writerOffset(woff + length);
499             // Try to reduce bounds-checking by using long and int when possible.
500             boolean needReverse = source.order() != ByteOrder.BIG_ENDIAN;
501             for (; length >= Long.BYTES; length -= Long.BYTES, woff += Long.BYTES) {
502                 setLong(woff, needReverse ? Long.reverseBytes(source.getLong()) : source.getLong());
503             }
504             for (; length >= Integer.BYTES; length -= Integer.BYTES, woff += Integer.BYTES) {
505                 setInt(woff, needReverse ? Integer.reverseBytes(source.getInt()) : source.getInt());
506             }
507             for (; length > 0; length--, woff++) {
508                 setByte(woff, source.get());
509             }
510         }
511         return this;
512     }
513 
514     /**
515      * Read from this buffer, into the destination {@link ByteBuffer}
516      * This updates the {@linkplain #readerOffset() read offset} of this buffer and also the position of
517      * the destination {@link ByteBuffer}.
518      * <p>
519      * Note: the behaviour is undefined if the given {@link ByteBuffer} is an alias for the memory in this buffer.
520      *
521      * @param destination The {@link ByteBuffer} to write into.
522      * @return This buffer.
523      */
524     default Buffer readBytes(ByteBuffer destination) {
525         int byteCount = destination.remaining();
526         copyInto(readerOffset(), destination, destination.position(), byteCount);
527         skipReadableBytes(byteCount);
528         destination.position(destination.limit());
529         return this;
530     }
531 
532     /**
533      * Read from this buffer, into the destination array, the given number of bytes.
534      * This updates the {@linkplain #readerOffset() read offset} of this buffer by the length argument.
535      *
536      * @param destination The byte array to write into.
537      * @param destPos Position in the {@code destination} to where bytes should be written from this buffer.
538      * @param length The number of bytes to copy.
539      * @return This buffer.
540      */
541     default Buffer readBytes(byte[] destination, int destPos, int length) {
542         int roff = readerOffset();
543         copyInto(roff, destination, destPos, length);
544         readerOffset(roff + length);
545         return this;
546     }
547 
548     /**
549      * Resets the {@linkplain #readerOffset() read offset} and the {@linkplain #writerOffset() write offset} on this
550      * buffer to zero, and return this buffer.
551      *
552      * @return This buffer instance.
553      */
554     default Buffer resetOffsets() {
555         readerOffset(0);
556         if (!readOnly()) {
557             writerOffset(0);
558         }
559         return this;
560     }
561 
562     /**
563      * Get the number of {@linkplain #readableBytes() readable bytes}, until the given {@code needle} is found in this
564      * buffer.
565      * If the needle is not found, {@code -1} is returned.
566      * <p>
567      * This method does not modify the {@linkplain #readerOffset() reader-offset} or the
568      * {@linkplain #writerOffset() write-offset}.
569      *
570      * @param needle The byte value to search for.
571      * @return The offset, relative to the current {@link #readerOffset()}, of the found value, or {@code -1} if none
572      * was found.
573      */
574     int bytesBefore(byte needle);
575 
576     /**
577      * Get the number of {@linkplain #readableBytes() readable bytes}, until the given {@code needle} is found in this
578      * buffer.
579      * The found offset will be the offset into this buffer, relative to its {@linkplain #readerOffset() reader-offset},
580      * of the first byte of a sequence that matches all readable bytes in the given {@code needle} buffer.
581      * If the needle is not found, {@code -1} is returned.
582      * <p>
583      * This method does not modify the {@linkplain #readerOffset() reader-offset} or the
584      * {@linkplain #writerOffset() write-offset}.
585      *
586      * @param needle The buffer value to search for.
587      * @return The offset, relative to the current {@link #readerOffset()}, of the found value, or {@code -1} if none
588      * was found.
589      */
590     int bytesBefore(Buffer needle);
591 
592     /**
593      * Opens a cursor to iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and
594      * {@linkplain #writerOffset() writer offset} are not modified by the cursor.
595      * <p>
596      * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
597      * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
598      * while the iteration takes place. Otherwise, unpredictable behaviour might result.
599      *
600      * @return A {@link ByteCursor} for iterating the readable bytes of this buffer.
601      */
602     ByteCursor openCursor();
603 
604     /**
605      * Opens a cursor to iterate the given number bytes of this buffer, starting at the given offset.
606      * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified by
607      * the cursor.
608      * <p>
609      * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
610      * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
611      * while the iteration takes place. Otherwise, unpredictable behaviour might result.
612      *
613      * @param fromOffset The offset into the buffer where iteration should start.
614      *                  The first byte read from the iterator will be the byte at this offset.
615      * @param length The number of bytes to iterate.
616      * @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
617      * @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
618      * the {@code length} reaches outside the bounds of this buffer.
619      */
620     ByteCursor openCursor(int fromOffset, int length);
621 
622     /**
623      * Opens a cursor to iterate the readable bytes of this buffer, in reverse.
624      * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified by
625      * the cursor.
626      * <p>
627      * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
628      * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
629      * while the iteration takes place. Otherwise, unpredictable behaviour might result.
630      *
631      * @return A {@link ByteCursor} for the readable bytes of this buffer.
632      */
633     default ByteCursor openReverseCursor() {
634         int woff = writerOffset();
635         return openReverseCursor(woff == 0? 0 : woff - 1, readableBytes());
636     }
637 
638     /**
639      * Opens a cursor to iterate the given number bytes of this buffer, in reverse, starting at the given offset.
640      * The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified by
641      * the cursor.
642      * <p>
643      * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
644      * the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
645      * while the iteration takes place. Otherwise, unpredictable behaviour might result.
646      *
647      * @param fromOffset The offset into the buffer where iteration should start.
648      *                  The first byte read from the iterator will be the byte at this offset.
649      * @param length The number of bytes to iterate.
650      * @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
651      * @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
652      * the {@code length} reaches outside the bounds of this buffer.
653      */
654     ByteCursor openReverseCursor(int fromOffset, int length);
655 
656     /**
657      * Ensures that this buffer has at least the given number of bytes of
658      * {@linkplain #writableBytes() available space for writing}.
659      * If this buffer already has the necessary space, then this method returns immediately.
660      * If this buffer does not already have the necessary space, then it will be expanded using the
661      * {@link BufferAllocator} the buffer was created with.
662      * This method is the same as calling {@link #ensureWritable(int, int, boolean)} where {@code allowCompaction} is
663      * {@code true}.
664      *
665      * @param size The requested number of bytes of space that should be available for writing.
666      * @return This buffer instance.
667      * @throws IllegalStateException if this buffer is in a bad state.
668      * @throws BufferClosedException if this buffer is closed.
669      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
670      */
671     default Buffer ensureWritable(int size) {
672         ensureWritable(size, capacity(), true);
673         return this;
674     }
675 
676     /**
677      * Ensures that this buffer has at least the given number of bytes of
678      * {@linkplain #writableBytes() available space for writing}.
679      * If this buffer already has the necessary space, then this method returns immediately.
680      * If this buffer does not already have the necessary space, then space will be made available in one or all of
681      * the following available ways:
682      *
683      * <ul>
684      *     <li>
685      *         If {@code allowCompaction} is {@code true}, and sum of the read and writable bytes would be enough to
686      *         satisfy the request, and it (depending on the buffer implementation) seems faster and easier to compact
687      *         the existing buffer rather than allocation a new buffer, then the requested bytes will be made available
688      *         that way. The compaction will not necessarily work the same way as the {@link #compact()} method, as the
689      *         implementation may be able to make the requested bytes available with less effort than is strictly
690      *         mandated by the {@link #compact()} method.
691      *     </li>
692      *     <li>
693      *         Regardless of the value of the {@code allowCompaction}, the implementation may make more space available
694      *         by just allocating more or larger buffers. This allocation would use the same {@link BufferAllocator}
695      *         that this buffer was created with.
696      *     </li>
697      *     <li>
698      *         If {@code allowCompaction} is {@code true}, then the implementation may choose to do a combination of
699      *         compaction and allocation.
700      *     </li>
701      * </ul>
702      *
703      * @param size The requested number of bytes of space that should be available for writing.
704      * @return This buffer instance.
705      * @param minimumGrowth The minimum number of bytes to grow by. If it is determined that memory should be allocated
706      *                     and copied, make sure that the new memory allocation is bigger than the old one by at least
707      *                     this many bytes. This way, the buffer can grow by more than what is immediately necessary,
708      *                     thus amortising the costs of allocating and copying.
709      * @param allowCompaction {@code true} if the method is allowed to modify the
710      *                                   {@linkplain #readerOffset() reader offset} and
711      *                                   {@linkplain #writerOffset() writer offset}, otherwise {@code false}.
712      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
713      * @throws IllegalArgumentException if {@code size} or {@code minimumGrowth} are negative.
714      * @throws IllegalStateException if this buffer is in a bad state.
715      */
716     Buffer ensureWritable(int size, int minimumGrowth, boolean allowCompaction);
717 
718     /**
719      * Returns a copy of this buffer's readable bytes.
720      * Modifying the content of the returned buffer will not affect this buffers contents.
721      * The two buffers will maintain separate offsets. This method is identical to
722      * {@code buf.copy(buf.readerOffset(), buf.readableBytes())}.
723      * This method does not modify {@link #readerOffset()} or {@link #writerOffset()} of this buffer.
724      * <p>
725      * The copy is created with a {@linkplain #writerOffset() write offset} equal to the length of the copied data,
726      * so that the entire contents of the copy is ready to be read.
727      * <p>
728      * The returned buffer will not be read-only, regardless of the {@linkplain #readOnly() read-only state} of this
729      * buffer.
730      *
731      * @return A new buffer instance, with independent {@link #readerOffset()} and {@link #writerOffset()},
732      * that contains a copy of the readable region of this buffer.
733      * @throws BufferClosedException if this buffer is closed.
734      */
735     default Buffer copy() {
736         int offset = readerOffset();
737         int length = readableBytes();
738         return copy(offset, length);
739     }
740 
741     /**
742      * Returns a copy of the given region of this buffer.
743      * Modifying the content of the returned buffer will not affect this buffers contents.
744      * The two buffers will maintain separate offsets.
745      * This method does not modify {@link #readerOffset()} or {@link #writerOffset()} of this buffer.
746      * <p>
747      * The copy is created with a {@linkplain #writerOffset() write offset} equal to the length of the copy,
748      * so that the entire contents of the copy is ready to be read.
749      * <p>
750      * The returned buffer will not be read-only, regardless of the {@linkplain #readOnly() read-only state} of this
751      * buffer.
752      * This has the same effect as calling {@link #copy(int, int, boolean)} with a {@code false} read-only argument.
753      *
754      * @param offset The offset where copying should start from. This is the offset of the first byte copied.
755      * @param length The number of bytes to copy, and the capacity of the returned buffer.
756      * @return A new buffer instance, with independent {@link #readerOffset()} and {@link #writerOffset()},
757      * that contains a copy of the given region of this buffer.
758      * @throws IllegalArgumentException if the {@code offset} or {@code length} reaches outside the bounds of the
759      * buffer.
760      * @throws BufferClosedException if this buffer is closed.
761      */
762     default Buffer copy(int offset, int length) {
763         return copy(offset, length, false);
764     }
765 
766     /**
767      * Returns a copy of this buffer's readable bytes, with the given read-only setting.
768      * Modifying the content of the returned buffer will not affect this buffers contents.
769      * The two buffers will maintain separate offsets.
770      * This method does not modify {@link #readerOffset()} or {@link #writerOffset()} of this buffer.
771      * <p>
772      * The copy is created with a {@linkplain #writerOffset() write offset} equal to the length of the copy,
773      * so that the entire contents of the copy is ready to be read.
774      * <p>
775      * The returned buffer will be read-only if, and only if, the {@code readOnly} argument is {@code true}, and it
776      * will not be read-only if the argument is {@code false}.
777      * This is the case regardless of the {@linkplain #readOnly() read-only state} of this buffer.
778      * <p>
779      * If this buffer is read-only, and a read-only copy is requested, then implementations <em>may</em> use structural
780      * sharing and have both buffers backed by the same underlying memory.
781      *
782      * @param readOnly The desired {@link #readOnly()} state of the returned buffer.
783      * @return A new buffer instance, with independent {@link #readerOffset()} and {@link #writerOffset()},
784      * that contains a copy of the given region of this buffer.
785      * @throws IllegalArgumentException if the {@code offset} or {@code length} reaches outside the bounds of the
786      * buffer.
787      * @throws BufferClosedException if this buffer is closed.
788      */
789     default Buffer copy(boolean readOnly) {
790         return copy(readerOffset(), readableBytes(), readOnly);
791     }
792 
793     /**
794      * Returns a copy of the given region of this buffer.
795      * Modifying the content of the returned buffer will not affect this buffers contents.
796      * The two buffers will maintain separate offsets.
797      * This method does not modify {@link #readerOffset()} or {@link #writerOffset()} of this buffer.
798      * <p>
799      * The copy is created with a {@linkplain #writerOffset() write offset} equal to the length of the copy,
800      * so that the entire contents of the copy is ready to be read.
801      * <p>
802      * The returned buffer will be read-only if, and only if, the {@code readOnly} argument is {@code true}, and it
803      * will not be read-only if the argument is {@code false}.
804      * This is the case regardless of the {@linkplain #readOnly() read-only state} of this buffer.
805      * <p>
806      * If this buffer is read-only, and a read-only copy is requested, then implementations <em>may</em> use structural
807      * sharing and have both buffers backed by the same underlying memory.
808      *
809      * @param offset The offset where copying should start from. This is the offset of the first byte copied.
810      * @param length The number of bytes to copy, and the capacity of the returned buffer.
811      * @param readOnly The desired {@link #readOnly()} state of the returned buffer.
812      * @return A new buffer instance, with independent {@link #readerOffset()} and {@link #writerOffset()},
813      * that contains a copy of the given region of this buffer.
814      * @throws IllegalArgumentException if the {@code offset} or {@code length} reaches outside the bounds of the
815      * buffer.
816      * @throws BufferClosedException if this buffer is closed.
817      */
818     Buffer copy(int offset, int length, boolean readOnly);
819 
820     /**
821      * Splits the buffer into two, at {@code length} number of bytes from the current
822      * {@linkplain #readerOffset()} reader offset} position.
823      * <p>
824      * The region of this buffer that contain the previously read and readable bytes till the
825      * {@code readerOffset() + length} position, will be captured and returned in a new buffer,
826      * that will hold its own ownership of that region.
827      * This allows the returned buffer to be independently {@linkplain #send() sent} to other threads.
828      * <p>
829      * The returned buffer will change its {@link #readerOffset()} to {@code readerOffset() + length}, and have its
830      * {@link #writerOffset()} and {@link #capacity()} both set to the {@code readerOffset() + length} position.
831      * <p>
832      * The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its
833      * capacity reduced by the capacity of the returned buffer, read offset will become zero and relative position of
834      * write offset will be preserved from the provided {@code readerOffset() + length} position,
835      * even though their position in memory remain unchanged.
836      * <p>
837      * Effectively, the following transformation takes place:
838      * <pre>{@code
839      *         This buffer, where offset = readerOffset() + length:
840      *          +------------------------------------------+
841      *         0|   |r/o    offset        |w/o             |cap
842      *          +---+---------+-----------+----------------+
843      *         /   /         / \          \                \
844      *        /   /         /   \          \                \
845      *       /   /         /     \          \                \
846      *      /   /         /       \          \                \
847      *     /   /         /         \          \                \
848      *    +---+---------+           +----------+----------------+
849      *    |   |r/o      |w/o & cap  |r/o      w/o               |cap
850      *    +---+---------+           +---------------------------+
851      *    Returned buffer.                   This buffer.
852      * }</pre>
853      * When the buffers are in this state, both of the split parts retain an atomic reference count on the
854      * underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
855      * all the split parts have been closed.
856      * <p>
857      * Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
858      * split. If the split point lands perfectly between two constituent buffers, then a composite buffer can
859      * simply split its internal array in two.
860      * <p>
861      * Split buffers support all operations that normal buffers do, including {@link #ensureWritable(int)}.
862      * <p>
863      * See the <a href="#split">Splitting buffers</a> section for details.
864      *
865      * @return A new buffer with independent and exclusive ownership over the previously read and readable bytes from
866      * this buffer.
867      */
868     default Buffer readSplit(int length) {
869         return split(readerOffset() + length);
870     }
871 
872     /**
873      * Splits the buffer into two, at {@code length} number of bytes from the current
874      * {@linkplain #writerOffset()} writer offset} position.
875      * <p>
876      * The region of this buffer that contain the previously read and readable bytes till the
877      * {@code writerOffset() + length} position, will be captured and returned in a new buffer,
878      * that will hold its own ownership of that region.
879      * This allows the returned buffer to be independently {@linkplain #send() sent} to other threads.
880      * <p>
881      * The returned buffer will change its {@link #writerOffset()} to {@code writerOffset() + length}, and have its
882      * {@link #writerOffset()} and {@link #capacity()} both set to the {@code writerOffset() + length}.
883      * <p>
884      * The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its
885      * capacity reduced by the capacity of the returned buffer, read offset will become zero and relative position of
886      * write offset will be preserved from the provided {@code writerOffset() + length} position,
887      * even though their position in memory remain unchanged.
888      * <p>
889      * Effectively, the following transformation takes place:
890      * <pre>{@code
891      *         This buffer, where offset = writerOffset() + length:
892      *          +------------------------------------------+
893      *         0|   |r/o  |w/o  offset                     |cap
894      *          +---+----+-------+-------------------------+
895      *         /   /    /       / \                        \
896      *        /   /    /       /   \                        \
897      *       /   /    /       /     \                        \
898      *      /   /    /       /       \                        \
899      *     /   /    /       /         \                        \
900      *    +---+----+-------+           +------------------------+
901      *    |   |r/o  |w/o   | cap       |r/o & w/o               |cap
902      *    +---+----+-------+           +------------------------+
903      *    Returned buffer.                   This buffer.
904      * }</pre>
905      * When the buffers are in this state, both of the split parts retain an atomic reference count on the
906      * underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
907      * all the split parts have been closed.
908      * <p>
909      * Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
910      * split. If the split point lands perfectly between two constituent buffers, then a composite buffer can
911      * simply split its internal array in two.
912      * <p>
913      * Split buffers support all operations that normal buffers do, including {@link #ensureWritable(int)}.
914      * <p>
915      * See the <a href="#split">Splitting buffers</a> section for details.
916      *
917      * @return A new buffer with independent and exclusive ownership over the previously read and readable bytes from
918      * this buffer.
919      */
920     default Buffer writeSplit(int length) {
921         return split(writerOffset() + length);
922     }
923 
924     /**
925      * Splits the buffer into two, at the {@linkplain #writerOffset() write offset} position.
926      * <p>
927      * The region of this buffer that contain the previously read and readable bytes, will be captured and returned in
928      * a new buffer, that will hold its own ownership of that region. This allows the returned buffer to be
929      * independently {@linkplain #send() sent} to other threads.
930      * <p>
931      * The returned buffer will adopt the {@link #readerOffset()} of this buffer, and have its {@link #writerOffset()}
932      * and {@link #capacity()} both set to the equal to the write-offset of this buffer.
933      * <p>
934      * The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its
935      * capacity reduced by the capacity of the returned buffer, and the read and write offsets of this buffer will both
936      * become zero, even though their position in memory remain unchanged.
937      * <p>
938      * Effectively, the following transformation takes place:
939      * <pre>{@code
940      *         This buffer:
941      *          +------------------------------------------+
942      *         0|   |r/o                  |w/o             |cap
943      *          +---+---------------------+----------------+
944      *         /   /                     / \               \
945      *        /   /                     /   \               \
946      *       /   /                     /     \               \
947      *      /   /                     /       \               \
948      *     /   /                     /         \               \
949      *    +---+---------------------+           +---------------+
950      *    |   |r/o                  |w/o & cap  |r/o & w/o      |cap
951      *    +---+---------------------+           +---------------+
952      *    Returned buffer.                      This buffer.
953      * }</pre>
954      * When the buffers are in this state, both of the split parts retain an atomic reference count on the
955      * underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
956      * all the split parts have been closed.
957      * <p>
958      * Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
959      * split. If the split point lands perfectly between two constituent buffers, then a composite buffer can
960      * simply split its internal array in two.
961      * <p>
962      * Split buffers support all operations that normal buffers do, including {@link #ensureWritable(int)}.
963      * <p>
964      * See the <a href="#split">Splitting buffers</a> section for details.
965      *
966      * @return A new buffer with independent and exclusive ownership over the previously read and readable bytes from
967      * this buffer.
968      */
969     default Buffer split() {
970         return split(writerOffset());
971     }
972 
973     /**
974      * Splits the buffer into two, at the given {@code splitOffset}.
975      * <p>
976      * The region of this buffer that precede the {@code splitOffset}, will be captured and returned in a new
977      * buffer, that will hold its own ownership of that region. This allows the returned buffer to be independently
978      * {@linkplain #send() sent} to other threads.
979      * <p>
980      * The returned buffer will adopt the {@link #readerOffset()} and {@link #writerOffset()} of this buffer,
981      * but truncated to fit within the capacity dictated by the {@code splitOffset}.
982      * <p>
983      * The memory region in the returned buffer will become inaccessible through this buffer. If the
984      * {@link #readerOffset()} or {@link #writerOffset()} of this buffer lie prior to the {@code splitOffset},
985      * then those offsets will be moved forward, so they land on offset 0 after the split.
986      * <p>
987      * Effectively, the following transformation takes place:
988      * <pre>{@code
989      *         This buffer:
990      *          +--------------------------------+
991      *         0|               |splitOffset     |cap
992      *          +---------------+----------------+
993      *         /               / \               \
994      *        /               /   \               \
995      *       /               /     \               \
996      *      /               /       \               \
997      *     /               /         \               \
998      *    +---------------+           +---------------+
999      *    |               |cap        |               |cap
1000      *    +---------------+           +---------------+
1001      *    Returned buffer.            This buffer.
1002      * }</pre>
1003      * When the buffers are in this state, both of the split parts retain an atomic reference count on the
1004      * underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
1005      * all the split parts have been closed.
1006      * <p>
1007      * Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
1008      * split. If the split point lands perfectly between two constituent buffers, then a composite buffer can
1009      * simply split its internal array in two.
1010      * <p>
1011      * Split buffers support all operations that normal buffers do, including {@link #ensureWritable(int)}.
1012      * <p>
1013      * See the <a href="#split">Splitting buffers</a> section for details.
1014      *
1015      * @param splitOffset The offset into this buffer where it should be split. After the split, the data at this offset
1016      *                    will be at offset zero in this buffer.
1017      * @return A new buffer with independent and exclusive ownership over the bytes from the beginning to the given
1018      * offset of this buffer.
1019      */
1020     Buffer split(int splitOffset);
1021 
1022     /**
1023      * Discards the read bytes, and moves the buffer contents to the beginning of the buffer.
1024      *
1025      * @return This buffer instance.
1026      * @throws BufferReadOnlyException if this buffer is {@linkplain #readOnly() read-only}.
1027      * @throws IllegalStateException if this buffer is in a bad state.
1028      */
1029     Buffer compact();
1030 
1031     /**
1032      * Get the number of "components" in this buffer. For composite buffers, this is the number of transitive
1033      * constituent buffers, while non-composite buffers only have one component.
1034      *
1035      * @return The number of components in this buffer.
1036      */
1037     int countComponents();
1038 
1039     /**
1040      * Get the number of "components" in this buffer, that are readable. These are the components that would be
1041      * processed by {@link #forEachReadable(int, ReadableComponentProcessor)}. For composite buffers, this is the
1042      * number of transitive constituent buffers that are readable, while non-composite buffers only have at most one
1043      * readable component.
1044      * <p>
1045      * The number of readable components may be less than the {@link #countComponents() component count}, if not all of
1046      * them have readable data.
1047      *
1048      * @return The number of readable components in this buffer.
1049      */
1050     int countReadableComponents();
1051 
1052     /**
1053      * Get the number of "components" in this buffer, that are writable. These are the components that would be
1054      * processed by {@link #forEachWritable(int, WritableComponentProcessor)}. For composite buffers, this is the
1055      * number of transitive constituent buffers that are writable, while non-composite buffers only have at most one
1056      * writable component.
1057      * <p>
1058      * The number of writable components may be less than the {@link #countComponents() component count}, if not all of
1059      * them have space for writing.
1060      *
1061      * @return The number of writable components in this buffer.
1062      */
1063     int countWritableComponents();
1064 
1065     /**
1066      * Processes all readable components of this buffer, and return the number of components processed.
1067      * <p>
1068      * The given {@linkplain ReadableComponentProcessor processor} is called for each readable component in this buffer,
1069      * and passed a component index, for the given component in the iteration, and a {@link ReadableComponent} object
1070      * for accessing the data within the given component.
1071      * <p>
1072      * The component index is specific to the particular invocation of this method. The first call to the consumer will
1073      * be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
1074      * <p>
1075      * The {@linkplain ReadableComponentProcessor component processor} may stop the iteration at any time by returning
1076      * {@code false}.
1077      * This will cause the number of components processed to be returned as a negative number (to signal early return),
1078      * and the number of components processed may then be less than the
1079      * {@linkplain #countReadableComponents() readable component count}.
1080      * <p>
1081      * <strong>Note</strong> that the {@link ReadableComponent} instance passed to the consumer could be reused for
1082      * multiple calls, so the data must be extracted from the component in the context of the iteration.
1083      * <p>
1084      * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
1085      * This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
1086      * such changes are {@link #split(int)}, {@link #split()}, {@link #readSplit(int)}, {@link #writeSplit(int)},
1087      * {@link #compact()}, {@link #ensureWritable(int)}, {@link #ensureWritable(int, int, boolean)},
1088      * and {@link #send()}.
1089      * <p>
1090      * The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
1091      * <p>
1092      * <strong>Note</strong> that the arrays, memory addresses, and byte buffers exposed as components by this method,
1093      * should not be used for changing the buffer contents. Doing so may cause undefined behaviour.
1094      * <p>
1095      * Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to
1096      * this buffer instance.
1097      *
1098      * @param initialIndex The initial index of the component for iteration, and the index that will be passed to the
1099      * first call to the {@linkplain ReadableComponentProcessor#process(int, ReadableComponent) processor}.
1100      * @param processor The processor that will be used to process the buffer components.
1101      * @return The number of readable components processed, as a positive number if all readable components were
1102      * processed, or as a negative number if the iteration was stopped because
1103      * {@link ReadableComponentProcessor#process(int, ReadableComponent)} returned {@code false}.
1104      * In any case, the number of components processed may be less than {@link #countComponents()}.
1105      */
1106     <E extends Exception> int forEachReadable(int initialIndex, ReadableComponentProcessor<E> processor) throws E;
1107 
1108     /**
1109      * Create a {@linkplain ComponentIterator component iterator} for all readable components in this buffer.
1110      * <p>
1111      * Unlike the {@link #forEachReadable(int, ReadableComponentProcessor)} method, this API permits <em>external</em>
1112      * iteration of the components, while at the same time protecting the life-cycle of the buffer.
1113      * <p>
1114      * The typical code pattern for using this API looks like the following:
1115      * <pre>{@code
1116      *      try (var iteration = buffer.forEachReadable()) {
1117      *          for (var c = iteration.first(); c != null; c = c.next()) {
1118      *              ByteBuffer componentBuffer = c.readableBuffer();
1119      *              // ...
1120      *          }
1121      *      }
1122      * }</pre>
1123      * Note the use of the {@code var} keyword for local variables, which are required for correctly expressing the
1124      * generic types used in the iteration.
1125      * Following this code pattern will ensure that the components, and their parent buffer, will be correctly
1126      * life-cycled.
1127      * <p>
1128      * <strong>Note</strong> that the {@link ReadableComponent} instances exposed by the iterator could be reused for
1129      * multiple calls, so the data must be extracted from the component in the context of the iteration.
1130      * <p>
1131      * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
1132      * This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
1133      * such changes are {@link #split(int)}, {@link #split()}, {@link #readSplit(int)}, {@link #writeSplit(int)},
1134      * {@link #compact()}, {@link #ensureWritable(int)}, {@link #ensureWritable(int, int, boolean)},
1135      * and {@link #send()}.
1136      * <p>
1137      * The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
1138      * <p>
1139      * <strong>Note</strong> that the arrays, memory addresses, and byte buffers exposed as components by this method,
1140      * should not be used for changing the buffer contents. Doing so may cause undefined behaviour.
1141      * <p>
1142      * Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to
1143      * this buffer instance.
1144      *
1145      * @return A component iterator of {@linkplain ReadableComponent readable components}.
1146      * @param <T> An intersection type that presents both the {@link ReadableComponent} interface,
1147      *          <em>and</em> the ability to progress the iteration via the {@link Next#next()} method.
1148      */
1149     <T extends ReadableComponent & ComponentIterator.Next> ComponentIterator<T> forEachReadable();
1150 
1151     /**
1152      * Process all writable components of this buffer, and return the number of components processed.
1153      * <p>
1154      * The given {@linkplain WritableComponentProcessor processor} is called for each writable component in this buffer,
1155      * and passed a component index, for the given component in the iteration, and a {@link WritableComponent} object
1156      * for accessing the data within the given component.
1157      * <p>
1158      * The component index is specific to the particular invocation of this method. The first call to the consumer will
1159      * be passed the given initial index, and the next call will be passed the initial index plus one, and so on.
1160      * <p>
1161      * The {@link WritableComponentProcessor component processor} may stop the iteration at any time by returning
1162      * {@code false}.
1163      * This will cause the number of components processed to be returned as a negative number (to signal early return),
1164      * and the number of components processed may then be less than the
1165      * {@linkplain #countReadableComponents() readable component count}.
1166      * <p>
1167      * <strong>Note</strong> that the {@link WritableComponent} instance passed to the consumer could be reused for
1168      * multiple calls, so the data must be extracted from the component in the context of the iteration.
1169      * <p>
1170      * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
1171      * This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
1172      * such changes are {@link #split(int)}, {@link #split()}, {@link #readSplit(int)}, {@link #writeSplit(int)},
1173      * {@link #compact()}, {@link #ensureWritable(int)}, {@link #ensureWritable(int, int, boolean)},
1174      * and {@link #send()}.
1175      * <p>
1176      * The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
1177      * <p>
1178      * Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to
1179      * this buffer instance.
1180      *
1181      * @param initialIndex The initial index of the component for iteration, and the index that will be passed to the
1182      * first call to the {@linkplain WritableComponentProcessor#process(int, WritableComponent) processor}.
1183      * @param processor The processor that will be used to process the buffer components.
1184      * @return The number of writable components processed, as a positive number if all writable components were
1185      * processed, or as a negative number if the iteration was stopped because
1186      * {@link WritableComponentProcessor#process(int, WritableComponent)} returned {@code false}.
1187      * In any case, the number of components processed may be less than {@link #countComponents()}.
1188      */
1189     <E extends Exception> int forEachWritable(int initialIndex, WritableComponentProcessor<E> processor) throws E;
1190 
1191     /**
1192      * Create a {@linkplain ComponentIterator component iterator} for all writable components in this buffer.
1193      * <p>
1194      * Unlike the {@link #forEachWritable(int, WritableComponentProcessor)} method, this API permits <em>external</em>
1195      * iteration of the components, while at the same time protecting the life-cycle of the buffer.
1196      * <p>
1197      * The typical code pattern for using this API looks like the following:
1198      * <pre>{@code
1199      *      try (var iteration = buffer.forEachWritable()) {
1200      *          for (var c = iteration.first(); c != null; c = c.next()) {
1201      *              ByteBuffer componentBuffer = c.writableBuffer();
1202      *              // ...
1203      *          }
1204      *      }
1205      * }</pre>
1206      * Note the use of the {@code var} keyword for local variables, which are required for correctly expressing the
1207      * generic types used in the iteration.
1208      * Following this code pattern will ensure that the components, and their parent buffer, will be correctly
1209      * life-cycled.
1210      * <p>
1211      * <strong>Note</strong> that the {@link WritableComponent} instances exposed by the iterator could be reused for
1212      * multiple calls, so the data must be extracted from the component in the context of the iteration.
1213      * <p>
1214      * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
1215      * This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
1216      * such changes are {@link #split(int)}, {@link #split()}, {@link #readSplit(int)}, {@link #writeSplit(int)},
1217      * {@link #compact()}, {@link #ensureWritable(int)}, {@link #ensureWritable(int, int, boolean)},
1218      * and {@link #send()}.
1219      * <p>
1220      * The best way to ensure this doesn't cause any trouble, is to use the buffers directly as part of the iteration.
1221      * <p>
1222      * <strong>Note</strong> that the arrays, memory addresses, and byte buffers exposed as components by this method,
1223      * should not be used for changing the buffer contents beyond the respective array offset and length,
1224      * or buffer position and limit. Doing so may cause undefined behaviour.
1225      * <p>
1226      * Changes to position and limit of the byte buffers exposed via the processed components, are not reflected back to
1227      * this buffer instance.
1228      *
1229      * @return A component iterator of {@linkplain ReadableComponent readable components}.
1230      * @param <T> An intersection type that presents both the {@link ReadableComponent} interface,
1231      *          <em>and</em> the ability to progress the iteration via the {@link Next#next()} method.
1232      */
1233     <T extends WritableComponent & ComponentIterator.Next> ComponentIterator<T> forEachWritable();
1234 
1235     /**
1236      * Decodes this buffer's readable bytes into a string with the specified {@linkplain Charset}.
1237      * <p>
1238      * This method does not modify the reader or writer offset of this buffer.
1239      *
1240      * @param charset used for decoding.
1241      * @return Buffer's readable bytes as a string.
1242      */
1243     default String toString(Charset charset) {
1244         return Statics.toString(this, charset);
1245     }
1246 }