merge Matt's array codec mechanism
[ldk-java] / typescript_strings.py
index 5820e0a6424dba2154608ca83bfd7be225729899..de8ce66a455235a298805603b20fdfae32b9e084 100644 (file)
@@ -71,7 +71,16 @@ public static native long new_empty_slice_vec();
 
 """
 
-        self.bindings_footer = ""
+        self.bindings_footer = """
+        export async function initializeWasm(allowDoubleInitialization: boolean = false): Promise<void> {
+            if(isWasmInitialized && !allowDoubleInitialization) {
+                return;
+            }
+            const wasmInstance = await WebAssembly.instantiate(wasmModule, imports)
+            wasm = wasmInstance.exports;
+            isWasmInitialized = true;
+        }
+        """
 
         self.common_base = """
             export default class CommonBase {
@@ -281,6 +290,7 @@ import * as bindings from '../bindings' // TODO: figure out location
     def wasm_import_header(self, target):
         if target == Target.NODEJS:
             return """
+            
 import * as fs from 'fs';
 const source = fs.readFileSync('./ldk.wasm');
 
@@ -299,8 +309,9 @@ imports.env["abort"] = function () {
     console.error("ABORT");
 };
 
-const wasmInstance = await WebAssembly.instantiate(wasmModule, imports)
-const wasm = wasmInstance.exports;
+let wasm = null;
+let isWasmInitialized: boolean = false;
+
 
 // WASM CODEC
 
@@ -309,33 +320,50 @@ const nextMultipleOfFour = (value: number) => {
 }
 
 const encodeArray = (inputArray) => {
-    // TODO: (matt) is this correct, or should it go back to length * 4?
-    // const cArrayPointer = wasm.wasm_malloc(inputArray.length * 4);
-    const cArrayPointer = wasm.wasm_malloc(nextMultipleOfFour(inputArray.length));
-
-    const arrayMemoryView = new Uint32Array(memory.buffer, cArrayPointer, inputArray.length);
-    arrayMemoryView.set(inputArray);
-    return cArrayPointer;
+       const cArrayPointer = wasm.wasm_malloc((inputArray.length + 1) * 4);
+       const arrayMemoryView = new Uint32Array(memory.buffer, cArrayPointer + 4, inputArray.length);
+       arrayMemoryView.set(inputArray, 1);
+    arrayMemoryView[0] = inputArray.length;
+       return cArrayPointer;
 }
 
-const decodeArray = (arrayPointer, free = true) => {
-    const arraySizeViewer = new Uint32Array(
-        memory.buffer, // value
-        arrayPointer, // offset
-        1 // one int
-    );
-    const arraySize = arraySizeViewer[0];
-    const actualArrayViewer = new Uint32Array(
-        memory.buffer, // value
-        arrayPointer, // offset
-        arraySize + 1
-    );
-    const actualArray = actualArrayViewer.slice(1, arraySize + 1);
-    if (free) {
-        // wasm.free_array(arrayPointer);
-        wasm.wasm_free(arrayPointer); // TODO: check if passing *void still captures remaining values
-    }
-    return actualArray;
+const getArrayLength = (arrayPointer) => {
+       const arraySizeViewer = new Uint32Array(
+               memory.buffer, // value
+               arrayPointer, // offset
+               1 // one int
+       );
+       return arraySizeViewer[0];
+}
+const decodeUint8Array = (arrayPointer, free = true) => {
+       const arraySize = getArrayLength(arrayPointer);
+       const actualArrayViewer = new Uint8Array(
+               memory.buffer, // value
+               arrayPointer + 4, // offset (ignoring length bytes)
+               arraySize // uint8 count
+       );
+       // Clone the contents, TODO: In the future we should wrap the Viewer in a class that
+       // will free the underlying memory when it becomes unreachable instead of copying here.
+       const actualArray = actualArrayViewer.slice(0, arraySize);
+       if (free) {
+               wasm.free(arrayPointer);
+       }
+       return actualArray;
+}
+const decodeUint32Array = (arrayPointer, free = true) => {
+       const arraySize = getArrayLength(arrayPointer);
+       const actualArrayViewer = new Uint32Array(
+               memory.buffer, // value
+               arrayPointer + 4, // offset (ignoring length bytes)
+               arraySize // uint32 count
+       );
+       // Clone the contents, TODO: In the future we should wrap the Viewer in a class that
+       // will free the underlying memory when it becomes unreachable instead of copying here.
+       const actualArray = actualArrayViewer.slice(0, arraySize);
+       if (free) {
+               wasm.free(arrayPointer);
+       }
+       return actualArray;
 }
 
 const encodeString = (string) => {
@@ -370,7 +398,9 @@ const decodeString = (stringPointer, free = true) => {
 
     return result;
 };
-"""
+
+
+            """
         return ''
 
     def init_str(self):
@@ -869,16 +899,21 @@ const decodeString = (stringPointer, free = true) => {
                 method_argument_string += f"{arg_conv_info.arg_name}: {arg_conv_info.java_ty}"
                 native_call_argument_string += native_argument
 
+        has_return_value = return_type_info.c_ty != 'void'
         needs_decoding = return_type_info.c_ty in self.wasm_decoding_map
-        return_value = 'nativeResponseValue'
-        if needs_decoding:
+        return_statement = 'return nativeResponseValue;'
+        if not has_return_value:
+            return_statement = '// debug statements here'
+        elif needs_decoding:
             converter = self.wasm_decoding_map[return_type_info.c_ty]
-            return_value = f"{converter}(nativeResponseValue)"
+            return_statement = f"return {converter}(nativeResponseValue);"
 
         out_java = f"""\texport function {method_name}({method_argument_string}): {return_type_info.java_ty} {{
+            if(!isWasmInitialized){{
+                throw new Error("initializeWasm() must be awaited first!");
+            }}
             const nativeResponseValue = wasm.{method_name}({native_call_argument_string});
-            return {return_value};
-        \n\t}}
+            {return_statement}\n\t}}
         \n"""