From 4259db264f4b01850f099cba424740a5f3ab8db3 Mon Sep 17 00:00:00 2001 From: Nitesh Kant Date: Wed, 28 Jul 2021 02:16:55 -0700 Subject: [PATCH] Add an ByteBuf -> Buffer adaptor (#11518) Add an ByteBuf -> Buffer adaptor Motivation: For migration of APIs from `ByteBuf` to `Buffer` sometime we may have to bridge APIs which use a `ByteBuf` (eg: `ByteToMessageDecoder` at the moment) to APIs that use a `Buffer` even when the allocator for the `ByteBuf` isn't migrated to use `ByteBufAllocatorAdaptor`. Modification: - Add a simple copy adaptor that copies all data from `ByteBuf` to a new `Buffer`. - I noticed we do not have a `writeBytes` method with offsets, so added that too. Result: One more adaptor to bridge old and new buffer APIs. --- .../main/java/io/netty/buffer/api/Buffer.java | 20 ++++++++++++---- .../buffer/api/adaptor/ByteBufAdaptor.java | 23 +++++++++++++++++++ .../api/tests/BufferBulkAccessTest.java | 13 +++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/api/Buffer.java b/buffer/src/main/java/io/netty/buffer/api/Buffer.java index ddde9ca861..46629a40f0 100644 --- a/buffer/src/main/java/io/netty/buffer/api/Buffer.java +++ b/buffer/src/main/java/io/netty/buffer/api/Buffer.java @@ -285,11 +285,23 @@ public interface Buffer extends Resource, BufferAccessor { * @return This buffer. */ default Buffer writeBytes(byte[] source) { - int size = source.length; + return writeBytes(source, 0, source.length); + } + + /** + * Writes into this buffer, all the bytes from the given byte array. + * This updates the {@linkplain #writerOffset() write offset} of this buffer by the length of the array. + * + * @param source The byte array to read from. + * @param srcPos Position in the {@code source} from where bytes should be written to this buffer. + * @param length The number of bytes to copy. + * @return This buffer. + */ + default Buffer writeBytes(byte[] source, int srcPos, int length) { int woff = writerOffset(); - writerOffset(woff + size); - for (int i = 0; i < size; i++) { - setByte(woff + i, source[i]); + writerOffset(woff + length); + for (int i = 0; i < length; i++) { + setByte(woff + i, source[srcPos + i]); } return this; } diff --git a/buffer/src/main/java/io/netty/buffer/api/adaptor/ByteBufAdaptor.java b/buffer/src/main/java/io/netty/buffer/api/adaptor/ByteBufAdaptor.java index 1f939e07a6..9df2f24e53 100644 --- a/buffer/src/main/java/io/netty/buffer/api/adaptor/ByteBufAdaptor.java +++ b/buffer/src/main/java/io/netty/buffer/api/adaptor/ByteBufAdaptor.java @@ -79,6 +79,29 @@ public final class ByteBufAdaptor extends ByteBuf { return null; } + /** + * Extracts the underlying {@link Buffer} instance that is backing this {@link ByteBuf}, if any. + * This is similar to {@link #unwrap()} except the return type is a {@link Buffer}. + * If this {@link ByteBuf} does not wrap a {@link Buffer}, then a new {@code Buffer} instance is returned with the + * contents copied from the given {@link ByteBuf}. + * + * @param byteBuf The {@link ByteBuf} to extract the {@link Buffer} from. + * @return The {@link Buffer} instance that is backing the given {@link ByteBuf}, or a new {@code Buffer} + * containing the contents copied from the given {@link ByteBuf}. If the data is copied, the passed {@link ByteBuf} + * will be {@link ByteBuf#release() released}. + */ + public static Buffer extractOrCopy(BufferAllocator allocator, ByteBuf byteBuf) { + final Buffer extracted = extract(byteBuf); + if (extracted != null) { + return extracted; + } + try { + return allocator.allocate(byteBuf.capacity()).writeBytes(ByteBufUtil.getBytes(byteBuf)); + } finally { + byteBuf.release(); + } + } + @Override public int capacity() { return buffer.capacity(); diff --git a/buffer/src/test/java/io/netty/buffer/api/tests/BufferBulkAccessTest.java b/buffer/src/test/java/io/netty/buffer/api/tests/BufferBulkAccessTest.java index d6c6cad048..ba9a495ffc 100644 --- a/buffer/src/test/java/io/netty/buffer/api/tests/BufferBulkAccessTest.java +++ b/buffer/src/test/java/io/netty/buffer/api/tests/BufferBulkAccessTest.java @@ -258,4 +258,17 @@ public class BufferBulkAccessTest extends BufferTestSupport { assertThat(toByteArray(buffer)).containsExactly(1, 2, 3, 4, 5, 6, 7, 0); } } + + @ParameterizedTest + @MethodSource("allocators") + public void writeBytesWithOffsetMustWriteAllBytesFromByteArray(Fixture fixture) { + try (BufferAllocator allocator = fixture.createAllocator(); + Buffer buffer = allocator.allocate(3)) { + buffer.writeByte((byte) 1); + buffer.writeBytes(new byte[] {2, 3, 4, 5, 6, 7}, 1, 2); + assertThat(buffer.writerOffset()).isEqualTo(3); + assertThat(buffer.readerOffset()).isZero(); + assertThat(toByteArray(buffer)).containsExactly(1, 3, 4); + } + } }