blob: 228ecaf5948fb96f2589746931779f4d7736a036 [file]
package org.wasmer;
import org.wasmer.exports.Export;
import java.lang.IllegalArgumentException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.BufferUnderflowException;
import java.nio.BufferOverflowException;
import java.nio.ReadOnlyBufferException;
/**
* `Memory` is a Java class that represents a WebAssembly memory.
*
* Example:
* <pre>{@code
* Instance instance = new Instance(wasmBytes);
* Memory memory = instance.memories.get("memory-name");
* memory.write(0, new byte[]{1, 2, 3, 4, 5});
* byte[] bytes = memory.read(0, 5);
* }</pre>
*/
public class Memory implements Export {
private native int nativeMemoryGrow(Memory memory, long memoryPointer, int page);
/**
* Represents the actual WebAssembly memory data, borrowed from the runtime (in Rust).
* The `setInner` method must be used to set this attribute.
*/
private ByteBuffer inner;
private long memoryPointer;
private Memory() {
// This object is instantiated by Rust.
}
/**
* Set the `ByteBuffer` of this memory. See `Memory.inner` to learn more.
*
* In addition, this method correctly sets the endianess of the `ByteBuffer`.
*/
private void setInner(ByteBuffer inner) {
this.inner = inner;
// Ensure the endianess matches WebAssemly specification.
if (this.inner.order() != ByteOrder.LITTLE_ENDIAN) {
this.inner.order(ByteOrder.LITTLE_ENDIAN);
}
}
/**
* Read the set of bytes from the offset.
*
* @param offset The offset within the memory data of the first byte to be read.
* @param length The number of bytes to be read from the memory data.
* @return The set of bytes.
*/
public byte[] read(int offset, int length) throws BufferUnderflowException, IllegalArgumentException {
byte[] result = new byte[length];
if (offset < 0) {
throw new IllegalArgumentException("newPosition < 0: (" + offset + " < 0)");
}
int size = this.size();
if (offset > size) {
throw new IllegalArgumentException("newPosition > limit: (" + offset + " > " + size + ")");
}
this.inner.position(offset);
this.inner.get(result);
return result;
}
/**
* Write the set of bytes from the offset.
*
* @param offset The offset within the memory data of the first byte to be read.
* @param data The bytes to write.
*/
public void write(int offset, byte[] data) throws BufferOverflowException, IllegalArgumentException, ReadOnlyBufferException {
if (offset < 0) {
throw new IllegalArgumentException("newPosition < 0: (" + offset + " < 0)");
}
int size = this.size();
if (offset > size) {
throw new IllegalArgumentException("newPosition > limit: (" + offset + " > " + size + ")");
}
this.inner.position(offset);
this.inner.put(data);
}
/**
* Return the size of the memory.
*
* @return The size of the memory.
*/
public int size() {
return this.inner.limit();
}
/**
* Grow this memory by the specified number of pages.
*
* @param page The number of pages to grow. 1 page size is 64KiB.
* @return The privious number of pages.
*/
public int grow(int page) {
return this.nativeMemoryGrow(this, this.memoryPointer, page);
}
}