diff --git a/projects/core/src/main/java/dan200/computercraft/core/apis/handles/ByteBufferChannel.java b/projects/core/src/main/java/dan200/computercraft/core/apis/handles/ByteBufferChannel.java index bffb70fc7..ff723d87a 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/apis/handles/ByteBufferChannel.java +++ b/projects/core/src/main/java/dan200/computercraft/core/apis/handles/ByteBufferChannel.java @@ -33,7 +33,9 @@ public class ByteBufferChannel implements SeekableByteChannel { var remaining = Math.min(backing.limit() - position, destination.remaining()); - destination.put(position, backing, position, remaining); + var destPos = destination.position(); + destination.put(destPos, backing, position, remaining); + destination.position(destPos + remaining); position += remaining; return remaining; } diff --git a/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ArrayByteChannelTest.java b/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ArrayByteChannelTest.java new file mode 100644 index 000000000..0a6421767 --- /dev/null +++ b/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ArrayByteChannelTest.java @@ -0,0 +1,17 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ +package dan200.computercraft.core.apis.handles; + +import dan200.computercraft.test.core.filesystem.ReadableChannelContract; + +import java.nio.channels.SeekableByteChannel; + +public class ArrayByteChannelTest implements ReadableChannelContract { + @Override + public SeekableByteChannel wrap(byte[] contents) { + return new ArrayByteChannel(contents); + } +} diff --git a/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ByteBufferChannelTest.java b/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ByteBufferChannelTest.java new file mode 100644 index 000000000..653720177 --- /dev/null +++ b/projects/core/src/test/java/dan200/computercraft/core/apis/handles/ByteBufferChannelTest.java @@ -0,0 +1,18 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ +package dan200.computercraft.core.apis.handles; + +import dan200.computercraft.test.core.filesystem.ReadableChannelContract; + +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; + +public class ByteBufferChannelTest implements ReadableChannelContract { + @Override + public SeekableByteChannel wrap(byte[] contents) { + return new ByteBufferChannel(ByteBuffer.wrap(contents)); + } +} diff --git a/projects/core/src/testFixtures/java/dan200/computercraft/test/core/filesystem/ReadableChannelContract.java b/projects/core/src/testFixtures/java/dan200/computercraft/test/core/filesystem/ReadableChannelContract.java new file mode 100644 index 000000000..596ffc269 --- /dev/null +++ b/projects/core/src/testFixtures/java/dan200/computercraft/test/core/filesystem/ReadableChannelContract.java @@ -0,0 +1,54 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ +package dan200.computercraft.test.core.filesystem; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SeekableByteChannel; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public interface ReadableChannelContract { + SeekableByteChannel wrap(byte[] contents); + + @Test + default void testReadAdvancesPosition() throws IOException { + try (var buffer = wrap(new byte[]{ 1, 2, 3, 4 })) { + var read = ByteBuffer.allocate(2); + + assertEquals(2, buffer.read(read)); + assertEquals(2, read.position()); + assertEquals(2, buffer.position()); + } + } + + @Test + default void testAtOffsetReadAdvancesPosition() throws IOException { + try (var buffer = wrap(new byte[]{ 1, 2, 3, 4 })) { + buffer.position(2); + var read = ByteBuffer.allocate(2); + + assertEquals(2, buffer.read(read)); + assertEquals(2, read.position()); + assertEquals(4, buffer.position()); + } + } + + @Test + default void testReadAtOffset() throws IOException { + try (var buffer = wrap(new byte[]{ 1, 2, 3, 4 })) { + buffer.position(2); + var read = ByteBuffer.allocate(2); + + assertEquals(2, buffer.read(read)); + read.flip(); + assertEquals(3, read.get(0)); + assertEquals(4, read.get(1)); + } + } +}