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.
This commit is contained in:
parent
564c8c3f7c
commit
4259db264f
@ -285,11 +285,23 @@ public interface Buffer extends Resource<Buffer>, 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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user