diff --git a/src/main/java/li/cil/circuity/vm/device/virtio/AbstractVirtIODevice.java b/src/main/java/li/cil/circuity/vm/device/virtio/AbstractVirtIODevice.java index b8d17ed8..e7c791ca 100644 --- a/src/main/java/li/cil/circuity/vm/device/virtio/AbstractVirtIODevice.java +++ b/src/main/java/li/cil/circuity/vm/device/virtio/AbstractVirtIODevice.java @@ -1124,6 +1124,34 @@ public abstract class AbstractVirtIODevice implements MemoryMappedDevice, Interr return writableByteCount - writtenByteCount; } + @Override + public void skip(int count) throws VirtIODeviceException, MemoryAccessException { + if (isUsed) { + throw new IllegalStateException(); + } + if (count > readableBytes() + writableBytes()) { + throw new IndexOutOfBoundsException(); + } + + while (count > 0) { + assert position < length; + final int remaining = length - position; + final int skip = Math.min(count, remaining); + count -= skip; + if (readableBytes() > 0) { + assert readableBytes() <= skip; + readByteCount += skip; + } else { + assert writableBytes() <= skip; + writtenByteCount += skip; + } + position += skip; + if (position >= length) { + nextDescriptor(); + } + } + } + @Override public byte get() throws VirtIODeviceException, MemoryAccessException { if (isUsed) { diff --git a/src/main/java/li/cil/circuity/vm/device/virtio/DescriptorChain.java b/src/main/java/li/cil/circuity/vm/device/virtio/DescriptorChain.java index 19deb909..1c77f509 100644 --- a/src/main/java/li/cil/circuity/vm/device/virtio/DescriptorChain.java +++ b/src/main/java/li/cil/circuity/vm/device/virtio/DescriptorChain.java @@ -60,10 +60,26 @@ public interface DescriptorChain { * Devices may opt to not completely fill up write-only descriptors before marking the descriptor * chain used by calling {@link DescriptorChain#use()}. * - * @return the maximum + * @return the number of remaining writable bytes in the descriptor chain. */ int writableBytes(); + /** + * Skips the specified number of bytes in this descriptor chain. + *

+ * This first uses up any remaining readable bytes followed by any remaining writable bytes. + *

+ * This can be useful for generating padding or ignoring parts of a descriptor chain. + * + * @param count the number of bytes to skip. + * @throws VirtIODeviceException when the device enters an error state. + * @throws MemoryAccessException when an exception is thrown while accessing physical memory. + * @throws IndexOutOfBoundsException if the sum of {@link #readableBytes()} and {@link #writableBytes()} + * is smaller than the specified number of bytes to skip. + * @throws IllegalStateException when called after {@link #use()} has been called. + */ + void skip(final int count) throws VirtIODeviceException, MemoryAccessException; + /** * Reads a single byte from the descriptor chain. *