diff --git a/.gitignore b/.gitignore
index bed43ed36..9459e8a3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ build-emscripten
build-wasi
src/io/internal/ImageIOIndex.ts
src/io/internal/MeshIOIndex.ts
+wasi-build/
dist/*
!dist/dicom
diff --git a/packages/core/java/.gitignore b/packages/core/java/.gitignore
new file mode 100644
index 000000000..10d81e8c6
--- /dev/null
+++ b/packages/core/java/.gitignore
@@ -0,0 +1,4 @@
+/.classpath
+/.project
+/.settings/
+/target/
diff --git a/packages/core/java/pom.xml b/packages/core/java/pom.xml
new file mode 100644
index 000000000..1e250da3c
--- /dev/null
+++ b/packages/core/java/pom.xml
@@ -0,0 +1,111 @@
+
+
+ 4.0.0
+
+
+ org.scijava
+ pom-scijava
+ 35.1.1
+
+
+ org.itk.wasm
+ itk-wasm
+ 0.1.0-SNAPSHOT
+
+ itk-wasm for Java
+ Java interface to itk-wasm WebAssembly modules.
+ https://github.com/InsightSoftwareConsortium/itk-wasm
+ 2023
+
+ ITK
+ https://itk.org/
+
+
+
+ The Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0
+
+
+
+
+
+ Matt McCormick
+ https://github.com/thewtex
+ thewtex
+
+
+
+
+ Curtis Rueden
+ https://github.com/ctrueden
+ ctrueden
+
+
+
+
+
+ ITK Forum
+ https://discourse.itk.org/
+
+
+
+
+ scm:https://github.com/InsightSoftwareConsortium/itk-wasm
+ scm:git@github.com:InsightSoftwareConsortium/itk-wasm
+ https://github.com/InsightSoftwareConsortium/itk-wasm
+
+
+ GitHub Issues
+ https://github.com/InsightSoftwareConsortium/itk-wasm/issues
+
+
+ GitHub Actions
+ https://github.com/InsightSoftwareConsortium/itk-wasm/actions
+
+
+
+ org.itk.wasm.Main
+
+ apache_v2
+ ITK developers.
+ Java bindings for itk-wasm.
+
+ 0.14.0
+
+
+
+
+ io.github.kawamuray.wasmtime
+ wasmtime-java
+ ${wasmtime-java.version}
+
+
+ net.imglib2
+ imglib2
+
+
+ net.java.dev.jna
+ jna
+
+
+ net.java.dev.jna
+ jna-platform
+
+
+ com.google.code.gson
+ gson
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
diff --git a/packages/core/java/src/main/java/org/itk/wasm/BinaryFile.java b/packages/core/java/src/main/java/org/itk/wasm/BinaryFile.java
new file mode 100644
index 000000000..769f1ab48
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/BinaryFile.java
@@ -0,0 +1,15 @@
+package org.itk.wasm;
+
+import java.nio.file.Path;
+
+public class BinaryFile {
+ public PurePosixPath path;
+
+ public BinaryFile(PurePosixPath path) {
+ this.path = path;
+ }
+
+ public BinaryFile(Path path) {
+ this(new PurePosixPath(path));
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/BinaryStream.java b/packages/core/java/src/main/java/org/itk/wasm/BinaryStream.java
new file mode 100644
index 000000000..617b33e5c
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/BinaryStream.java
@@ -0,0 +1,28 @@
+/*-
+ * #%L
+ * Java bindings for itk-wasm.
+ * %%
+ * Copyright (C) 2023 ITK developers.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package org.itk.wasm;
+
+public class BinaryStream {
+ public byte[] data;
+
+ public BinaryStream(byte[] data) {
+ this.data = data;
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/FloatTypes.java b/packages/core/java/src/main/java/org/itk/wasm/FloatTypes.java
new file mode 100644
index 000000000..d03f6fb96
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/FloatTypes.java
@@ -0,0 +1,18 @@
+package org.itk.wasm;
+
+public enum FloatTypes {
+ Float32("float32"),
+ Float64("float64"),
+ SpacePrecisionType("float64");
+
+ private final String value;
+
+ FloatTypes(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/IO.java b/packages/core/java/src/main/java/org/itk/wasm/IO.java
new file mode 100644
index 000000000..002b4bf6c
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/IO.java
@@ -0,0 +1,29 @@
+package org.itk.wasm;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+public final class IO {
+
+ public IO() { }
+
+ public static byte[] readBytes(String path) throws IOException {
+ //try (InputStream is = Main.class.getResourceAsStream(filename)) {
+ try (InputStream is = new FileInputStream(path)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nRead;
+ byte[] buf = new byte[16384];
+ while ((nRead = is.read(buf, 0, buf.length)) != -1) {
+ buffer.write(buf, 0, nRead);
+ }
+ return buffer.toByteArray();
+ }
+ }
+
+ public static String readString(String path) throws IOException {
+ return new String(readBytes(path), StandardCharsets.UTF_8);
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/Image.java b/packages/core/java/src/main/java/org/itk/wasm/Image.java
new file mode 100644
index 000000000..3039fc2e0
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/Image.java
@@ -0,0 +1,69 @@
+package org.itk.wasm;
+
+import java.util.*;
+
+public class Image {
+ public ImageType imageType;
+ public String name;
+ public List origin;
+ public List spacing;
+ public double[][] direction;
+ public List size;
+ public Map metadata;
+ public double[] data;
+
+ public Image() {
+ this.imageType = new ImageType();
+ this.name = "Image";
+ this.origin = new ArrayList<>();
+ this.spacing = new ArrayList<>();
+ this.direction = new double[0][0];
+ this.size = new ArrayList<>();
+ this.metadata = new HashMap<>();
+ this.data = null;
+ }
+
+ public void postInit() {
+ if (imageType instanceof Map) {
+ imageType = new ImageType();
+ Map imageTypeMap = asdict(imageType);
+ // Set values from the map to the corresponding fields in ImageType
+ // Example: imageType.setDimension((int) imageTypeMap.get("dimension"));
+ // Add similar code for other fields
+ }
+
+ int dimension = imageType.dimension;
+ if (origin.isEmpty()) {
+ for (int i = 0; i < dimension; i++) {
+ origin.add(0.0);
+ }
+ }
+
+ if (spacing.isEmpty()) {
+ for (int i = 0; i < dimension; i++) {
+ spacing.add(1.0);
+ }
+ }
+
+ if (direction.length == 0) {
+ direction = new double[dimension][dimension];
+ for (int i = 0; i < dimension; i++) {
+ for (int j = 0; j < dimension; j++) {
+ if (i == j) {
+ direction[i][j] = 1.0;
+ } else {
+ direction[i][j] = 0.0;
+ }
+ }
+ }
+ }
+
+ if (size.isEmpty()) {
+ for (int i = 0; i < dimension; i++) {
+ size.add(1);
+ }
+ }
+ }
+
+ // Add getters and setters for the fields
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/ImageType.java b/packages/core/java/src/main/java/org/itk/wasm/ImageType.java
new file mode 100644
index 000000000..b2e74479e
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/ImageType.java
@@ -0,0 +1,17 @@
+package org.itk.wasm;
+
+public class ImageType {
+ public int dimension;
+ public IntTypes componentType;
+ public PixelType pixelType;
+ public int components;
+
+ public ImageType() {
+ this.dimension = 2;
+ this.componentType = IntTypes.UInt8;
+ this.pixelType = PixelType.Scalar;
+ this.components = 1;
+ }
+
+ // Add getters and setters for the fields
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/IntTypes.java b/packages/core/java/src/main/java/org/itk/wasm/IntTypes.java
new file mode 100644
index 000000000..791cabe48
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/IntTypes.java
@@ -0,0 +1,27 @@
+package org.itk.wasm;
+
+public enum IntTypes {
+ Int8("int8"),
+ UInt8("uint8"),
+ Int16("int16"),
+ UInt16("uint16"),
+ Int32("int32"),
+ UInt32("uint32"),
+ Int64("int64"),
+ UInt64("uint64"),
+ SizeValueType("uint64"),
+ IdentifierType("uint64"),
+ IndexValueType("int64"),
+ OffsetValueType("int64");
+
+ private final String value;
+
+ IntTypes(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/InterfaceType.java b/packages/core/java/src/main/java/org/itk/wasm/InterfaceType.java
new file mode 100644
index 000000000..bad6226e1
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/InterfaceType.java
@@ -0,0 +1,31 @@
+/*-
+ * #%L
+ * Java bindings for itk-wasm.
+ * %%
+ * Copyright (C) 2023 ITK developers.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package org.itk.wasm;
+
+public enum InterfaceType {
+ TextFile,
+ BinaryFile,
+ TextStream,
+ BinaryStream,
+ Image,
+ Mesh,
+ PolyData,
+ JsonObject
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/JsonObject.java b/packages/core/java/src/main/java/org/itk/wasm/JsonObject.java
new file mode 100644
index 000000000..a31d4a7b4
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/JsonObject.java
@@ -0,0 +1,19 @@
+package org.itk.wasm;
+
+import java.util.Map;
+
+public class JsonObject {
+ private Map data;
+
+ public JsonObject(Map data) {
+ this.data = data;
+ }
+
+ public Map getData() {
+ return data;
+ }
+
+ public void setData(Map data) {
+ this.data = data;
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/Main.java b/packages/core/java/src/main/java/org/itk/wasm/Main.java
new file mode 100644
index 000000000..d470415e9
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/Main.java
@@ -0,0 +1,77 @@
+/*-
+ * #%L
+ * Java bindings for itk-wasm.
+ * %%
+ * Copyright (C) 2023 ITK developers.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package org.itk.wasm;
+
+import io.github.kawamuray.wasmtime.Config;
+import io.github.kawamuray.wasmtime.Engine;
+import io.github.kawamuray.wasmtime.Extern;
+import io.github.kawamuray.wasmtime.Linker;
+import io.github.kawamuray.wasmtime.Module;
+import io.github.kawamuray.wasmtime.Store;
+import io.github.kawamuray.wasmtime.WasmFunctions;
+import io.github.kawamuray.wasmtime.WasmFunctions.Consumer0;
+import io.github.kawamuray.wasmtime.wasi.WasiCtx;
+import io.github.kawamuray.wasmtime.wasi.WasiCtxBuilder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class Main {
+ public static void main(String... args) throws IOException {
+ // Configure the initial compilation environment, creating the global
+ // `Store` structure. Note that you can also tweak configuration settings
+ // with a `Config` and an `Engine` if desired.
+ System.err.println("Initializing...");
+ Config config = new Config();
+ try (
+ Engine engine = new Engine(config);
+ Linker linker = new Linker(engine);
+ Module module = Module.fromBinary(engine, readBytes("../test/data/input/stdout-stderr-test.wasi.wasm")))
+ {
+ // Here we handle the imports of the module, which in this case is our
+ // `HelloCallback` type and its associated implementation of `Callback.
+ System.err.println("Creating callback...");
+
+ WasiCtx wasi = new WasiCtxBuilder().inheritStdout().inheritStderr().build();
+ Store store = new Store<>(null, engine, wasi);
+ WasiCtx.addToLinker(linker);
+ String moduleName = "this-can-be-anything";
+ linker.module(store, moduleName, module);
+ Extern extern = linker.get(store, moduleName, "").get();
+ Consumer0 doWork = WasmFunctions.consumer(store, extern.func());
+ doWork.accept();
+ }
+ }
+
+ private static byte[] readBytes(String filename) throws IOException {
+ //try (InputStream is = Main.class.getResourceAsStream(filename)) {
+ try (InputStream is = new FileInputStream(filename)) {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nRead;
+ byte[] buf = new byte[16384];
+ while ((nRead = is.read(buf, 0, buf.length)) != -1) {
+ buffer.write(buf, 0, nRead);
+ }
+ return buffer.toByteArray();
+ }
+ }
+}
diff --git a/packages/core/java/src/main/java/org/itk/wasm/Pipeline.java b/packages/core/java/src/main/java/org/itk/wasm/Pipeline.java
new file mode 100644
index 000000000..6b90d419f
--- /dev/null
+++ b/packages/core/java/src/main/java/org/itk/wasm/Pipeline.java
@@ -0,0 +1,301 @@
+/*-
+ * #%L
+ * Java bindings for itk-wasm.
+ * %%
+ * Copyright (C) 2023 ITK developers.
+ * %%
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * #L%
+ */
+package org.itk.wasm;
+
+import static io.github.kawamuray.wasmtime.WasmValType.I32;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+
+import io.github.kawamuray.wasmtime.Config;
+import io.github.kawamuray.wasmtime.Engine;
+import io.github.kawamuray.wasmtime.Extern;
+import io.github.kawamuray.wasmtime.Linker;
+import io.github.kawamuray.wasmtime.Memory;
+import io.github.kawamuray.wasmtime.Module;
+import io.github.kawamuray.wasmtime.Store;
+import io.github.kawamuray.wasmtime.WasmFunctions;
+import io.github.kawamuray.wasmtime.WasmFunctions.Consumer0;
+import io.github.kawamuray.wasmtime.WasmFunctions.Consumer1;
+import io.github.kawamuray.wasmtime.WasmFunctions.Function0;
+import io.github.kawamuray.wasmtime.WasmFunctions.Function1;
+import io.github.kawamuray.wasmtime.WasmFunctions.Function2;
+import io.github.kawamuray.wasmtime.WasmFunctions.Function3;
+import io.github.kawamuray.wasmtime.WasmFunctions.Function4;
+import io.github.kawamuray.wasmtime.wasi.WasiCtx;
+import io.github.kawamuray.wasmtime.wasi.WasiCtxBuilder;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class Pipeline {
+ private static int instanceID = 0;
+
+ private Config config;
+ private Engine engine;
+ private Linker linker;
+ private Module module;
+
+ public Pipeline(Path path) throws IOException {
+ this(path.toString());
+ }
+
+ public Pipeline(String path) throws IOException {
+ this(IO.readBytes(path));
+ }
+
+ public Pipeline(byte[] wasmBytes) {
+ config = new Config();
+ //config.wasmBulkMemory(true); // <-- This method causes a mysterious ClassNotFoundException
+ //config.wasmSimd(true); // <-- This method causes a mysterious ClassNotFoundException
+ //config.wasmMemory64(true); // <-- This method does not exist
+ engine = new Engine(config);
+
+ linker = new Linker(engine);
+ //linker.allowShadowing(true);
+ module = new Module(engine, wasmBytes);
+
+ WasiCtx.addToLinker(linker);
+ }
+
+ public List> run(List args) {
+ return run(args, Collections.emptyList(), Collections.emptyList());
+ }
+
+ public List> run(List args, List> outputs, List> inputs) {
+ try (RunInstance ri = new RunInstance(args, outputs, inputs)) {
+ int returnCode = ri.delayedStart();
+ if (returnCode != 0) throw new RuntimeException("Non-zero return code: " + returnCode); //TEMP
+
+ List> populatedOutputs = new ArrayList<>();
+ if (!outputs.isEmpty() && returnCode == 0) {
+ for (int index = 0; index < outputs.size(); index++) {
+ PipelineOutput> output = outputs.get(index);
+ if (output.type == InterfaceType.TextStream) {
+ int dataPtr = ri.outputArrayAddress(0, index, 0);
+ int dataLen = ri.outputArraySize(0, index, 0);
+ byte[] dataBytes = ri.wasmTimeLift(dataPtr, dataLen);
+ String dataString = str(dataBytes);
+ TextStream textStream = new TextStream(dataString);
+ populatedOutputs.add(new PipelineOutput<>(InterfaceType.TextStream, textStream));
+ } else if (output.type == InterfaceType.BinaryStream) {
+ int dataPtr = ri.outputArrayAddress(0, index, 0);
+ int dataLen = ri.outputArraySize(0, index, 0);
+ byte[] dataBytes = ri.wasmTimeLift(dataPtr, dataLen);
+ BinaryStream binaryStream = new BinaryStream(dataBytes);
+ populatedOutputs.add(new PipelineOutput<>(InterfaceType.BinaryStream, binaryStream));
+ } else {
+ throw new IllegalArgumentException("Unexpected/not yet supported output.type " + output.type);
+ }
+ }
+ }
+
+ return populatedOutputs;
+ }
+ }
+
+ private static String str(byte[] bytes) {
+ return new String(bytes, StandardCharsets.UTF_8);
+ }
+ private static byte[] bytes(String str) {
+ return str.getBytes(StandardCharsets.UTF_8);
+ }
+
+ private class RunInstance implements AutoCloseable {
+
+ private final Store store;
+ private final String moduleName;
+
+ private final Consumer0 main;
+ private final Consumer0 initialize;
+ private final Function0 delayedStart;
+ private final Consumer1 delayedExit;
+ private final Function4 inputArrayAlloc;
+ private final Function3 inputJsonAlloc;
+ private final Function2 outputJsonAddress;
+ private final Function2 outputJsonSize;
+ private final Function3 outputArrayAddress;
+ private final Function3 outputArraySize;
+ private final Consumer0 freeAll;
+ private final Memory memory;
+
+ public RunInstance(List args, List> outputs,
+ List> inputs)
+ {
+ WasiCtx wasiConfig = new WasiCtxBuilder()
+ //.inheritEnv()
+ .inheritStderr()
+ //.inheritStdin()
+ .inheritStdout()
+ //.args(args)
+ .build();
+
+
+ Set preopenDirectories = new HashSet<>();
+ for (PipelineInput> input : inputs) {
+ if (input.type == InterfaceType.TextFile) {
+ PurePosixPath path = ((TextFile) input.data).path;
+ preopenDirectories.add(path.getParent().toString());
+ }
+ if (input.type == InterfaceType.BinaryFile) {
+ PurePosixPath path = ((BinaryFile) input.data).path;
+ preopenDirectories.add(path.getParent().toString());
+ }
+ }
+ for (PipelineOutput> output : outputs) {
+ if (output.type == InterfaceType.TextFile) {
+ PurePosixPath path = ((TextFile) output.data).path;
+ preopenDirectories.add(path.getParent().toString());
+ }
+ if (output.type == InterfaceType.BinaryFile) {
+ PurePosixPath path = ((BinaryFile) output.data).path;
+ preopenDirectories.add(path.getParent().toString());
+ }
+ }
+
+ for (String preopen : preopenDirectories) {
+ Path p = Paths.get(preopen);
+ wasiConfig.pushPreopenDir(p, preopen);
+ }
+
+ // Instantiate the module.
+ store = new Store<>(null, engine, wasiConfig);
+ moduleName = "instance" + instanceID++;
+ linker.module(store, moduleName, module);
+
+ main = consumer0(store, "");
+ initialize = consumer0(store, "_initialize");
+ delayedStart = func0(store, "itk_wasm_delayed_start");
+ delayedExit = consumer1(store, "itk_wasm_delayed_exit");
+ inputArrayAlloc = func4(store, "itk_wasm_input_array_alloc");
+ inputJsonAlloc = func3(store, "itk_wasm_input_json_alloc");
+ outputJsonAddress = func2(store, "itk_wasm_output_json_address");
+ outputJsonSize = func2(store, "itk_wasm_output_json_size");
+ outputArrayAddress = func3(store, "itk_wasm_output_array_address");
+ outputArraySize = func3(store, "itk_wasm_output_array_size");
+ freeAll = consumer0(store, "itk_wasm_free_all");
+ memory = extern(store, "memory").memory();
+ }
+
+ public Integer delayedStart() { return delayedStart.call(); }
+ public void delayedExit(Integer i) { delayedExit.accept(i); }
+ public Integer inputArrayAlloc(Integer i1, Integer i2, Integer i3, Integer i4) { return inputArrayAlloc.call(i1, i2, i3, i4); }
+ public Integer inputJsonAlloc(Integer i1, Integer i2, Integer i3) { return inputJsonAlloc.call(i1, i2, i3); }
+ public Integer outputJsonAddress(Integer i1, Integer i2) { return outputJsonAddress.call(i1, i2); }
+ public Integer outputJsonSize(Integer i1, Integer i2) { return outputJsonSize.call(i1, i2); }
+ public Integer outputArrayAddress(Integer i1, Integer i2, Integer i3) { return outputArrayAddress.call(i1, i2, i3); }
+ public Integer outputArraySize(Integer i1, Integer i2, Integer i3) { return outputArraySize.call(i1, i2, i3); }
+ public void freeAll() { freeAll.accept(); }
+
+ public ByteBuffer memoryBuffer(int offset, int length) {
+ ByteBuffer buffer = memory.buffer(store);
+ buffer.position(offset);
+ buffer.limit(length);
+ return buffer.slice();
+ }
+ public int memorySize() { return memory.size(store); }
+
+ @Override
+ public void close() {
+ store.close();
+ }
+
+ private byte[] wasmTimeLift(int offset, int length) {
+ if (offset + length > memorySize()) {
+ throw new IndexOutOfBoundsException("Attempting to lift out of bounds");
+ }
+ ByteBuffer byteBuffer = memoryBuffer(offset, length);
+ byte[] data = new byte[byteBuffer.remaining()];
+ byteBuffer.get(data);
+ return data;
+ }
+
+ private void wasmTimeLower(int offset, byte[] data) {
+ int size = data.length;
+ if (offset + size > memorySize()) {
+ throw new IndexOutOfBoundsException("Attempting to lower out of bounds");
+ }
+ ByteBuffer byteBuffer = memoryBuffer(offset, size);
+ byteBuffer.put(data);
+ }
+
+ private int setInputArray(byte[] dataArray, int inputIndex, int subIndex) {
+ int dataPtr = 0;
+ if (dataArray != null) {
+ dataPtr = inputArrayAlloc(0, inputIndex, subIndex, dataArray.length);
+ wasmTimeLower(dataPtr, dataArray);
+ }
+ return dataPtr;
+ }
+
+ private void setInputJson(Map dataObject, int inputIndex) {
+ Gson gson = new GsonBuilder().create();
+ JsonElement jsonElement = gson.toJsonTree(dataObject);
+ byte[] dataJson = bytes(jsonElement.toString());
+ int jsonPtr = inputJsonAlloc(0, inputIndex, dataJson.length);
+ wasmTimeLower(jsonPtr, dataJson);
+ }
+
+ private Map getOutputJson(int outputIndex) {
+ int jsonPtr = outputJsonAddress(0, outputIndex);
+ int jsonLen = outputJsonSize(0, outputIndex);
+ byte[] jsonBytes = wasmTimeLift(jsonPtr, jsonLen);
+ String jsonString = str(jsonBytes);
+ Gson gson = new GsonBuilder().create();
+ return gson.fromJson(jsonString, new TypeToken