diff --git a/src/main/java/io/netty/buffer/api/Buffer.java b/src/main/java/io/netty/buffer/api/Buffer.java
index bdf8346..759c3ee 100644
--- a/src/main/java/io/netty/buffer/api/Buffer.java
+++ b/src/main/java/io/netty/buffer/api/Buffer.java
@@ -37,7 +37,7 @@ import java.nio.ByteOrder;
* When the buffer is initially allocated, a pairing {@link #close()} call will deallocate it.
* In this state, the buffer {@linkplain #isOwned() is "owned"}.
*
- * The buffer can also be {@linkplain #acquire() acquired} when it's about to be involved in a complicated life time.
+ * The buffer can also be {@linkplain #acquire() acquired} when it's about to be involved in a complicated lifetime.
* The {@link #acquire()} call increments the reference count of the buffer,
* and a pairing {@link #close()} call will decrement the reference count.
* Each acquire lends out the buffer, and the buffer is said to be in a "borrowed" state.
@@ -58,14 +58,15 @@ import java.nio.ByteOrder;
* then the ownership of that buffer must be sent to that thread.
* This can be done with the {@link #send()} method.
* The send method consumes the buffer, if it is in an owned state, and produces a {@link Send} object.
- * The {@link Send} object can then be shared in a thread-safe way (so called "safe publication"),
+ * The {@link Send} object can then be shared in a thread-safe way (so-called "safe publication"),
* with the intended recipient thread.
*
* To send a buffer to another thread, the buffer must not have any outstanding borrows.
* That is to say, all {@linkplain #acquire() acquires} must have been paired with a {@link #close()};
* all {@linkplain #slice() slices} must have been closed.
- * And if this buffer is a constituent of a {@linkplain Buffer#compose(BufferAllocator, Buffer...) composite buffer},
- * then that composite buffer must be closed.
+ * And if this buffer is a constituent of a
+ * {@linkplain CompositeBuffer#compose(BufferAllocator, Buffer...) composite buffer}, then that composite buffer must
+ * be closed.
* And if this buffer is itself a composite buffer, then it must own all of its constituent buffers.
* The {@link #isOwned()} method can be used on any buffer to check if it can be sent or not.
*
@@ -79,7 +80,7 @@ import java.nio.ByteOrder;
*
, BufferAccessors {
- /**
- * Compose the given sequence of buffers and present them as a single buffer.
- *
- * Note: The composite buffer increments the reference count on all the constituent buffers,
- * and holds a reference to them until the composite buffer is deallocated.
- * This means the constituent buffers must still have their outside-reference count decremented as normal.
- * If the buffers are allocated for the purpose of participating in the composite buffer,
- * then they should be closed as soon as the composite buffer has been created, like in this example:
- *
{@code
- * try (Buffer a = allocator.allocate(size);
- * Buffer b = allocator.allocate(size)) {
- * return allocator.compose(a, b); // Reference counts for 'a' and 'b' incremented here.
- * } // Reference count for 'a' and 'b' decremented here; composite buffer now holds the last references.
- * }
- *
- * {@linkplain Buffer#send() Sending} a composite buffer implies sending all of its constituent buffers.
- * For sending to be possible, both the composite buffer itself, and all of its constituent buffers, must be in an
- * {@linkplain Rc#isOwned() owned state}.
- * This means that the composite buffer must be the only reference to the constituent buffers.
- *
- * All of the constituent buffers must have the same {@linkplain Buffer#order() byte order}.
- * An exception will be thrown if you attempt to compose buffers that have different byte orders,
- * and changing the byte order of the constituent buffers so they become inconsistent after construction,
- * will result in unspecified behaviour.
- *
- * The read and write offsets of the constituent buffers must be arranged such that there are no "gaps" when viewed
- * as a single connected chunk of memory.
- * Specifically, there can be at most one buffer whose write offset is neither zero nor at capacity,
- * and all buffers prior to it must have their write offsets at capacity, and all buffers after it must have a write
- * offset of zero.
- * Likewise, there can be at most one buffer whose read offset is neither zero nor at capacity,
- * and all buffers prior to it must have their read offsets at capacity, and all buffers after it must have a read
- * offset of zero.
- * Furthermore, the sum of the read offsets must be less than or equal to the sum of the write offsets.
- *
- * Reads and writes to the composite buffer that modifies the read or write offsets, will also modify the relevant
- * offsets in the constituent buffers.
- *
- * It is not a requirement that the buffers have the same size.
- *
- * It is not a requirement that the buffers are allocated by this allocator, but if
- * {@link Buffer#ensureWritable(int)} is called on the composed buffer, and the composed buffer needs to be
- * expanded, then this allocator instance will be used for allocation the extra memory.
- *
- * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
- * {@link #ensureWritable(int)} calls.
- * @param bufs The buffers to compose into a single buffer view.
- * @return A buffer composed of, and backed by, the given buffers.
- * @throws IllegalArgumentException if the given buffers have an inconsistent
- * {@linkplain Buffer#order() byte order}.
- */
- static Buffer compose(BufferAllocator allocator, Buffer... bufs) {
- return new CompositeBuffer(allocator, bufs);
- }
-
- /**
- * Compose the given sequence of sends of buffers and present them as a single buffer.
- *
- * Note: The composite buffer holds a reference to all the constituent buffers,
- * until the composite buffer is deallocated.
- * This means the constituent buffers must still have their outside-reference count decremented as normal.
- * If the buffers are allocated for the purpose of participating in the composite buffer,
- * then they should be closed as soon as the composite buffer has been created, like in this example:
- *
{@code
- * try (Buffer a = allocator.allocate(size);
- * Buffer b = allocator.allocate(size)) {
- * return allocator.compose(a, b); // Reference counts for 'a' and 'b' incremented here.
- * } // Reference count for 'a' and 'b' decremented here; composite buffer now holds the last references.
- * }
- *
- * {@linkplain Buffer#send() Sending} a composite buffer implies sending all of its constituent buffers.
- * For sending to be possible, both the composite buffer itself, and all of its constituent buffers, must be in an
- * {@linkplain Rc#isOwned() owned state}.
- * This means that the composite buffer must be the only reference to the constituent buffers.
- *
- * All of the constituent buffers must have the same {@linkplain Buffer#order() byte order}.
- * An exception will be thrown if you attempt to compose buffers that have different byte orders,
- * and changing the byte order of the constituent buffers so they become inconsistent after construction,
- * will result in unspecified behaviour.
- *
- * The read and write offsets of the constituent buffers must be arranged such that there are no "gaps" when viewed
- * as a single connected chunk of memory.
- * Specifically, there can be at most one buffer whose write offset is neither zero nor at capacity,
- * and all buffers prior to it must have their write offsets at capacity, and all buffers after it must have a write
- * offset of zero.
- * Likewise, there can be at most one buffer whose read offset is neither zero nor at capacity,
- * and all buffers prior to it must have their read offsets at capacity, and all buffers after it must have a read
- * offset of zero.
- * Furthermore, the sum of the read offsets must be less than or equal to the sum of the write offsets.
- *
- * Reads and writes to the composite buffer that modifies the read or write offsets, will also modify the relevant
- * offsets in the constituent buffers.
- *
- * It is not a requirement that the buffers have the same size.
- *
- * It is not a requirement that the buffers are allocated by this allocator, but if
- * {@link Buffer#ensureWritable(int)} is called on the composed buffer, and the composed buffer needs to be
- * expanded, then this allocator instance will be used for allocation the extra memory.
- *
- * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
- * {@link #ensureWritable(int)} calls.
- * @param sends The sent buffers to compose into a single buffer view.
- * @return A buffer composed of, and backed by, the given buffers.
- * @throws IllegalArgumentException if the given buffers have an inconsistent
- * {@linkplain Buffer#order() byte order}.
- */
- @SafeVarargs
- static Buffer compose(BufferAllocator allocator, Send... sends) {
- return new CompositeBuffer(allocator, sends);
- }
-
- /**
- * Create an empty composite buffer, that has no components. The buffer can be extended with components using either
- * {@link #ensureWritable(int)} or {@link #extendComposite(Buffer, Buffer)}.
- *
- * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
- * {@link #ensureWritable(int)} calls.
- * @return A composite buffer that has no components, and has a capacity of zero.
- */
- static Buffer compose(BufferAllocator allocator) {
- return new CompositeBuffer(allocator, new Buffer[0]);
- }
-
- /**
- * Extend the given composite buffer with the given extension buffer.
- * This works as if the extension had originally been included at the end of the list of constituent buffers when
- * the composite buffer was created.
- * The composite buffer is modified in-place.
- *
- * @see #compose(BufferAllocator, Buffer...)
- * @see #compose(BufferAllocator, Send...)
- * @param composite The composite buffer (from a prior {@link #compose(BufferAllocator, Buffer...)} call) to extend
- * with the given extension buffer.
- * @param extension The buffer to extend the composite buffer with.
- */
- static void extendComposite(Buffer composite, Buffer extension) {
- if (!isComposite(composite)) {
- throw new IllegalArgumentException(
- "Expected the first buffer to be a composite buffer, " +
- "but it is a " + composite.getClass() + " buffer: " + composite + '.');
- }
- CompositeBuffer compositeBuffer = (CompositeBuffer) composite;
- compositeBuffer.extendWith(extension);
- }
-
- /**
- * Check if the given buffer is a {@linkplain #compose(BufferAllocator, Buffer...) composite} buffer or not.
- * @param composite The buffer to check.
- * @return {@code true} if the given buffer was created with {@link #compose(BufferAllocator, Buffer...)},
- * {@code false} otherwise.
- */
- static boolean isComposite(Buffer composite) {
- return composite.getClass() == CompositeBuffer.class;
- }
-
/**
* Change the default byte order of this buffer, and return this buffer.
*
@@ -399,7 +245,7 @@ public interface Buffer extends Rc, BufferAccessors {
* @param length The number of bytes to copy.
* @throws NullPointerException if the destination array is null.
* @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
- * or if the resulting end positions reaches beyond the end of either this buffer or the destination array.
+ * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
*/
void copyInto(int srcPos, byte[] dest, int destPos, int length);
@@ -420,7 +266,7 @@ public interface Buffer extends Rc, BufferAccessors {
* @param length The number of bytes to copy.
* @throws NullPointerException if the destination array is null.
* @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
- * or if the resulting end positions reaches beyond the end of either this buffer or the destination array.
+ * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
*/
void copyInto(int srcPos, ByteBuffer dest, int destPos, int length);
@@ -441,7 +287,7 @@ public interface Buffer extends Rc, BufferAccessors {
* @param length The number of bytes to copy.
* @throws NullPointerException if the destination array is null.
* @throws IndexOutOfBoundsException if the source or destination positions, or the length, are negative,
- * or if the resulting end positions reaches beyond the end of either this buffer or the destination array.
+ * or if the resulting end positions reaches beyond the end of either this buffer, or the destination array.
*/
void copyInto(int srcPos, Buffer dest, int destPos, int length);
@@ -476,9 +322,9 @@ public interface Buffer extends Rc, BufferAccessors {
* Open a cursor to iterate the readable bytes of this buffer. The {@linkplain #readerOffset() reader offset} and
* {@linkplain #writerOffset() witer offset} are not modified by the cursor.
*
- * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
+ * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
- * while the iteration takes place. Otherwise unpredictable behaviour might result.
+ * while the iteration takes place. Otherwise, unpredictable behaviour might result.
*
* @return A {@link ByteCursor} for iterating the readable bytes of this buffer.
*/
@@ -489,16 +335,16 @@ public interface Buffer extends Rc, BufferAccessors {
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
* the cursor.
*
- * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
+ * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
- * while the iteration takes place. Otherwise unpredictable behaviour might result.
+ * while the iteration takes place. Otherwise, unpredictable behaviour might result.
*
* @param fromOffset The offset into the buffer where iteration should start.
* The first byte read from the iterator will be the byte at this offset.
* @param length The number of bytes to iterate.
* @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
* @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
- * the {@code length} reaches outside of the bounds of this buffer.
+ * the {@code length} reaches outside the bounds of this buffer.
*/
ByteCursor openCursor(int fromOffset, int length);
@@ -507,9 +353,9 @@ public interface Buffer extends Rc, BufferAccessors {
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
* the cursor.
*
- * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
+ * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
- * while the iteration takes place. Otherwise unpredictable behaviour might result.
+ * while the iteration takes place. Otherwise, unpredictable behaviour might result.
*
* @return A {@link ByteCursor} for the readable bytes of this buffer.
*/
@@ -523,16 +369,16 @@ public interface Buffer extends Rc, BufferAccessors {
* The {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() witer offset} are not modified by
* the cursor.
*
- * Care should be taken to ensure that the buffers lifetime extends beyond the cursor and the iteration, and that
+ * Care should be taken to ensure that the buffer's lifetime extends beyond the cursor and the iteration, and that
* the {@linkplain #readerOffset() reader offset} and {@linkplain #writerOffset() writer offset} are not modified
- * while the iteration takes place. Otherwise unpredictable behaviour might result.
+ * while the iteration takes place. Otherwise, unpredictable behaviour might result.
*
* @param fromOffset The offset into the buffer where iteration should start.
* The first byte read from the iterator will be the byte at this offset.
* @param length The number of bytes to iterate.
* @return A {@link ByteCursor} for the given stretch of bytes of this buffer.
* @throws IllegalArgumentException if the length is negative, or if the region given by the {@code fromOffset} and
- * the {@code length} reaches outside of the bounds of this buffer.
+ * the {@code length} reaches outside the bounds of this buffer.
*/
ByteCursor openReverseCursor(int fromOffset, int length);
@@ -648,7 +494,7 @@ public interface Buffer extends Rc, BufferAccessors {
* {@linkplain #send() sent} to other threads.
*
* The returned buffer will adopt the {@link #readerOffset()} of this buffer, and have its {@link #writerOffset()}
- * and {@link #capacity()} both set to the equal to the write offset of this buffer.
+ * and {@link #capacity()} both set to the equal to the write-offset of this buffer.
*
* The memory region in the returned buffer will become inaccessible through this buffer. This buffer will have its
* capacity reduced by the capacity of the returned buffer, and the read and write offsets of this buffer will both
@@ -672,7 +518,7 @@ public interface Buffer extends Rc, BufferAccessors {
* }
* When the buffers are in this state, both of the bifurcated parts retain an atomic reference count on the
* underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
- * all of the bifurcated parts have been closed.
+ * all the bifurcated parts have been closed.
*
* Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
* bifurcated. If the split point lands perfectly between two constituent buffers, then a composite buffer can
@@ -703,7 +549,7 @@ public interface Buffer extends Rc, BufferAccessors {
*
* The memory region in the returned buffer will become inaccessible through this buffer. If the
* {@link #readerOffset()} or {@link #writerOffset()} of this buffer lie prior to the {@code splitOffset},
- * then those offsets will be moved forward so they land on offset 0 after the bifurcation.
+ * then those offsets will be moved forward, so they land on offset 0 after the bifurcation.
*
* Effectively, the following transformation takes place:
*
{@code
@@ -723,7 +569,7 @@ public interface Buffer extends Rc, BufferAccessors {
* }
* When the buffers are in this state, both of the bifurcated parts retain an atomic reference count on the
* underlying memory. This means that shared underlying memory will not be deallocated or returned to a pool, until
- * all of the bifurcated parts have been closed.
+ * all the bifurcated parts have been closed.
*
* Composite buffers have it a little easier, in that at most only one of the constituent buffers will actually be
* bifurcated. If the split point lands perfectly between two constituent buffers, then a composite buffer can
@@ -799,7 +645,7 @@ public interface Buffer extends Rc, BufferAccessors {
* Note that the {@link ReadableComponent} instance passed to the consumer could be reused for
* multiple calls, so the data must be extracted from the component in the context of the iteration.
*
- * The {@link ByteBuffer} instances obtained from the component, share life time with that internal component.
+ * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
* This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
* such changes, are any method that requires the buffer to be {@linkplain #isOwned() owned}.
*
@@ -841,7 +687,7 @@ public interface Buffer extends Rc, BufferAccessors {
* Note that the {@link WritableComponent} instance passed to the consumer could be reused for
* multiple calls, so the data must be extracted from the component in the context of the iteration.
*
- * The {@link ByteBuffer} instances obtained from the component, share life time with that internal component.
+ * The {@link ByteBuffer} instances obtained from the component, share lifetime with that internal component.
* This means they can be accessed as long as the internal memory store remain unchanged. Methods that may cause
* such changes, are any method that requires the buffer to be {@linkplain #isOwned() owned}.
*
diff --git a/src/main/java/io/netty/buffer/api/CompositeBuffer.java b/src/main/java/io/netty/buffer/api/CompositeBuffer.java
index f2e9164..9e3b4e4 100644
--- a/src/main/java/io/netty/buffer/api/CompositeBuffer.java
+++ b/src/main/java/io/netty/buffer/api/CompositeBuffer.java
@@ -24,7 +24,70 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
-final class CompositeBuffer extends RcSupport implements Buffer {
+/**
+ * The {@code CompositeBuffer} is a concrete {@link Buffer} implementation that make a number of other buffers appear
+ * as one. A composite buffer behaves the same as a normal, non-composite buffer in every way, so you normally don't
+ * need to handle them specially.
+ *
+ * A composite buffer is constructed using one of the {@code compose} methods:
+ *
+ * -
+ * {@link #compose(BufferAllocator, Buffer...)} creates a composite buffer from the given set of buffers.
+ * The reference count to the passed buffers will be increased, and the resulting composite buffer may or may
+ * not have ownership.
+ *
+ * -
+ * {@link #compose(BufferAllocator, Send[])} creates a composite buffer from the buffers that are sent to it via
+ * the passed in send objects. Since {@link Send#receive()} transfers ownership, the resulting composite buffer
+ * will have ownership, because it is guaranteed that there are no other references to its constituent buffers.
+ *
+ * -
+ * {@link #compose(BufferAllocator)} creates and empty, zero capacity, composite buffer. Such empty buffers may
+ * change their {@linkplain #order() byte order} or {@linkplain #readOnly() read-only} states when they gain
+ * their first component.
+ *
+ *
+ * Composite buffers can later be extended with internally allocated components, with {@link #ensureWritable(int)},
+ * or with externally allocated buffers, using {@link #extendComposite(Buffer, Buffer)}.
+ *
+ * Constituent buffer requirements
+ *
+ * The buffers that a being composed to form the composite buffer, need to live up to a number of requirements.
+ * Basically, if we imagine that the constituent buffers have their memory regions concatenated together, then the
+ * result needs to make sense.
+ *
+ * All the constituent buffers must have the same {@linkplain Buffer#order() byte order}.
+ * An exception will be thrown if you attempt to compose buffers that have different byte orders,
+ * and changing the byte order of the constituent buffers so that they become inconsistent after construction,
+ * will result in unspecified behaviour.
+ *
+ * The read and write offsets of the constituent buffers must be arranged such that there are no "gaps" when viewed
+ * as a single connected chunk of memory.
+ * Specifically, there can be at most one buffer whose write offset is neither zero nor at capacity,
+ * and all buffers prior to it must have their write offsets at capacity, and all buffers after it must have a
+ * write-offset of zero.
+ * Likewise, there can be at most one buffer whose read offset is neither zero nor at capacity,
+ * and all buffers prior to it must have their read offsets at capacity, and all buffers after it must have a read
+ * offset of zero.
+ * Furthermore, the sum of the read offsets must be less than or equal to the sum of the write-offsets.
+ *
+ * Reads and writes to the composite buffer that modifies the read or write offsets, will also modify the relevant
+ * offsets in the constituent buffers.
+ *
+ * It is not a requirement that the buffers have the same size.
+ *
+ * It is not a requirement that the buffers are allocated by this allocator, but if
+ * {@link Buffer#ensureWritable(int)} is called on the composed buffer, and the composed buffer needs to be
+ * expanded, then this allocator instance will be used for allocation the extra memory.
+ *
+ *
Ownership and Send
+ *
+ * {@linkplain Buffer#send() Sending} a composite buffer implies sending all of its constituent buffers.
+ * For sending to be possible, both the composite buffer itself, and all of its constituent buffers, must be in an
+ * {@linkplain Rc#isOwned() owned state}.
+ * This means that the composite buffer must be the only reference to the constituent buffers.
+ */
+public final class CompositeBuffer extends RcSupport implements Buffer {
/**
* The max array size is JVM implementation dependant, but most seem to settle on {@code Integer.MAX_VALUE - 8}.
* We set the max composite buffer capacity to the same, since it would otherwise be impossible to create a
@@ -45,6 +108,7 @@ final class CompositeBuffer extends RcSupport implement
return "COMPOSITE_DROP";
}
};
+ private static final Buffer[] EMPTY_BUFFER_ARRAY = new Buffer[0];
private final BufferAllocator allocator;
private final TornBufferAccessors tornBufAccessors;
@@ -58,14 +122,130 @@ final class CompositeBuffer extends RcSupport implement
private boolean closed;
private boolean readOnly;
- CompositeBuffer(BufferAllocator allocator, Buffer[] refs) {
- this(allocator, filterExternalBufs(Arrays.stream(refs)
- .map(buf -> buf.acquire() /* Increments reference counts. */)), COMPOSITE_DROP, false);
+ /**
+ * Compose the given sequence of buffers and present them as a single buffer.
+ *
+ * Note: The composite buffer increments the reference count on all the constituent buffers,
+ * and holds a reference to them until the composite buffer is deallocated.
+ * This means the constituent buffers must still have their outside-reference count decremented as normal.
+ * If the buffers are allocated for the purpose of participating in the composite buffer,
+ * then they should be closed as soon as the composite buffer has been created, like in this example:
+ *
{@code
+ * try (Buffer a = allocator.allocate(size);
+ * Buffer b = allocator.allocate(size)) {
+ * return allocator.compose(a, b); // Reference counts for 'a' and 'b' incremented here.
+ * } // Reference count for 'a' and 'b' decremented here; composite buffer now holds the last references.
+ * }
+ *
+ * See the class documentation for more information on what is required of the given buffers for composition to be
+ * allowed.
+ *
+ * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
+ * {@link #ensureWritable(int)} calls.
+ * @param bufs The buffers to compose into a single buffer view.
+ * @return A buffer composed of, and backed by, the given buffers.
+ * @throws IllegalArgumentException if the given buffers have an inconsistent
+ * {@linkplain Buffer#order() byte order}.
+ */
+ public static Buffer compose(BufferAllocator allocator, Buffer... bufs) {
+ Stream bufferStream = Arrays.stream(bufs)
+ .map(buf -> buf.acquire()); // Increments reference counts.
+ return new CompositeBuffer(allocator, filterExternalBufs(bufferStream), COMPOSITE_DROP, false);
}
- CompositeBuffer(BufferAllocator allocator, Send[] refs) {
- this(allocator, filterExternalBufs(Arrays.stream(refs)
- .map(buf -> buf.receive())), COMPOSITE_DROP, false);
+ /**
+ * Compose the given sequence of sends of buffers and present them as a single buffer.
+ *
+ * Note: The composite buffer holds a reference to all the constituent buffers,
+ * until the composite buffer is deallocated.
+ * This means the constituent buffers must still have their outside-reference count decremented as normal.
+ * If the buffers are allocated for the purpose of participating in the composite buffer,
+ * then they should be closed as soon as the composite buffer has been created, like in this example:
+ *
{@code
+ * try (Buffer a = allocator.allocate(size);
+ * Buffer b = allocator.allocate(size)) {
+ * return allocator.compose(a, b); // Reference counts for 'a' and 'b' incremented here.
+ * } // Reference count for 'a' and 'b' decremented here; composite buffer now holds the last references.
+ * }
+ *
+ * See the class documentation for more information on what is required of the given buffers for composition to be
+ * allowed.
+ *
+ * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
+ * {@link #ensureWritable(int)} calls.
+ * @param sends The sent buffers to compose into a single buffer view.
+ * @return A buffer composed of, and backed by, the given buffers.
+ * @throws IllegalArgumentException if the given buffers have an inconsistent
+ * {@linkplain Buffer#order() byte order}.
+ * @throws IllegalStateException if one of the sends have already been received. The remaining buffers and sends
+ * will be closed and descarded, respectively.
+ */
+ @SafeVarargs
+ public static Buffer compose(BufferAllocator allocator, Send... sends) {
+ Buffer[] bufs = new Buffer[sends.length];
+ IllegalStateException ise = null;
+ for (int i = 0; i < sends.length; i++) {
+ if (ise != null) {
+ sends[i].discard();
+ } else {
+ try {
+ bufs[i] = sends[i].receive();
+ } catch (IllegalStateException e) {
+ ise = e;
+ for (int j = 0; j < i; j++) {
+ bufs[j].close();
+ }
+ }
+ }
+ }
+ if (ise != null) {
+ throw ise;
+ }
+ return compose(allocator, bufs);
+ }
+
+ /**
+ * Create an empty composite buffer, that has no components. The buffer can be extended with components using either
+ * {@link #ensureWritable(int)} or {@link #extendComposite(Buffer, Buffer)}.
+ *
+ * @param allocator The allocator for the composite buffer. This allocator will be used e.g. to service
+ * {@link #ensureWritable(int)} calls.
+ * @return A composite buffer that has no components, and has a capacity of zero.
+ */
+ public static Buffer compose(BufferAllocator allocator) {
+ return new CompositeBuffer(allocator, EMPTY_BUFFER_ARRAY, COMPOSITE_DROP, false);
+ }
+
+ /**
+ * Extend the given composite buffer with the given extension buffer.
+ * This works as if the extension had originally been included at the end of the list of constituent buffers when
+ * the composite buffer was created.
+ * The composite buffer is modified in-place.
+ *
+ * @see #compose(BufferAllocator, Buffer...)
+ * @see #compose(BufferAllocator, Send...)
+ * @param composite The composite buffer (from a prior {@link #compose(BufferAllocator, Buffer...)} call) to extend
+ * with the given extension buffer.
+ * @param extension The buffer to extend the composite buffer with.
+ */
+ public static void extendComposite(Buffer composite, Buffer extension) {
+ if (!isComposite(composite)) {
+ throw new IllegalArgumentException(
+ "Expected the first buffer to be a composite buffer, " +
+ "but it is a " + composite.getClass() + " buffer: " + composite + '.');
+ }
+ CompositeBuffer compositeBuffer = (CompositeBuffer) composite;
+ compositeBuffer.extendWith(extension);
+ }
+
+ /**
+ * Check if the given buffer is a {@linkplain #compose(BufferAllocator, Buffer...) composite} buffer or not.
+ * @param composite The buffer to check.
+ * @return {@code true} if the given buffer was created with {@link #compose(BufferAllocator, Buffer...)},
+ * {@code false} otherwise.
+ */
+ public static boolean isComposite(Buffer composite) {
+ return composite.getClass() == CompositeBuffer.class;
}
private static Buffer[] filterExternalBufs(Stream refs) {
@@ -706,7 +886,7 @@ final class CompositeBuffer extends RcSupport implement
Buffer[] restoreTemp = bufs; // We need this to restore our buffer array, in case offset computations fail.
try {
if (extension instanceof CompositeBuffer) {
- // If the extension is itself a composite buffer, then extend this one by all of the constituent
+ // If the extension is itself a composite buffer, then extend this one by all the constituent
// component buffers.
CompositeBuffer compositeExtension = (CompositeBuffer) extension;
Buffer[] addedBuffers = compositeExtension.bufs;
diff --git a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java
index 739b73e..6a0d588 100644
--- a/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferBulkAccessTest.java
@@ -115,7 +115,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return Buffer.compose(a, bufFirst, bufSecond);
+ return CompositeBuffer.compose(a, bufFirst, bufSecond);
}
});
}
@@ -131,7 +131,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return Buffer.compose(a, bufFirst, bufSecond);
+ return CompositeBuffer.compose(a, bufFirst, bufSecond);
}
});
}
@@ -147,7 +147,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return Buffer.compose(a, bufFirst, bufSecond);
+ return CompositeBuffer.compose(a, bufFirst, bufSecond);
}
});
}
@@ -163,7 +163,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return Buffer.compose(a, bufFirst, bufSecond);
+ return CompositeBuffer.compose(a, bufFirst, bufSecond);
}
});
}
@@ -180,7 +180,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return scope.add(Buffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
+ return scope.add(CompositeBuffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
}
});
}
@@ -197,7 +197,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return scope.add(Buffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
+ return scope.add(CompositeBuffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
}
});
}
@@ -214,7 +214,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return scope.add(Buffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
+ return scope.add(CompositeBuffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
}
});
}
@@ -231,7 +231,7 @@ public class BufferBulkAccessTest extends BufferTestSupport {
int second = size - first;
try (var bufFirst = a.allocate(first);
var bufSecond = b.allocate(second)) {
- return scope.add(Buffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
+ return scope.add(CompositeBuffer.compose(a, bufFirst, bufSecond)).writerOffset(size).slice();
}
});
}
diff --git a/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java b/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java
index 2189169..030e9f2 100644
--- a/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferComponentIterationTest.java
@@ -69,8 +69,8 @@ public class BufferComponentIterationTest extends BufferTestSupport {
try (Buffer a = allocator.allocate(8);
Buffer b = allocator.allocate(8);
Buffer c = allocator.allocate(8);
- Buffer x = Buffer.compose(allocator, b, c)) {
- buf = Buffer.compose(allocator, a, x);
+ Buffer x = CompositeBuffer.compose(allocator, b, c)) {
+ buf = CompositeBuffer.compose(allocator, a, x);
}
assertThat(buf.countComponents()).isEqualTo(3);
assertThat(buf.countReadableComponents()).isZero();
@@ -122,7 +122,7 @@ public class BufferComponentIterationTest extends BufferTestSupport {
a.writeInt(1);
b.writeInt(2);
c.writeInt(3);
- composite = Buffer.compose(allocator, a, b, c);
+ composite = CompositeBuffer.compose(allocator, a, b, c);
}
var list = new LinkedList(List.of(1, 2, 3));
int count = composite.forEachReadable(0, (index, component) -> {
@@ -159,7 +159,7 @@ public class BufferComponentIterationTest extends BufferTestSupport {
a.writeInt(1);
b.writeInt(2);
c.writeInt(3);
- composite = Buffer.compose(allocator, a, b, c);
+ composite = CompositeBuffer.compose(allocator, a, b, c);
}
int readPos = composite.readerOffset();
int writePos = composite.writerOffset();
@@ -197,7 +197,7 @@ public class BufferComponentIterationTest extends BufferTestSupport {
try (Buffer a = allocator.allocate(4);
Buffer b = allocator.allocate(4);
Buffer c = allocator.allocate(4)) {
- buf = Buffer.compose(allocator, a, b, c);
+ buf = CompositeBuffer.compose(allocator, a, b, c);
}
int i = 1;
while (buf.writableBytes() > 0) {
@@ -269,7 +269,7 @@ public class BufferComponentIterationTest extends BufferTestSupport {
try (Buffer a = allocator.allocate(8);
Buffer b = allocator.allocate(8);
Buffer c = allocator.allocate(8)) {
- buf = Buffer.compose(allocator, a, b, c);
+ buf = CompositeBuffer.compose(allocator, a, b, c);
}
buf.order(BIG_ENDIAN);
buf.forEachWritable(0, (index, component) -> {
diff --git a/src/test/java/io/netty/buffer/api/BufferCompositionTest.java b/src/test/java/io/netty/buffer/api/BufferCompositionTest.java
index aa03120..365f72e 100644
--- a/src/test/java/io/netty/buffer/api/BufferCompositionTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferCompositionTest.java
@@ -40,7 +40,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (Buffer b = allocator.allocate(8)) {
assertTrue(a.isOwned());
assertTrue(b.isOwned());
- composite = Buffer.compose(allocator, a, b);
+ composite = CompositeBuffer.compose(allocator, a, b);
assertFalse(composite.isOwned());
assertFalse(a.isOwned());
assertFalse(b.isOwned());
@@ -58,13 +58,14 @@ public class BufferCompositionTest extends BufferTestSupport {
public void compositeBuffersCannotHaveDuplicateComponents() {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(4)) {
- var e = assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, a, a));
+ var e = assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, a));
assertThat(e).hasMessageContaining("duplicate");
- try (Buffer composite = Buffer.compose(allocator, a)) {
+ try (Buffer composite = CompositeBuffer.compose(allocator, a)) {
a.close();
try {
- e = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, a));
+ e = assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(composite, a));
assertThat(e).hasMessageContaining("duplicate");
} finally {
a.acquire();
@@ -76,7 +77,7 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void compositeBufferFromSends() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator,
+ Buffer composite = CompositeBuffer.compose(allocator,
allocator.allocate(8).send(),
allocator.allocate(8).send(),
allocator.allocate(8).send())) {
@@ -89,18 +90,19 @@ public class BufferCompositionTest extends BufferTestSupport {
public void compositeBufferMustNotBeAllowedToContainThemselves() {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer a = allocator.allocate(4);
- Buffer buf = Buffer.compose(allocator, a);
+ Buffer buf = CompositeBuffer.compose(allocator, a);
try (buf; a) {
a.close();
try {
- assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(buf, buf));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.extendComposite(buf, buf));
assertTrue(buf.isOwned());
- try (Buffer composite = Buffer.compose(allocator, buf)) {
+ try (Buffer composite = CompositeBuffer.compose(allocator, buf)) {
// the composing increments the reference count of constituent buffers...
// counter-act this so it can be extended:
a.close(); // buf is now owned so it can be extended.
try {
- assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(buf, composite));
+ assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(buf, composite));
} finally {
a.acquire(); // restore the reference count to align with our try-with-resources structure.
}
@@ -119,7 +121,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = fixture.createAllocator()) {
Buffer composite;
try (Buffer a = allocator.allocate(4, BIG_ENDIAN)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeInt(0x01020304);
@@ -136,7 +138,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = fixture.createAllocator()) {
Buffer composite;
try (Buffer a = allocator.allocate(4, LITTLE_ENDIAN)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeInt(0x05060708);
@@ -150,7 +152,7 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void emptyCompositeBufferMustUseNativeByteOrder() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator)) {
+ Buffer composite = CompositeBuffer.compose(allocator)) {
assertThat(composite.order()).isEqualTo(ByteOrder.nativeOrder());
}
}
@@ -160,7 +162,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(8);
Buffer b = allocator.allocate(8)) {
- var exc = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(a, b));
+ var exc = assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.extendComposite(a, b));
assertThat(exc).hasMessageContaining("Expected").hasMessageContaining("composite");
}
}
@@ -170,9 +172,9 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(8);
Buffer b = allocator.allocate(8);
- Buffer composed = Buffer.compose(allocator, a)) {
+ Buffer composed = CompositeBuffer.compose(allocator, a)) {
try (Buffer ignore = composed.acquire()) {
- var exc = assertThrows(IllegalStateException.class, () -> Buffer.extendComposite(composed, b));
+ var exc = assertThrows(IllegalStateException.class, () -> CompositeBuffer.extendComposite(composed, b));
assertThat(exc).hasMessageContaining("owned");
}
}
@@ -183,11 +185,11 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
var exc = assertThrows(IllegalArgumentException.class,
- () -> Buffer.extendComposite(composite, composite));
+ () -> CompositeBuffer.extendComposite(composite, composite));
assertThat(exc).hasMessageContaining("cannot be extended");
}
}
@@ -196,20 +198,20 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void extendingWithZeroCapacityBufferHasNoEffect() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator)) {
- Buffer.extendComposite(composite, composite);
+ Buffer composite = CompositeBuffer.compose(allocator)) {
+ CompositeBuffer.extendComposite(composite, composite);
assertThat(composite.capacity()).isZero();
assertThat(composite.countComponents()).isZero();
}
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer a = allocator.allocate(1);
- Buffer composite = Buffer.compose(allocator, a);
+ Buffer composite = CompositeBuffer.compose(allocator, a);
a.close();
assertTrue(composite.isOwned());
assertThat(composite.capacity()).isOne();
assertThat(composite.countComponents()).isOne();
- try (Buffer b = Buffer.compose(allocator)) {
- Buffer.extendComposite(composite, b);
+ try (Buffer b = CompositeBuffer.compose(allocator)) {
+ CompositeBuffer.extendComposite(composite, b);
}
assertTrue(composite.isOwned());
assertThat(composite.capacity()).isOne();
@@ -220,18 +222,18 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void extendingCompositeBufferWithNullMustThrow() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator)) {
- assertThrows(NullPointerException.class, () -> Buffer.extendComposite(composite, null));
+ Buffer composite = CompositeBuffer.compose(allocator)) {
+ assertThrows(NullPointerException.class, () -> CompositeBuffer.extendComposite(composite, null));
}
}
@Test
public void extendingCompositeBufferMustIncreaseCapacityByGivenBigEndianBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator)) {
+ Buffer composite = CompositeBuffer.compose(allocator)) {
assertThat(composite.capacity()).isZero();
try (Buffer buf = allocator.allocate(8, BIG_ENDIAN)) {
- Buffer.extendComposite(composite, buf);
+ CompositeBuffer.extendComposite(composite, buf);
}
assertThat(composite.capacity()).isEqualTo(8);
composite.writeLong(0x0102030405060708L);
@@ -242,10 +244,10 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void extendingCompositeBufferMustIncreaseCapacityByGivenLittleEndianBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer composite = Buffer.compose(allocator)) {
+ Buffer composite = CompositeBuffer.compose(allocator)) {
assertThat(composite.capacity()).isZero();
try (Buffer buf = allocator.allocate(8, LITTLE_ENDIAN)) {
- Buffer.extendComposite(composite, buf);
+ CompositeBuffer.extendComposite(composite, buf);
}
assertThat(composite.capacity()).isEqualTo(8);
composite.writeLong(0x0102030405060708L);
@@ -258,11 +260,12 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8, BIG_ENDIAN)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
try (Buffer b = allocator.allocate(8, LITTLE_ENDIAN)) {
- var exc = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ var exc = assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(composite, b));
assertThat(exc).hasMessageContaining("byte order");
}
}
@@ -274,11 +277,12 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8, LITTLE_ENDIAN)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
try (Buffer b = allocator.allocate(8, BIG_ENDIAN)) {
- var exc = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ var exc = assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(composite, b));
assertThat(exc).hasMessageContaining("byte order");
}
}
@@ -288,9 +292,9 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void emptyCompositeBufferMustAllowExtendingWithBufferWithBigEndianByteOrder() {
try (BufferAllocator allocator = BufferAllocator.heap()) {
- try (Buffer composite = Buffer.compose(allocator)) {
+ try (Buffer composite = CompositeBuffer.compose(allocator)) {
try (Buffer b = allocator.allocate(8, BIG_ENDIAN)) {
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.order()).isEqualTo(BIG_ENDIAN);
}
}
@@ -300,9 +304,9 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void emptyCompositeBufferMustAllowExtendingWithBufferWithLittleEndianByteOrder() {
try (BufferAllocator allocator = BufferAllocator.heap()) {
- try (Buffer composite = Buffer.compose(allocator)) {
+ try (Buffer composite = CompositeBuffer.compose(allocator)) {
try (Buffer b = allocator.allocate(8, LITTLE_ENDIAN)) {
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.order()).isEqualTo(LITTLE_ENDIAN);
}
}
@@ -312,9 +316,9 @@ public class BufferCompositionTest extends BufferTestSupport {
@Test
public void emptyCompositeBufferMustAllowExtendingWithReadOnlyBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap()) {
- try (Buffer composite = Buffer.compose(allocator)) {
+ try (Buffer composite = CompositeBuffer.compose(allocator)) {
try (Buffer b = allocator.allocate(8).readOnly(true)) {
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertTrue(composite.readOnly());
}
}
@@ -326,13 +330,13 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeLong(0);
try (Buffer b = allocator.allocate(8)) {
b.writeInt(1);
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.capacity()).isEqualTo(16);
assertThat(composite.writerOffset()).isEqualTo(12);
}
@@ -345,16 +349,17 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeInt(0);
try (Buffer b = allocator.allocate(8)) {
b.writeInt(1);
- var exc = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ var exc = assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(composite, b));
assertThat(exc).hasMessageContaining("unwritten gap");
b.writerOffset(0);
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.capacity()).isEqualTo(16);
assertThat(composite.writerOffset()).isEqualTo(4);
}
@@ -367,7 +372,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeLong(0);
@@ -375,7 +380,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (Buffer b = allocator.allocate(8)) {
b.writeInt(1);
b.readInt();
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.capacity()).isEqualTo(16);
assertThat(composite.writerOffset()).isEqualTo(12);
}
@@ -388,7 +393,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite) {
composite.writeLong(0);
@@ -396,10 +401,11 @@ public class BufferCompositionTest extends BufferTestSupport {
try (Buffer b = allocator.allocate(8)) {
b.writeInt(1);
b.readInt();
- var exc = assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ var exc = assertThrows(IllegalArgumentException.class,
+ () -> CompositeBuffer.extendComposite(composite, b));
assertThat(exc).hasMessageContaining("unread gap");
b.readerOffset(0);
- Buffer.extendComposite(composite, b);
+ CompositeBuffer.extendComposite(composite, b);
assertThat(composite.capacity()).isEqualTo(16);
assertThat(composite.writerOffset()).isEqualTo(12);
assertThat(composite.readerOffset()).isEqualTo(4);
@@ -413,7 +419,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(4, BIG_ENDIAN);
Buffer b = allocator.allocate(4, LITTLE_ENDIAN)) {
- assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, a, b));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b));
}
}
@@ -422,7 +428,7 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(4).readOnly(true);
Buffer b = allocator.allocate(4).readOnly(true);
- Buffer composite = Buffer.compose(allocator, a, b)) {
+ Buffer composite = CompositeBuffer.compose(allocator, a, b)) {
assertTrue(composite.readOnly());
verifyWriteInaccessible(composite);
}
@@ -433,10 +439,10 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap();
Buffer a = allocator.allocate(8).readOnly(true);
Buffer b = allocator.allocate(8)) {
- assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, a, b));
- assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, b, a));
- assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, a, b, a));
- assertThrows(IllegalArgumentException.class, () -> Buffer.compose(allocator, b, a, b));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, b, a));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, a, b, a));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.compose(allocator, b, a, b));
}
}
@@ -445,10 +451,10 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite; Buffer b = allocator.allocate(8).readOnly(true)) {
- assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.extendComposite(composite, b));
}
}
}
@@ -458,10 +464,10 @@ public class BufferCompositionTest extends BufferTestSupport {
try (BufferAllocator allocator = BufferAllocator.heap()) {
Buffer composite;
try (Buffer a = allocator.allocate(8).readOnly(true)) {
- composite = Buffer.compose(allocator, a);
+ composite = CompositeBuffer.compose(allocator, a);
}
try (composite; Buffer b = allocator.allocate(8)) {
- assertThrows(IllegalArgumentException.class, () -> Buffer.extendComposite(composite, b));
+ assertThrows(IllegalArgumentException.class, () -> CompositeBuffer.extendComposite(composite, b));
}
}
}
diff --git a/src/test/java/io/netty/buffer/api/BufferEnsureWritableTest.java b/src/test/java/io/netty/buffer/api/BufferEnsureWritableTest.java
index eb436bb..c2880d8 100644
--- a/src/test/java/io/netty/buffer/api/BufferEnsureWritableTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferEnsureWritableTest.java
@@ -33,7 +33,7 @@ public class BufferEnsureWritableTest extends BufferTestSupport {
assertThrows(IllegalStateException.class, () -> slice.ensureWritable(1));
assertThrows(IllegalStateException.class, () -> buf.ensureWritable(1));
}
- try (Buffer compose = Buffer.compose(allocator, buf)) {
+ try (Buffer compose = CompositeBuffer.compose(allocator, buf)) {
assertThrows(IllegalStateException.class, () -> compose.ensureWritable(1));
assertThrows(IllegalStateException.class, () -> buf.ensureWritable(1));
}
@@ -92,7 +92,7 @@ public class BufferEnsureWritableTest extends BufferTestSupport {
@Test
public void ensureWritableMustExpandCapacityOfEmptyCompositeBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer buf = Buffer.compose(allocator)) {
+ Buffer buf = CompositeBuffer.compose(allocator)) {
assertThat(buf.writableBytes()).isEqualTo(0);
buf.ensureWritable(8);
assertThat(buf.writableBytes()).isGreaterThanOrEqualTo(8);
diff --git a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java
index 13decea..bce1846 100644
--- a/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferReadOnlyTest.java
@@ -82,7 +82,7 @@ public class BufferReadOnlyTest extends BufferTestSupport {
@Test
public void readOnlyBufferMustRemainReadOnlyAfterSendForEmptyCompositeBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer buf = Buffer.compose(allocator)) {
+ Buffer buf = CompositeBuffer.compose(allocator)) {
buf.readOnly(true);
var send = buf.send();
try (Buffer receive = send.receive()) {
diff --git a/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java b/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java
index a8974fd..b43005a 100644
--- a/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java
+++ b/src/test/java/io/netty/buffer/api/BufferReferenceCountingTest.java
@@ -310,7 +310,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
assertEquals(0, slice.capacity()); // We haven't written anything, so the slice is empty.
int sliceBorrows = slice.countBorrows();
assertEquals(borrows + 2, buf.countBorrows());
- try (Buffer ignored1 = Buffer.compose(allocator, buf, slice)) {
+ try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
assertEquals(borrows + 3, buf.countBorrows());
// Note: Slice is empty; not acquired by the composite buffer.
assertEquals(sliceBorrows, slice.countBorrows());
@@ -337,7 +337,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
assertEquals(1, slice.capacity());
int sliceBorrows = slice.countBorrows();
assertEquals(borrows + 2, buf.countBorrows());
- try (Buffer ignored1 = Buffer.compose(allocator, buf, slice)) {
+ try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
assertEquals(borrows + 3, buf.countBorrows());
assertEquals(sliceBorrows + 1, slice.countBorrows());
}
@@ -656,7 +656,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
@Test
public void bifurcateOnEmptyBigEndianCompositeBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer buf = Buffer.compose(allocator).order(BIG_ENDIAN)) {
+ Buffer buf = CompositeBuffer.compose(allocator).order(BIG_ENDIAN)) {
verifyBifurcateEmptyCompositeBuffer(buf);
}
}
@@ -664,7 +664,7 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
@Test
public void bifurcateOnEmptyLittleEndianCompositeBuffer() {
try (BufferAllocator allocator = BufferAllocator.heap();
- Buffer buf = Buffer.compose(allocator).order(LITTLE_ENDIAN)) {
+ Buffer buf = CompositeBuffer.compose(allocator).order(LITTLE_ENDIAN)) {
verifyBifurcateEmptyCompositeBuffer(buf);
}
}
diff --git a/src/test/java/io/netty/buffer/api/BufferTestSupport.java b/src/test/java/io/netty/buffer/api/BufferTestSupport.java
index 722e1b2..40960f9 100644
--- a/src/test/java/io/netty/buffer/api/BufferTestSupport.java
+++ b/src/test/java/io/netty/buffer/api/BufferTestSupport.java
@@ -166,7 +166,7 @@ public abstract class BufferTestSupport {
int half = size / 2;
try (Buffer firstHalf = a.allocate(half);
Buffer secondHalf = b.allocate(size - half)) {
- return Buffer.compose(a, firstHalf, secondHalf);
+ return CompositeBuffer.compose(a, firstHalf, secondHalf);
}
}
@@ -190,7 +190,7 @@ public abstract class BufferTestSupport {
try (Buffer a = alloc.allocate(part);
Buffer b = alloc.allocate(part);
Buffer c = alloc.allocate(size - part * 2)) {
- return Buffer.compose(alloc, a, b, c);
+ return CompositeBuffer.compose(alloc, a, b, c);
}
}
@@ -229,7 +229,7 @@ public abstract class BufferTestSupport {
if (size < 2) {
return allocator.allocate(size);
}
- var buf = Buffer.compose(allocator);
+ var buf = CompositeBuffer.compose(allocator);
buf.ensureWritable(size);
return buf;
}
@@ -364,8 +364,8 @@ public abstract class BufferTestSupport {
assertThrows(IllegalStateException.class, () -> buf.copyInto(0, target, 0, 1));
assertThrows(IllegalStateException.class, () -> buf.copyInto(0, new byte[1], 0, 1));
assertThrows(IllegalStateException.class, () -> buf.copyInto(0, ByteBuffer.allocate(1), 0, 1));
- if (Buffer.isComposite(buf)) {
- assertThrows(IllegalStateException.class, () -> Buffer.extendComposite(buf, target));
+ if (CompositeBuffer.isComposite(buf)) {
+ assertThrows(IllegalStateException.class, () -> CompositeBuffer.extendComposite(buf, target));
}
}
diff --git a/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java b/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java
index a64189a..4197826 100644
--- a/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java
+++ b/src/test/java/io/netty/buffer/api/benchmarks/ByteIterationBenchmark.java
@@ -17,6 +17,7 @@ package io.netty.buffer.api.benchmarks;
import io.netty.buffer.api.BufferAllocator;
import io.netty.buffer.api.Buffer;
+import io.netty.buffer.api.CompositeBuffer;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
@@ -62,14 +63,14 @@ public class ByteIterationBenchmark {
allocator = BufferAllocator.heap();
try (var a = allocator.allocate(SIZE / 2);
var b = allocator.allocate(SIZE / 2)) {
- buf = Buffer.compose(allocator, a, b);
+ buf = CompositeBuffer.compose(allocator, a, b);
}
break;
case "composite-direct":
allocator = BufferAllocator.direct();
try (var a = allocator.allocate(SIZE / 2);
var b = allocator.allocate(SIZE / 2)) {
- buf = Buffer.compose(allocator, a, b);
+ buf = CompositeBuffer.compose(allocator, a, b);
}
break;
default:
diff --git a/src/test/java/io/netty/buffer/api/examples/ComposingAndSlicingExample.java b/src/test/java/io/netty/buffer/api/examples/ComposingAndSlicingExample.java
index 653663b..62315f3 100644
--- a/src/test/java/io/netty/buffer/api/examples/ComposingAndSlicingExample.java
+++ b/src/test/java/io/netty/buffer/api/examples/ComposingAndSlicingExample.java
@@ -17,6 +17,7 @@ package io.netty.buffer.api.examples;
import io.netty.buffer.api.BufferAllocator;
import io.netty.buffer.api.Buffer;
+import io.netty.buffer.api.CompositeBuffer;
import io.netty.buffer.api.Scope;
import java.util.concurrent.ThreadLocalRandom;
@@ -44,7 +45,7 @@ public final class ComposingAndSlicingExample {
private static Buffer createBigBuffer(BufferAllocator allocator) {
try (Scope scope = new Scope()) {
- return Buffer.compose(allocator,
+ return CompositeBuffer.compose(allocator,
scope.add(allocator.allocate(64)),
scope.add(allocator.allocate(64)),
scope.add(allocator.allocate(64)),
diff --git a/src/test/java/io/netty/buffer/api/examples/FileCopyExample.java b/src/test/java/io/netty/buffer/api/examples/FileCopyExample.java
index d05d184..214c3dd 100644
--- a/src/test/java/io/netty/buffer/api/examples/FileCopyExample.java
+++ b/src/test/java/io/netty/buffer/api/examples/FileCopyExample.java
@@ -17,6 +17,7 @@ package io.netty.buffer.api.examples;
import io.netty.buffer.api.BufferAllocator;
import io.netty.buffer.api.Buffer;
+import io.netty.buffer.api.CompositeBuffer;
import io.netty.buffer.api.Send;
import java.nio.channels.FileChannel;
@@ -37,7 +38,7 @@ public final class FileCopyExample {
try (BufferAllocator allocator = BufferAllocator.pooledDirect();
var input = FileChannel.open(Path.of("/dev/urandom"), READ);
var output = FileChannel.open(Path.of("random.bin"), CREATE, TRUNCATE_EXISTING, WRITE)) {
- Send done = Buffer.compose(allocator).send();
+ Send done = CompositeBuffer.compose(allocator).send();
var reader = executor.submit(() -> {
for (int i = 0; i < 1024; i++) {
diff --git a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/AlternativeMessageDecoder.java b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/AlternativeMessageDecoder.java
index a1ed218..ff8dc1b 100644
--- a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/AlternativeMessageDecoder.java
+++ b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/AlternativeMessageDecoder.java
@@ -17,6 +17,7 @@ package io.netty.buffer.api.examples.bytetomessagedecoder;
import io.netty.buffer.api.Buffer;
import io.netty.buffer.api.BufferAllocator;
+import io.netty.buffer.api.CompositeBuffer;
import io.netty.buffer.api.Send;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
@@ -82,11 +83,11 @@ public abstract class AlternativeMessageDecoder extends ChannelHandlerAdapter {
}
private void processRead(ChannelHandlerContext ctx, Buffer input) {
- if (collector.isOwned() && Buffer.isComposite(collector) && input.isOwned()
+ if (collector.isOwned() && CompositeBuffer.isComposite(collector) && input.isOwned()
&& (collector.writableBytes() == 0 || input.writerOffset() == 0)
&& (collector.readableBytes() == 0 || input.readerOffset() == 0)
&& collector.order() == input.order()) {
- Buffer.extendComposite(collector, input);
+ CompositeBuffer.extendComposite(collector, input);
drainCollector(ctx);
return;
}
diff --git a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoder.java b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoder.java
index a145d9c..35b9d2b 100644
--- a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoder.java
+++ b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoder.java
@@ -18,6 +18,7 @@ package io.netty.buffer.api.examples.bytetomessagedecoder;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.api.Buffer;
import io.netty.buffer.api.BufferAllocator;
+import io.netty.buffer.api.CompositeBuffer;
import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelFuture;
@@ -94,7 +95,7 @@ public abstract class ByteToMessageDecoder extends ChannelHandlerAdapter {
* Cumulate {@link Buffer}s by merge them into one {@link Buffer}'s, using memory copies.
*/
public static final Cumulator MERGE_CUMULATOR = (alloc, cumulation, in) -> {
- if (cumulation.readableBytes() == 0 && !Buffer.isComposite(cumulation)) {
+ if (cumulation.readableBytes() == 0 && !CompositeBuffer.isComposite(cumulation)) {
// If cumulation is empty and input buffer is contiguous, use it directly
cumulation.close();
return in;
@@ -128,7 +129,7 @@ public abstract class ByteToMessageDecoder extends ChannelHandlerAdapter {
}
Buffer composite;
try (in) {
- if (Buffer.isComposite(cumulation) && cumulation.isOwned()) {
+ if (CompositeBuffer.isComposite(cumulation) && cumulation.isOwned()) {
composite = cumulation;
if (composite.writerOffset() != composite.capacity()) {
// Writer index must equal capacity if we are going to "write"
@@ -137,9 +138,9 @@ public abstract class ByteToMessageDecoder extends ChannelHandlerAdapter {
cumulation.close();
}
} else {
- composite = Buffer.compose(alloc, cumulation);
+ composite = CompositeBuffer.compose(alloc, cumulation);
}
- Buffer.extendComposite(composite, in);
+ CompositeBuffer.extendComposite(composite, in);
return composite;
}
};
@@ -224,7 +225,7 @@ public abstract class ByteToMessageDecoder extends ChannelHandlerAdapter {
}
private static Buffer newEmptyBuffer() {
- return Buffer.compose(BufferAllocator.heap());
+ return CompositeBuffer.compose(BufferAllocator.heap());
}
@Override
diff --git a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java
index ac8175d..42016b7 100644
--- a/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java
+++ b/src/test/java/io/netty/buffer/api/examples/bytetomessagedecoder/ByteToMessageDecoderTest.java
@@ -17,6 +17,7 @@ package io.netty.buffer.api.examples.bytetomessagedecoder;
import io.netty.buffer.api.Buffer;
import io.netty.buffer.api.BufferAllocator;
+import io.netty.buffer.api.CompositeBuffer;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.embedded.EmbeddedChannel;
@@ -32,6 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static io.netty.buffer.api.BufferAllocator.heap;
import static io.netty.buffer.api.BufferTestSupport.assertEquals;
+import static io.netty.buffer.api.CompositeBuffer.compose;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static java.nio.ByteOrder.LITTLE_ENDIAN;
import static org.assertj.core.api.Assertions.assertThat;
@@ -421,7 +423,7 @@ public class ByteToMessageDecoderTest {
@Test
public void releaseWhenCompositeCumulateThrows() {
Buffer in = heap().allocate(12, LITTLE_ENDIAN).writerOffset(12);
- try (Buffer cumulation = Buffer.compose(heap(), heap().allocate(1, BIG_ENDIAN).writeByte((byte) 0).send())) {
+ try (Buffer cumulation = compose(heap(), heap().allocate(1, BIG_ENDIAN).writeByte((byte) 0).send())) {
ByteToMessageDecoder.COMPOSITE_CUMULATOR.cumulate(heap(), cumulation, in);
fail();
} catch (IllegalArgumentException expected) {