From 762ff9e0f2f781e0d25830da06e771ed94751d1b Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Wed, 17 Jan 2024 16:20:56 +0100 Subject: [PATCH] Test `H5WasmApi` --- .vscode/settings.json | 1 + packages/app/vite.config.js | 4 +- packages/h5wasm/create_h5_sample.py | 248 +++ packages/h5wasm/package.json | 1 + .../src/__snapshots__/h5wasm-api.test.ts.snap | 1918 +++++++++++++++++ packages/h5wasm/src/h5wasm-api.test.ts | 64 + packages/h5wasm/src/h5wasm-api.ts | 12 +- packages/h5wasm/vite.config.js | 5 + pnpm-lock.yaml | 3 + 9 files changed, 2248 insertions(+), 8 deletions(-) create mode 100644 packages/h5wasm/create_h5_sample.py create mode 100644 packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap create mode 100644 packages/h5wasm/src/h5wasm-api.test.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index a75f82f8a..99d674865 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "css.validate": false, "editor.defaultFormatter": "esbenp.prettier-vscode", + "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" }, "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" diff --git a/packages/app/vite.config.js b/packages/app/vite.config.js index 54ce81453..938746c78 100644 --- a/packages/app/vite.config.js +++ b/packages/app/vite.config.js @@ -38,9 +38,7 @@ export default defineProject({ restoreMocks: true, testTimeout: 15_000, server: { - deps: { - inline: ['react-suspense-fetch'], - }, + deps: { inline: ['react-suspense-fetch'] }, }, }, }); diff --git a/packages/h5wasm/create_h5_sample.py b/packages/h5wasm/create_h5_sample.py new file mode 100644 index 000000000..0bfaf49f1 --- /dev/null +++ b/packages/h5wasm/create_h5_sample.py @@ -0,0 +1,248 @@ +import os +import sys +import h5py +import numpy as np + +if sys.version_info.major < 3: + raise RuntimeError("Python 2 is not supported") + +BASE_PATH = os.path.dirname(os.path.realpath(sys.argv[0])) +DIST_PATH = os.path.join(BASE_PATH, "dist-h5") +os.makedirs(DIST_PATH, exist_ok=True) + +h5py.get_config().track_order = True + + +def add_empty(group, name, dtype=None): + dataset = group.create_dataset(name + "_empty", data=h5py.Empty(dtype)) + return dataset + + +def add_scalar(group, name, data=None, dtype=None): + dataset = group.create_dataset(name + "_scalar", (), dtype, data) + return dataset + + +def add_array(group, name, data=None, dtype=None, shape=None): + dataset = group.create_dataset( + name + "_{0}D".format(len(shape or data.shape)), shape, dtype, data + ) + return dataset + + +def print_h5t_class(dataset): + # https://nasa.github.io/MISR-Toolkit/html/_h5_tpublic_8h_source.html + print("H5T_class=" + str(dataset.id.get_type().get_class())) + + +with h5py.File(os.path.join(DIST_PATH, "sample.h5"), "w") as h5: + # === H5T_INTEGER === + + add_scalar(h5, "int8", np.int8(np.iinfo(np.int8).min)) + add_array(h5, "int8", np.array([[0, 1, 2], [3, 4, 5]], np.int8)) + add_scalar(h5, "int16", np.int16(np.iinfo(np.int16).min)) + add_array(h5, "int16", np.array([[0, 1, 2], [3, 4, 5]], np.int16)) + add_scalar(h5, "int32", np.int32(np.iinfo(np.int32).min)) + add_scalar(h5, "int32_BE", 0, np.dtype(">i")) + add_array(h5, "int32", np.array([[0, 1, 2], [3, 4, 5]], np.int32)) + add_scalar(h5, "int64", np.int64(np.iinfo(np.int64).min)) + add_array(h5, "int64", np.array([[0, 1, 2], [3, 4, 5]], np.int64)) + + add_scalar(h5, "uint8", np.uint8(np.iinfo(np.uint8).max)) + add_array(h5, "uint8", np.array([[0, 1, 2], [3, 4, 5]], np.uint8)) + add_scalar(h5, "uint16", np.uint16(np.iinfo(np.uint16).max)) + add_array(h5, "uint16", np.array([[0, 1, 2], [3, 4, 5]], np.uint16)) + add_scalar(h5, "uint32", np.uint32(np.iinfo(np.uint32).max)) + add_array(h5, "uint32", np.array([[0, 1, 2], [3, 4, 5]], np.uint32)) + add_scalar(h5, "uint64", np.uint64(np.iinfo(np.uint64).max)) + add_array( + h5, + "uint64", + np.array( + [[[0, 1], [2, 3]], [[4, 5], [6, np.uint64(np.iinfo(np.uint64).max)]]], + np.uint64, + ), + ) + + # === H5T_FLOAT === + + add_scalar(h5, "float16", np.float16(np.finfo(np.float16).smallest_normal)) + add_array(h5, "float16", np.array([[0, 1, 2], [3, 4, 5]], np.float16)) + add_empty(h5, "float32", np.float32) + add_scalar(h5, "float32", np.float32(np.finfo(np.float32).smallest_normal)) + add_scalar(h5, "float32_BE", 0, np.dtype(">f")) + add_array(h5, "float32", np.array([[0, 1, 2], [3, 4, 5]], np.float32)) + add_scalar(h5, "float64", np.float64(np.finfo(np.float64).smallest_normal)) + + add_scalar(h5, "float64_nan", np.nan) + add_scalar(h5, "float64_inf", np.inf) + add_scalar(h5, "float64_ninf", np.NINF) + add_scalar(h5, "float64_zero", np.PZERO) + add_scalar(h5, "float64_nzero", np.NZERO) + add_scalar(h5, "float64_pi", np.pi) + add_array( + h5, + "float64", + np.array([[0, 1, np.inf, 3, 4], [3, 4, np.nan, 6, 7], [6, 7, np.NINF, 9, 10]]), + ) + + add_scalar(h5, "float128", np.float128(np.finfo(np.float128).smallest_normal)) + add_array(h5, "float128", np.array([[0, 1, 2], [3, 4, 5]], np.float128)) + + # === H5T_TIME === + + # Not supported by h5py + + # === H5T_STRING === + + add_empty(h5, "ascii_vlen", h5py.string_dtype("ascii")) + add_scalar(h5, "ascii_vlen", b"Some text") + add_scalar( + h5, + "ascii_fixed", + np.string_("Some text"), + ) + add_scalar(h5, "utf8_vlen", "Some text") + add_array(h5, "utf8_vlen", np.array(["foo", "bar", "baz"], h5py.string_dtype())) + add_scalar(h5, "utf8_fixed", "Some text", h5py.string_dtype("utf-8", 9)) + + # === H5T_BITFIELD === + + # h5py syntax unknown + + # === H5T_OPAQUE === + + add_scalar(h5, "byte_string", np.void(b"\x00\x11\x22")) + add_scalar(h5, "datetime64", np.void(np.datetime64("2019-09-22T17:38:30"))) + add_scalar(h5, "datetime64_not-a-time", np.void(np.datetime64("NaT"))) + + # === H5T_COMPOUND (and H5T_ARRAY) === + + add_scalar( + h5, + "complex64", + np.complex64( + np.finfo(np.complex64).smallest_normal + np.finfo(np.complex64).max * 1j + ), + ) + add_array( + h5, "complex64", np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]], np.complex64) + ), + add_scalar( + h5, + "complex128", + np.complex128( + np.finfo(np.complex128).smallest_normal + np.finfo(np.complex128).max * 1j + ), + ) + add_scalar(h5, "complex128_BE", 1 + 2j, np.dtype(">c16")) + add_array( + h5, "complex128", np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]], np.complex128) + ), + add_scalar( + h5, + "complex256", + np.complex256( + np.finfo(np.complex256).smallest_normal + np.finfo(np.complex256).max * 1j + ), + ) + add_array( + h5, "complex256", np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]], np.complex256) + ), + + add_scalar( + h5, + "compound", + (1, 2.0, "foo"), + [("bigint", np.int64), ("double", np.float64), ("utf-8", h5py.string_dtype())], + ) + for_ref = add_array( + h5, + "compound", + np.array( + [(1, np.nan, "foo"), (2, np.inf, "bar"), (3, np.NZERO, "baz")], + [ + ("bigint", np.int64), + ("double", np.float64), + ("utf-8", h5py.string_dtype()), + ], + ), + ) + add_scalar( + h5, + "compound_nested", + ((True, 1 + 2j),), + [("nested", [("bool", np.bool_), ("cplx", np.complex64)])], + ) + + comp = add_array( + h5, + "compound_array_vlen", + np.array( + [ + ( + np.array([0, 1], np.float32), + np.array([0], np.uint64), + ), + ( + np.array([2, 3], np.float32), + np.array([0, 1], np.uint64), + ), + ( + np.array([4, 5], np.float32), + np.array([0, 1, 2], np.uint64), + ), + ], + [("arr", np.float32, (2,)), ("vlen", h5py.vlen_dtype(np.uint64))], + ), + ) + + # === H5T_REFERENCE === + + add_scalar(h5, "reference", for_ref.ref, h5py.special_dtype(ref=h5py.Reference)) + add_scalar( + h5, + "reference_region", + for_ref.regionref[0:1], + h5py.special_dtype(ref=h5py.Reference), + ) + + # === H5T_ENUM === + + add_empty(h5, "bool", h5py.enum_dtype({"FALSE": 0, "TRUE": 1})) + add_scalar(h5, "bool_false", False) + add_scalar(h5, "bool_true", True) + add_array( + h5, "bool", np.array([[True, False, True, True], [False, False, True, False]]) + ) + + add_scalar( + h5, + "enum_uint8", + 1, + h5py.enum_dtype({"A": 0, "B": 1}), + ) + add_scalar( + h5, + "enum_int32", + 256, + h5py.enum_dtype({"A": 256, "B": 257}, np.int32), + ) + + # === H5T_VLEN === + + # https://docs.h5py.org/en/stable/special.html#arbitrary-vlen-data + scalar_vlen = add_scalar(h5, "vlen_int8", dtype=h5py.vlen_dtype(np.int8)) + scalar_vlen[()] = [0, 1] + + # https://docs.h5py.org/en/stable/special.html#arbitrary-vlen-data + scalar_vlen = add_array( + h5, "vlen_int64", shape=(3,), dtype=h5py.vlen_dtype(np.int64) + ) + scalar_vlen[0] = [0] + scalar_vlen[1] = [0, 1] + scalar_vlen[2] = [0, 1, 2] + + # === H5T_ARRAY === + + # cf. section `H5T_COMPOUND` above diff --git a/packages/h5wasm/package.json b/packages/h5wasm/package.json index 692cea8d9..298d33aef 100644 --- a/packages/h5wasm/package.json +++ b/packages/h5wasm/package.json @@ -60,6 +60,7 @@ "eslint": "8.56.0", "eslint-config-galex": "4.5.2", "react": "18.2.0", + "react-dom": "18.2.0", "rollup": "4.9.0", "rollup-plugin-dts": "6.1.0", "typescript": "5.0.4", diff --git a/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap b/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap new file mode 100644 index 000000000..f954019cf --- /dev/null +++ b/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap @@ -0,0 +1,1918 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`test file matches snapshot 1`] = ` +[ + { + "name": "int8_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 1, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 8, + }, + "value": -128, + }, + { + "name": "int8_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 1, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 8, + }, + "value": Int8Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "int16_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 2, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 16, + }, + "value": -32768, + }, + { + "name": "int16_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 2, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 16, + }, + "value": Int16Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "int32_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 4, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 32, + }, + "value": -2147483648, + }, + { + "name": "int32_BE_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": true, + "size": 4, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer", + "endianness": "big-endian", + "size": 32, + }, + "value": 0, + }, + { + "name": "int32_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 4, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 32, + }, + "value": Int32Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "int64_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 8, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 64, + }, + "value": -9223372036854776000, + }, + { + "name": "int64_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 8, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer", + "endianness": "little-endian", + "size": 64, + }, + "value": [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "uint8_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 1, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 8, + }, + "value": 255, + }, + { + "name": "uint8_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 1, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 8, + }, + "value": Uint8Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "uint16_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 2, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 16, + }, + "value": 65535, + }, + { + "name": "uint16_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 2, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 16, + }, + "value": Uint16Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "uint32_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 32, + }, + "value": 4294967295, + }, + { + "name": "uint32_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 6, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 32, + }, + "value": Uint32Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "uint64_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 0, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 64, + }, + "value": 18446744073709552000, + }, + { + "name": "uint64_3D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 8, + "type": 0, + "vlen": false, + }, + "shape": [ + 2, + 2, + 2, + ], + "type": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 64, + }, + "value": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + ], + }, + { + "name": "float16_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 2, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 16, + }, + "value": [Error: Float16 not supported], + }, + { + "name": "float16_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 2, + "total_size": 6, + "type": 1, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 16, + }, + "value": [Error: Float16 not supported], + }, + { + "name": "float32_empty", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 0, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "value": undefined, + }, + { + "name": "float32_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "value": 1.1754943508222875e-38, + }, + { + "name": "float32_BE_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 4, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "big-endian", + "size": 32, + }, + "value": 0, + }, + { + "name": "float32_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 6, + "type": 1, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "value": Float32Array [ + 0, + 1, + 2, + 3, + 4, + 5, + ], + }, + { + "name": "float64_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": 2.2250738585072014e-308, + }, + { + "name": "float64_nan_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": NaN, + }, + { + "name": "float64_inf_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": Infinity, + }, + { + "name": "float64_ninf_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": -Infinity, + }, + { + "name": "float64_zero_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": 0, + }, + { + "name": "float64_nzero_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": -0, + }, + { + "name": "float64_pi_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": 3.141592653589793, + }, + { + "name": "float64_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 15, + "type": 1, + "vlen": false, + }, + "shape": [ + 3, + 5, + ], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "value": Float64Array [ + 0, + 1, + Infinity, + 3, + 4, + 3, + 4, + NaN, + 6, + 7, + 6, + 7, + -Infinity, + 9, + 10, + ], + }, + { + "name": "float128_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 16, + "total_size": 1, + "type": 1, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + "value": [Error: Float128 not supported], + }, + { + "name": "float128_2D", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 16, + "total_size": 6, + "type": 1, + "vlen": false, + }, + "shape": [ + 2, + 3, + ], + "type": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + "value": [Error: Float128 not supported], + }, + { + "name": "ascii_vlen_empty", + "rawType": { + "cset": 0, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 0, + "type": 3, + "vlen": true, + }, + "shape": [], + "type": { + "charSet": "ASCII", + "class": "String", + }, + "value": undefined, + }, + { + "name": "ascii_vlen_scalar", + "rawType": { + "cset": 0, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 1, + "type": 3, + "vlen": true, + }, + "shape": [], + "type": { + "charSet": "ASCII", + "class": "String", + }, + "value": "Some text", + }, + { + "name": "ascii_fixed_scalar", + "rawType": { + "cset": 0, + "littleEndian": false, + "signed": false, + "size": 9, + "total_size": 1, + "type": 3, + "vlen": false, + }, + "shape": [], + "type": { + "charSet": "ASCII", + "class": "String", + "length": 9, + }, + "value": "Some text", + }, + { + "name": "utf8_vlen_scalar", + "rawType": { + "cset": 1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 1, + "type": 3, + "vlen": true, + }, + "shape": [], + "type": { + "charSet": "UTF-8", + "class": "String", + }, + "value": "Some text", + }, + { + "name": "utf8_vlen_1D", + "rawType": { + "cset": 1, + "littleEndian": true, + "signed": false, + "size": 4, + "total_size": 3, + "type": 3, + "vlen": true, + }, + "shape": [ + 3, + ], + "type": { + "charSet": "UTF-8", + "class": "String", + }, + "value": [ + "foo", + "bar", + "baz", + ], + }, + { + "name": "utf8_fixed_scalar", + "rawType": { + "cset": 1, + "littleEndian": false, + "signed": false, + "size": 9, + "total_size": 1, + "type": 3, + "vlen": false, + }, + "shape": [], + "type": { + "charSet": "UTF-8", + "class": "String", + "length": 9, + }, + "value": "Some text", + }, + { + "name": "byte_string_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 3, + "total_size": 1, + "type": 5, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 0, + 17, + 34, + ], + }, + { + "name": "datetime64_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 8, + "total_size": 1, + "type": 5, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 150, + 177, + 135, + 93, + 0, + 0, + 0, + 0, + ], + }, + { + "name": "datetime64_not-a-time_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 8, + "total_size": 1, + "type": 5, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 128, + ], + }, + { + "name": "complex64_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 4, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + }, + "value": [ + 1.1754943508222875e-38, + 3.4028234663852886e+38, + ], + }, + { + "name": "complex64_2D", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 4, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 8, + "total_size": 4, + "type": 6, + "vlen": false, + }, + "shape": [ + 2, + 2, + ], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + }, + "value": [ + [ + 1, + 2, + ], + [ + 3, + 4, + ], + [ + 5, + 6, + ], + [ + 7, + 8, + ], + ], + }, + { + "name": "complex128_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 8, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 16, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + }, + "value": [ + 2.2250738585072014e-308, + 1.7976931348623157e+308, + ], + }, + { + "name": "complex128_BE_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": false, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": false, + "name": "i", + "offset": 8, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 16, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "big-endian", + "size": 64, + }, + "realType": { + "class": "Float", + "endianness": "big-endian", + "size": 64, + }, + }, + "value": [ + 1, + 2, + ], + }, + { + "name": "complex128_2D", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 8, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 16, + "total_size": 4, + "type": 6, + "vlen": false, + }, + "shape": [ + 2, + 2, + ], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + }, + "value": [ + [ + 1, + 2, + ], + [ + 3, + 4, + ], + [ + 5, + 6, + ], + [ + 7, + 8, + ], + ], + }, + { + "name": "complex256_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 16, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 16, + "shape": [], + "signed": false, + "size": 16, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 32, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + }, + "value": [Error: Float128 not supported], + }, + { + "name": "complex256_2D", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 16, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 16, + "shape": [], + "signed": false, + "size": 16, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 32, + "total_size": 4, + "type": 6, + "vlen": false, + }, + "shape": [ + 2, + 2, + ], + "type": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 128, + }, + }, + "value": [Error: Float128 not supported], + }, + { + "name": "compound_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "bigint", + "offset": 0, + "shape": [], + "signed": true, + "size": 8, + "type": 0, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "double", + "offset": 8, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + { + "cset": 1, + "littleEndian": true, + "name": "utf-8", + "offset": 16, + "shape": [], + "signed": false, + "size": 4, + "type": 3, + "vlen": true, + }, + ], + "nmembers": 3, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 20, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Compound", + "fields": { + "bigint": { + "class": "Integer", + "endianness": "little-endian", + "size": 64, + }, + "double": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "utf-8": { + "charSet": "UTF-8", + "class": "String", + }, + }, + }, + "value": [ + 1, + 2, + "foo", + ], + }, + { + "name": "compound_1D", + "rawType": { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "bigint", + "offset": 0, + "shape": [], + "signed": true, + "size": 8, + "type": 0, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "double", + "offset": 8, + "shape": [], + "signed": false, + "size": 8, + "type": 1, + "vlen": false, + }, + { + "cset": 1, + "littleEndian": true, + "name": "utf-8", + "offset": 16, + "shape": [], + "signed": false, + "size": 4, + "type": 3, + "vlen": true, + }, + ], + "nmembers": 3, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 20, + "total_size": 3, + "type": 6, + "vlen": false, + }, + "shape": [ + 3, + ], + "type": { + "class": "Compound", + "fields": { + "bigint": { + "class": "Integer", + "endianness": "little-endian", + "size": 64, + }, + "double": { + "class": "Float", + "endianness": "little-endian", + "size": 64, + }, + "utf-8": { + "charSet": "UTF-8", + "class": "String", + }, + }, + }, + "value": [ + [ + 1, + NaN, + "foo", + ], + [ + 2, + Infinity, + "bar", + ], + [ + 3, + -0, + "baz", + ], + ], + }, + { + "name": "compound_nested_scalar", + "rawType": { + "compound_type": { + "members": [ + { + "compound_type": { + "members": [ + { + "cset": -1, + "enum_type": { + "members": { + "FALSE": 0, + "TRUE": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "name": "bool", + "offset": 0, + "shape": [], + "signed": true, + "size": 1, + "type": 8, + "vlen": false, + }, + { + "compound_type": { + "members": [ + { + "cset": -1, + "littleEndian": true, + "name": "r", + "offset": 0, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + { + "cset": -1, + "littleEndian": true, + "name": "i", + "offset": 4, + "shape": [], + "signed": false, + "size": 4, + "type": 1, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "name": "cplx", + "offset": 1, + "shape": [], + "signed": false, + "size": 8, + "type": 6, + "vlen": false, + }, + ], + "nmembers": 2, + }, + "cset": -1, + "littleEndian": true, + "name": "nested", + "offset": 0, + "shape": [], + "signed": false, + "size": 9, + "type": 6, + "vlen": false, + }, + ], + "nmembers": 1, + }, + "cset": -1, + "littleEndian": true, + "signed": false, + "size": 9, + "total_size": 1, + "type": 6, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Compound", + "fields": { + "nested": { + "class": "Compound", + "fields": { + "bool": { + "class": "Boolean", + }, + "cplx": { + "class": "Complex", + "imagType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + "realType": { + "class": "Float", + "endianness": "little-endian", + "size": 32, + }, + }, + }, + }, + }, + }, + "value": [ + [ + true, + [ + 1, + 2, + ], + ], + ], + }, + { + "name": "reference_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 8, + "total_size": 1, + "type": 7, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 214, + 91, + 0, + 0, + 0, + 0, + 0, + 0, + ], + }, + { + "name": "reference_region_scalar", + "rawType": { + "cset": -1, + "littleEndian": false, + "signed": false, + "size": 8, + "total_size": 1, + "type": 7, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 34, + 56, + 0, + 0, + 0, + 0, + 0, + 0, + ], + }, + { + "name": "bool_empty", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "FALSE": 0, + "TRUE": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": false, + "size": 1, + "total_size": 0, + "type": 8, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Boolean", + }, + "value": false, + }, + { + "name": "bool_false_scalar", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "FALSE": 0, + "TRUE": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": true, + "size": 1, + "total_size": 1, + "type": 8, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Boolean", + }, + "value": false, + }, + { + "name": "bool_true_scalar", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "FALSE": 0, + "TRUE": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": true, + "size": 1, + "total_size": 1, + "type": 8, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Boolean", + }, + "value": true, + }, + { + "name": "bool_2D", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "FALSE": 0, + "TRUE": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": true, + "size": 1, + "total_size": 8, + "type": 8, + "vlen": false, + }, + "shape": [ + 2, + 4, + ], + "type": { + "class": "Boolean", + }, + "value": [ + true, + false, + true, + true, + false, + false, + true, + false, + ], + }, + { + "name": "enum_uint8_scalar", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "A": 0, + "B": 1, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": false, + "size": 1, + "total_size": 1, + "type": 8, + "vlen": false, + }, + "shape": [], + "type": { + "base": { + "class": "Integer (unsigned)", + "endianness": "little-endian", + "size": 8, + }, + "class": "Enumeration", + "mapping": { + "A": 0, + "B": 1, + }, + }, + "value": 1, + }, + { + "name": "enum_int32_scalar", + "rawType": { + "cset": -1, + "enum_type": { + "members": { + "A": 256, + "B": 257, + }, + "nmembers": 2, + "type": 0, + }, + "littleEndian": true, + "signed": true, + "size": 4, + "total_size": 1, + "type": 8, + "vlen": false, + }, + "shape": [], + "type": { + "base": { + "class": "Integer", + "endianness": "little-endian", + "size": 32, + }, + "class": "Enumeration", + "mapping": { + "A": 256, + "B": 257, + }, + }, + "value": 256, + }, + { + "name": "vlen_int8_scalar", + "rawType": { + "cset": -1, + "littleEndian": true, + "signed": true, + "size": 8, + "total_size": 1, + "type": 9, + "vlen": false, + }, + "shape": [], + "type": { + "class": "Unknown", + }, + "value": Uint8Array [ + 2, + 0, + 0, + 0, + 184, + 128, + 34, + 0, + ], + }, +] +`; diff --git a/packages/h5wasm/src/h5wasm-api.test.ts b/packages/h5wasm/src/h5wasm-api.test.ts new file mode 100644 index 000000000..42dc4a1b6 --- /dev/null +++ b/packages/h5wasm/src/h5wasm-api.test.ts @@ -0,0 +1,64 @@ +import { + assertDataset, + assertGroup, + assertGroupWithChildren, + hasNonNullShape, +} from '@h5web/shared/guards'; +import type { + ArrayShape, + Dataset, + ScalarShape, +} from '@h5web/shared/hdf5-models'; +import { existsSync } from 'fs'; +import { readFile } from 'fs/promises'; +import path from 'path'; +import { expect, test } from 'vitest'; + +import { H5WasmApi } from './h5wasm-api'; + +const LOCAL_TEST_FILE = path.resolve(__dirname, '../dist-h5/sample.h5'); +const REMOTE_TEST_FILE = 'http://www.silx.org/pub/h5web/sample.h5'; // `https` would complicate things... + +async function loadTestFile(): Promise { + if (existsSync(LOCAL_TEST_FILE)) { + return readFile(LOCAL_TEST_FILE); + } + + const resp = await fetch(REMOTE_TEST_FILE); + return resp.arrayBuffer(); +} + +async function getValueOrError( + api: H5WasmApi, + dataset: Dataset, +): Promise { + try { + return await api.getValue({ dataset }); + } catch (error) { + return error; + } +} + +test('test file matches snapshot', async () => { + const buffer = await loadTestFile(); + const api = new H5WasmApi('sample.h5', buffer); + + const root = await api.getEntity('/'); + assertGroup(root); + assertGroupWithChildren(root); + + const children = await Promise.all( + root.children.map(async (child) => { + assertDataset(child); + const { name, shape, type, rawType } = child; + + const value = hasNonNullShape(child) + ? await getValueOrError(api, child) + : null; + + return { name, shape, type, rawType, value }; + }), + ); + + expect(children).toMatchSnapshot(); +}); diff --git a/packages/h5wasm/src/h5wasm-api.ts b/packages/h5wasm/src/h5wasm-api.ts index 9fb0cdbd1..444cf510d 100644 --- a/packages/h5wasm/src/h5wasm-api.ts +++ b/packages/h5wasm/src/h5wasm-api.ts @@ -256,16 +256,18 @@ export class H5WasmApi extends DataProviderApi { } if (isH5WasmDataset(h5wEntity)) { - const { shape, metadata, dtype, filters } = h5wEntity; + const { metadata, filters } = h5wEntity; + const { chunks, maxshape, shape, ...rawType } = metadata; // keep `rawType` concise + return { ...baseEntity, - chunks: metadata.chunks ?? undefined, kind: EntityKind.Dataset, - attributes: this.processH5WasmAttrs(h5wEntity.attrs), - shape, + shape: metadata.shape, type: convertMetadataToDType(metadata), - rawType: dtype, + chunks: metadata.chunks ?? undefined, filters, + attributes: this.processH5WasmAttrs(h5wEntity.attrs), + rawType, }; } diff --git a/packages/h5wasm/vite.config.js b/packages/h5wasm/vite.config.js index dc7e990f9..97df3adb9 100644 --- a/packages/h5wasm/vite.config.js +++ b/packages/h5wasm/vite.config.js @@ -31,4 +31,9 @@ export default defineProject({ }, sourcemap: true, }, + test: { + server: { + deps: { inline: ['react-suspense-fetch'] }, + }, + }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c0443de1..2e3583b2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -399,6 +399,9 @@ importers: react: specifier: 18.2.0 version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) rollup: specifier: 4.9.0 version: 4.9.0