From bd165352b076c7150d1a8354753f14be97e22cf2 Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Mon, 20 Jan 2025 13:22:14 +0100 Subject: [PATCH] Merge signed and unsigned integer types --- packages/app/src/metadata-viewer/utils.ts | 11 +++- .../__snapshots__/h5grove-api.test.ts.snap | 58 ++++++++++++++----- .../app/src/providers/h5grove/utils.test.ts | 9 ++- packages/app/src/providers/h5grove/utils.ts | 6 +- packages/app/src/providers/hsds/utils.test.ts | 7 +-- packages/app/src/providers/hsds/utils.ts | 7 +-- packages/app/src/providers/mock/mock-file.ts | 33 ++++++----- packages/app/src/providers/utils.ts | 27 ++++----- packages/app/src/vis-packs/core/utils.ts | 7 ++- .../src/vis-packs/core/visualizations.test.ts | 13 ++--- .../src/__snapshots__/h5wasm-api.test.ts.snap | 58 ++++++++++++++----- packages/h5wasm/src/utils.ts | 5 +- packages/h5wasm/src/worker-utils.ts | 13 ++--- packages/shared/src/guards.ts | 15 +++-- packages/shared/src/hdf5-models.ts | 13 ++++- packages/shared/src/hdf5-utils.ts | 29 +++------- packages/shared/src/mock-utils.ts | 2 +- 17 files changed, 187 insertions(+), 126 deletions(-) diff --git a/packages/app/src/metadata-viewer/utils.ts b/packages/app/src/metadata-viewer/utils.ts index 88c40541d..c8a4061cd 100644 --- a/packages/app/src/metadata-viewer/utils.ts +++ b/packages/app/src/metadata-viewer/utils.ts @@ -1,5 +1,6 @@ import { isH5WebComplex, + isIntegerType, isNumericType, isScalarShape, } from '@h5web/shared/guards'; @@ -29,7 +30,15 @@ export function renderShape(shape: Shape): string { export function renderType(type: DType): string { if (isNumericType(type)) { const { endianness, size } = type; - return `${type.class}, ${size}-bit${endianness ? `, ${endianness}` : ''}`; + + const endiannessStr = endianness ? `, ${endianness}` : ''; + const signStr = isIntegerType(type) + ? type.signed + ? ' (signed)' + : ' (unsigned)' + : ''; + + return `${type.class}${signStr}, ${size}-bit${endiannessStr}`; } if (type.class === DTypeClass.String) { diff --git a/packages/app/src/providers/h5grove/__snapshots__/h5grove-api.test.ts.snap b/packages/app/src/providers/h5grove/__snapshots__/h5grove-api.test.ts.snap index 93bddc039..956f9e271 100644 --- a/packages/app/src/providers/h5grove/__snapshots__/h5grove-api.test.ts.snap +++ b/packages/app/src/providers/h5grove/__snapshots__/h5grove-api.test.ts.snap @@ -15,6 +15,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "value": -128, @@ -35,6 +36,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "value": Int8Array [ @@ -59,6 +61,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 16, }, "value": -32768, @@ -79,6 +82,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 16, }, "value": Int16Array [ @@ -103,6 +107,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "value": -2147483648, @@ -120,6 +125,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "big-endian", + "signed": true, "size": 32, }, "value": 0, @@ -140,6 +146,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "value": Int32Array [ @@ -164,6 +171,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "value": -9223372036854776000, @@ -184,6 +192,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "value": [ @@ -206,8 +215,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "value": 255, @@ -226,8 +236,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "value": Uint8Array [ @@ -250,8 +261,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 16, }, "value": 65535, @@ -270,8 +282,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 16, }, "value": Uint16Array [ @@ -294,8 +307,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 32, }, "value": 4294967295, @@ -314,8 +328,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 32, }, "value": Uint32Array [ @@ -338,8 +353,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "value": 18446744073709552000, @@ -359,8 +375,9 @@ exports[`test file matches snapshot 1`] = ` 2, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "value": [ @@ -1255,6 +1272,7 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "double": { @@ -1318,6 +1336,7 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "double": { @@ -1428,12 +1447,14 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "bool": { "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1523,8 +1544,9 @@ exports[`test file matches snapshot 1`] = ` }, "vlen": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "class": "Array (variable length)", @@ -1611,8 +1633,9 @@ exports[`test file matches snapshot 1`] = ` "shape": null, "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Boolean", @@ -1642,6 +1665,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1671,6 +1695,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1703,6 +1728,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1739,8 +1765,9 @@ exports[`test file matches snapshot 1`] = ` "shape": [], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -1774,6 +1801,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "class": "Enumeration", @@ -1808,8 +1836,9 @@ exports[`test file matches snapshot 1`] = ` ], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -1857,8 +1886,9 @@ exports[`test file matches snapshot 1`] = ` ], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -1910,6 +1940,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Array (variable length)", @@ -1971,6 +2002,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "class": "Array (variable length)", diff --git a/packages/app/src/providers/h5grove/utils.test.ts b/packages/app/src/providers/h5grove/utils.test.ts index ce30416e0..6ea6b521f 100644 --- a/packages/app/src/providers/h5grove/utils.test.ts +++ b/packages/app/src/providers/h5grove/utils.test.ts @@ -12,7 +12,6 @@ import { referenceType, strType, timeType, - uintType, unknownType, } from '@h5web/shared/hdf5-utils'; import { describe, expect, it } from 'vitest'; @@ -23,10 +22,10 @@ import { parseDType } from './utils'; describe('parseDType', () => { it('should convert integer types', () => { expect(parseDType({ class: 0, size: 1, order: 0, sign: 1 })).toStrictEqual( - intType(8, H5T_ORDER.LE), + intType(true, 8, H5T_ORDER.LE), ); expect(parseDType({ class: 0, size: 8, order: 1, sign: 0 })).toStrictEqual( - uintType(64, H5T_ORDER.BE), + intType(false, 64, H5T_ORDER.BE), ); }); @@ -83,7 +82,7 @@ describe('parseDType', () => { base: { class: 0, size: 4, order: 0, sign: 0 }, members: { FOO: 41, BAR: 42 }, }), - ).toStrictEqual(enumType(uintType(), { FOO: 41, BAR: 42 })); + ).toStrictEqual(enumType(intType(false), { FOO: 41, BAR: 42 })); expect( parseDType({ @@ -92,7 +91,7 @@ describe('parseDType', () => { base: { class: 0, size: 1, order: 0, sign: 1 }, members: { FALSE: 0, TRUE: 1 }, }), - ).toStrictEqual(boolType(intType(8))); + ).toStrictEqual(boolType(intType(true, 8))); }); it('should convert array types', () => { diff --git a/packages/app/src/providers/h5grove/utils.ts b/packages/app/src/providers/h5grove/utils.ts index 375a19f5b..60f657f10 100644 --- a/packages/app/src/providers/h5grove/utils.ts +++ b/packages/app/src/providers/h5grove/utils.ts @@ -1,5 +1,5 @@ import { isNumericType } from '@h5web/shared/guards'; -import { H5T_CLASS } from '@h5web/shared/h5t'; +import { H5T_CLASS, H5T_SIGN } from '@h5web/shared/h5t'; import { type Attribute, type ChildEntity, @@ -16,7 +16,7 @@ import { compoundOrCplxType, enumOrBoolType, floatType, - intOrUintType, + intType, opaqueType, referenceType, strType, @@ -162,7 +162,7 @@ export function parseDType(type: H5GroveType): DType { const { class: h5tClass, size } = type; if (h5tClass === H5T_CLASS.INTEGER) { - return intOrUintType(type.sign, size * 8, type.order); + return intType(type.sign === H5T_SIGN.SIGN_2, size * 8, type.order); } if (h5tClass === H5T_CLASS.FLOAT) { diff --git a/packages/app/src/providers/hsds/utils.test.ts b/packages/app/src/providers/hsds/utils.test.ts index 446ab060e..a6fbda6d5 100644 --- a/packages/app/src/providers/hsds/utils.test.ts +++ b/packages/app/src/providers/hsds/utils.test.ts @@ -8,7 +8,6 @@ import { floatType, intType, strType, - uintType, unknownType, } from '@h5web/shared/hdf5-utils'; import { describe, expect, it } from 'vitest'; @@ -29,12 +28,12 @@ interface TestType { const leInt = { hsds: { class: 'H5T_INTEGER', base: 'H5T_STD_I8LE' }, - hdf5: intType(8, H5T_ORDER.LE), + hdf5: intType(true, 8, H5T_ORDER.LE), } satisfies TestType; const beUint = { hsds: { class: 'H5T_INTEGER', base: 'H5T_STD_U64BE' }, - hdf5: uintType(64, H5T_ORDER.BE), + hdf5: intType(false, 64, H5T_ORDER.BE), } satisfies TestType; const leFloat = { @@ -130,7 +129,7 @@ describe('convertHsdsType', () => { mapping: { FALSE: 0, TRUE: 1 }, }; - expect(convertHsdsType(boolEnum)).toStrictEqual(boolType(intType(8))); + expect(convertHsdsType(boolEnum)).toStrictEqual(boolType(intType(true, 8))); }); it('should convert the complex compound type into Complex type', () => { diff --git a/packages/app/src/providers/hsds/utils.ts b/packages/app/src/providers/hsds/utils.ts index 61b09be1c..602b51d38 100644 --- a/packages/app/src/providers/hsds/utils.ts +++ b/packages/app/src/providers/hsds/utils.ts @@ -23,7 +23,6 @@ import { floatType, intType, strType, - uintType, unknownType, } from '@h5web/shared/hdf5-utils'; @@ -88,11 +87,7 @@ function convertHsdsNumericType(hsdsType: HsdsNumericType): NumericType { return floatType(size, h5tOrder); } - if (sign === 'U') { - return uintType(size, h5tOrder); - } - - return intType(size, h5tOrder); + return intType(sign === 'I', size, h5tOrder); } function convertHsdsCompoundType( diff --git a/packages/app/src/providers/mock/mock-file.ts b/packages/app/src/providers/mock/mock-file.ts index 903cff783..fc1716027 100644 --- a/packages/app/src/providers/mock/mock-file.ts +++ b/packages/app/src/providers/mock/mock-file.ts @@ -12,7 +12,6 @@ import { opaqueType, printableCompoundType, strType, - uintType, unknownType, } from '@h5web/shared/hdf5-utils'; import { @@ -70,13 +69,13 @@ export function makeMockFile(): GroupWithChildren { scalar('scalar_compound', ['foo', 2], { type: compoundType({ str: strType(H5T_CSET.ASCII, H5T_STR.NULLPAD, 3), - int: intType(8), + int: intType(true, 8), }), attributes: [ scalarAttr('attr', ['foo', 2], { type: compoundType({ str: strType(H5T_CSET.UTF8), - int: intType(8), + int: intType(true, 8), }), }), ], @@ -94,10 +93,10 @@ export function makeMockFile(): GroupWithChildren { ], }), scalar('scalar_enum', 2, { - type: enumType(uintType(8), ENUM_MAPPING), + type: enumType(intType(false, 8), ENUM_MAPPING), attributes: [ scalarAttr('attr', 2, { - type: enumType(uintType(8), ENUM_MAPPING), + type: enumType(intType(false, 8), ENUM_MAPPING), }), ], }), @@ -120,12 +119,14 @@ export function makeMockFile(): GroupWithChildren { string: strType(), int: intType(), float: floatType(), - bool: boolType(intType(8)), + bool: boolType(intType(true, 8)), complex: cplxType(floatType()), }), }), array('oneD_bool'), - array('oneD_enum', { type: enumType(uintType(8), ENUM_MAPPING) }), + array('oneD_enum', { + type: enumType(intType(false, 8), ENUM_MAPPING), + }), array('twoD'), array('twoD_bigint'), array('twoD_cplx'), @@ -134,12 +135,14 @@ export function makeMockFile(): GroupWithChildren { string: strType(), int: intType(), float: floatType(), - bool: boolType(intType(8)), + bool: boolType(intType(true, 8)), complex: cplxType(floatType()), }), }), array('twoD_bool'), - array('twoD_enum', { type: enumType(uintType(8), ENUM_MAPPING) }), + array('twoD_enum', { + type: enumType(intType(false, 8), ENUM_MAPPING), + }), array('threeD'), array('threeD_bool'), array('threeD_cplx'), @@ -147,13 +150,13 @@ export function makeMockFile(): GroupWithChildren { array('fourD'), ]), group('typed_arrays', [ - array('uint8', { type: uintType(8) }), - array('int16', { type: intType(16) }), + array('uint8', { type: intType(false, 8) }), + array('int16', { type: intType(true, 16) }), array('float32', { type: floatType(32) }), array('float64', { type: floatType(64) }), - withImageAttr(array('uint8_rgb', { type: uintType(8) })), - withImageAttr(array('int8_rgb', { type: intType(8) })), - withImageAttr(array('int32_rgb', { type: intType(32) })), + withImageAttr(array('uint8_rgb', { type: intType(false, 8) })), + withImageAttr(array('int8_rgb', { type: intType(true, 8) })), + withImageAttr(array('int32_rgb', { type: intType(true, 32) })), withImageAttr(array('float32_rgb', { type: floatType(32) })), ]), nxGroup('nexus_entry', 'NXentry', { @@ -284,7 +287,7 @@ export function makeMockFile(): GroupWithChildren { nxData('bool', { signal: array('twoD_bool') }), nxData('enum', { signal: array('twoD_enum', { - type: enumType(uintType(8), ENUM_MAPPING), + type: enumType(intType(false, 8), ENUM_MAPPING), }), }), ], diff --git a/packages/app/src/providers/utils.ts b/packages/app/src/providers/utils.ts index 07107188b..c21fec426 100644 --- a/packages/app/src/providers/utils.ts +++ b/packages/app/src/providers/utils.ts @@ -1,9 +1,13 @@ -import { isBoolType, isEnumType, isNumericType } from '@h5web/shared/guards'; +import { + isBoolType, + isEnumType, + isFloatType, + isIntegerType, +} from '@h5web/shared/guards'; import { type ArrayShape, type Dataset, type DType, - DTypeClass, type ScalarShape, } from '@h5web/shared/hdf5-models'; import { type OnProgress } from '@h5web/shared/react-suspense-fetch'; @@ -21,15 +25,8 @@ export function typedArrayFromDType( return typedArrayFromDType(dtype.base); } - if (!isNumericType(dtype)) { - return undefined; - } - - /* Adapted from https://github.com/ludwigschubert/js-numpy-parser/blob/v1.2.3/src/main.js#L116 */ - const { class: dtypeClass, size } = dtype; - - if (dtypeClass === DTypeClass.Integer) { - switch (size) { + if (isIntegerType(dtype) && dtype.signed) { + switch (dtype.size) { case 8: return Int8Array; case 16: @@ -41,8 +38,8 @@ export function typedArrayFromDType( } } - if (dtypeClass === DTypeClass.Unsigned) { - switch (size) { + if (isIntegerType(dtype) && !dtype.signed) { + switch (dtype.size) { case 8: return Uint8Array; case 16: @@ -54,8 +51,8 @@ export function typedArrayFromDType( } } - if (dtypeClass === DTypeClass.Float) { - switch (size) { + if (isFloatType(dtype)) { + switch (dtype.size) { case 16: // No support for 16-bit floating values in JS return undefined; case 32: diff --git a/packages/app/src/vis-packs/core/utils.ts b/packages/app/src/vis-packs/core/utils.ts index 54955b6d3..1e6ef9545 100644 --- a/packages/app/src/vis-packs/core/utils.ts +++ b/packages/app/src/vis-packs/core/utils.ts @@ -1,5 +1,5 @@ import { type InteractionInfo } from '@h5web/lib'; -import { isNumericType } from '@h5web/shared/guards'; +import { isIntegerType, isNumericType } from '@h5web/shared/guards'; import { type ArrayValue, DTypeClass, @@ -107,10 +107,11 @@ const TYPE_STRINGS: Record = { [DTypeClass.Bool]: 'bool', [DTypeClass.Enum]: 'enum', [DTypeClass.Integer]: 'int', - [DTypeClass.Unsigned]: 'uint', [DTypeClass.Float]: 'float', }; export function formatNumLikeType(type: NumericLikeType): string { - return `${TYPE_STRINGS[type.class]}${isNumericType(type) ? type.size : ''}`; + const unsignedPrefix = isIntegerType(type) && !type.signed ? 'u' : ''; + const sizeSuffix = isNumericType(type) ? type.size : ''; + return `${unsignedPrefix}${TYPE_STRINGS[type.class]}${sizeSuffix}`; } diff --git a/packages/app/src/vis-packs/core/visualizations.test.ts b/packages/app/src/vis-packs/core/visualizations.test.ts index 3386d287c..f98b8cbf1 100644 --- a/packages/app/src/vis-packs/core/visualizations.test.ts +++ b/packages/app/src/vis-packs/core/visualizations.test.ts @@ -6,7 +6,6 @@ import { floatType, intType, strType, - uintType, } from '@h5web/shared/hdf5-utils'; import { assertMockAttribute, @@ -31,20 +30,20 @@ const mockStore = { }; const scalarInt = dataset('int', intType(), []); -const scalarUint = dataset('uint', uintType(), []); +const scalarUint = dataset('uint', intType(false), []); const scalarFloat = dataset('float', floatType(), []); const scalarStr = dataset('float', strType(), []); -const scalarBool = dataset('bool', boolType(intType(8)), []); +const scalarBool = dataset('bool', boolType(intType(true, 8)), []); const scalarCplx = dataset('cplx', cplxType(floatType()), []); const scalarCompound = dataset('comp', compoundType({ int: intType() }), []); const oneDInt = dataset('int_1d', intType(), [5]); -const oneDUint = dataset('uint_1d', uintType(), [5]); -const oneDBool = dataset('bool_1d', boolType(intType(8)), [3]); +const oneDUint = dataset('uint_1d', intType(false), [5]); +const oneDBool = dataset('bool_1d', boolType(intType(true, 8)), [3]); const oneDCplx = dataset('cplx_1d', cplxType(floatType()), [10]); const oneDCompound = dataset('comp_1d', compoundType({ int: intType() }), [5]); const twoDInt = dataset('int_2d', intType(), [5, 3]); -const twoDUint = dataset('uint_2d', uintType(), [5, 3]); -const twoDBool = dataset('bool_2d', boolType(intType(8)), [3, 2]); +const twoDUint = dataset('uint_2d', intType(false), [5, 3]); +const twoDBool = dataset('bool_2d', boolType(intType(true, 8)), [3, 2]); const twoDCplx = dataset('cplx_2d', cplxType(floatType()), [2, 2]); const twoDStr = dataset('str_2d', strType(), [5, 3]); const threeDFloat = dataset('float_3d', intType(), [5, 3, 1]); diff --git a/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap b/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap index 81aa9af8e..cd6283d03 100644 --- a/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap +++ b/packages/h5wasm/src/__snapshots__/h5wasm-api.test.ts.snap @@ -16,6 +16,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "value": -128, @@ -37,6 +38,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "value": Int8Array [ @@ -62,6 +64,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 16, }, "value": -32768, @@ -83,6 +86,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 16, }, "value": Int16Array [ @@ -108,6 +112,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "value": -2147483648, @@ -126,6 +131,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "big-endian", + "signed": true, "size": 32, }, "value": 0, @@ -147,6 +153,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "value": Int32Array [ @@ -172,6 +179,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "value": -9223372036854776000, @@ -193,6 +201,7 @@ exports[`test file matches snapshot 1`] = ` "type": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "value": [ @@ -216,8 +225,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "value": 255, @@ -237,8 +247,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "value": Uint8Array [ @@ -262,8 +273,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 16, }, "value": 65535, @@ -283,8 +295,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 16, }, "value": Uint16Array [ @@ -308,8 +321,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 32, }, "value": 4294967295, @@ -329,8 +343,9 @@ exports[`test file matches snapshot 1`] = ` 3, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 32, }, "value": Uint32Array [ @@ -354,8 +369,9 @@ exports[`test file matches snapshot 1`] = ` }, "shape": [], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "value": 18446744073709552000, @@ -376,8 +392,9 @@ exports[`test file matches snapshot 1`] = ` 2, ], "type": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "value": [ @@ -1401,6 +1418,7 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "double": { @@ -1477,6 +1495,7 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "double": { @@ -1612,12 +1631,14 @@ exports[`test file matches snapshot 1`] = ` "bigint": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "bool": { "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1722,8 +1743,9 @@ exports[`test file matches snapshot 1`] = ` }, "vlen": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 64, }, "class": "Array (variable length)", @@ -1818,8 +1840,9 @@ exports[`test file matches snapshot 1`] = ` "shape": null, "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Boolean", @@ -1849,6 +1872,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1878,6 +1902,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1910,6 +1935,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Boolean", @@ -1946,8 +1972,9 @@ exports[`test file matches snapshot 1`] = ` "shape": [], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -1981,6 +2008,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 32, }, "class": "Enumeration", @@ -2015,8 +2043,9 @@ exports[`test file matches snapshot 1`] = ` ], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -2064,8 +2093,9 @@ exports[`test file matches snapshot 1`] = ` ], "type": { "base": { - "class": "Integer (unsigned)", + "class": "Integer", "endianness": "little-endian", + "signed": false, "size": 8, }, "class": "Enumeration", @@ -2120,6 +2150,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 8, }, "class": "Array (variable length)", @@ -2188,6 +2219,7 @@ exports[`test file matches snapshot 1`] = ` "base": { "class": "Integer", "endianness": "little-endian", + "signed": true, "size": 64, }, "class": "Array (variable length)", diff --git a/packages/h5wasm/src/utils.ts b/packages/h5wasm/src/utils.ts index 7e50e3a4c..606aabc41 100644 --- a/packages/h5wasm/src/utils.ts +++ b/packages/h5wasm/src/utils.ts @@ -28,10 +28,7 @@ export function hasBigInts(type: DType): boolean { return Object.values(type.fields).some(hasBigInts); } - return ( - (type.class === DTypeClass.Integer || type.class === DTypeClass.Unsigned) && - type.size === 64 - ); + return type.class === DTypeClass.Integer && type.size === 64; } export function sanitizeBigInts(value: unknown): unknown { diff --git a/packages/h5wasm/src/worker-utils.ts b/packages/h5wasm/src/worker-utils.ts index 0568a9068..647864e5b 100644 --- a/packages/h5wasm/src/worker-utils.ts +++ b/packages/h5wasm/src/worker-utils.ts @@ -3,12 +3,7 @@ import { assertNonNull, isNumericType, } from '@h5web/shared/guards'; -import { - H5T_CLASS, - H5T_ORDER, - H5T_SIGN, - type H5T_STR, -} from '@h5web/shared/h5t'; +import { H5T_CLASS, H5T_ORDER, type H5T_STR } from '@h5web/shared/h5t'; import { type Attribute, type ChildEntity, @@ -26,7 +21,7 @@ import { enumOrBoolType, floatType, getNameFromPath, - intOrUintType, + intType, opaqueType, referenceType, strType, @@ -221,8 +216,8 @@ function parseDType(metadata: Metadata): DType { if (h5tClass === H5T_CLASS.INTEGER) { const { signed, littleEndian } = metadata; - return intOrUintType( - signed ? H5T_SIGN.SIGN_2 : H5T_SIGN.NONE, + return intType( + signed, size * 8, littleEndian ? H5T_ORDER.LE : H5T_ORDER.BE, ); diff --git a/packages/shared/src/guards.ts b/packages/shared/src/guards.ts index fce963fe7..132e79518 100644 --- a/packages/shared/src/guards.ts +++ b/packages/shared/src/guards.ts @@ -13,9 +13,11 @@ import { type Entity, EntityKind, type EnumType, + type FloatType, type Group, type GroupWithChildren, type H5WebComplex, + type IntegerType, type NumericLikeType, type NumericType, type Primitive, @@ -34,7 +36,6 @@ import { import { AXIS_SCALE_TYPES, COLOR_SCALE_TYPES, getValues } from './vis-utils'; const PRINTABLE_DTYPES = new Set([ - DTypeClass.Unsigned, DTypeClass.Integer, DTypeClass.Float, DTypeClass.String, @@ -294,10 +295,16 @@ export function assertStringType( } } +export function isIntegerType(type: DType): type is IntegerType { + return type.class === DTypeClass.Integer; +} + +export function isFloatType(type: DType): type is FloatType { + return type.class === DTypeClass.Float; +} + export function isNumericType(type: DType): type is NumericType { - return [DTypeClass.Integer, DTypeClass.Unsigned, DTypeClass.Float].includes( - type.class, - ); + return isIntegerType(type) || isFloatType(type); } export function hasNumericType( diff --git a/packages/shared/src/hdf5-models.ts b/packages/shared/src/hdf5-models.ts index 8b615954a..c695f6366 100644 --- a/packages/shared/src/hdf5-models.ts +++ b/packages/shared/src/hdf5-models.ts @@ -102,7 +102,6 @@ export type ScalarShape = []; export enum DTypeClass { Bool = 'Boolean', Integer = 'Integer', - Unsigned = 'Integer (unsigned)', Float = 'Float', Complex = 'Complex', String = 'String', @@ -121,6 +120,7 @@ export type Endianness = (typeof H5T_TO_ENDIANNESS)[H5T_ORDER]; export type CharSet = (typeof H5T_TO_CHAR_SET)[H5T_CSET]; export type StrPad = (typeof H5T_TO_STR_PAD)[H5T_STR]; +export type NumericType = IntegerType | FloatType; export type NumericLikeType = NumericType | BooleanType | EnumType; export type PrintableType = StringType | NumericLikeType | ComplexType; @@ -134,8 +134,15 @@ export type DType = | ReferenceType | UnknownType; -export interface NumericType { - class: DTypeClass.Integer | DTypeClass.Unsigned | DTypeClass.Float; +export interface IntegerType { + class: DTypeClass.Integer; + signed: boolean; + size: number; + endianness: Endianness | undefined; +} + +export interface FloatType { + class: DTypeClass.Float; size: number; endianness: Endianness | undefined; } diff --git a/packages/shared/src/hdf5-utils.ts b/packages/shared/src/hdf5-utils.ts index b3e8c1010..8801cf7f3 100644 --- a/packages/shared/src/hdf5-utils.ts +++ b/packages/shared/src/hdf5-utils.ts @@ -2,7 +2,6 @@ import { isNumericType } from './guards'; import { H5T_CSET, H5T_ORDER, - H5T_SIGN, H5T_STR, H5T_TO_CHAR_SET, H5T_TO_ENDIANNESS, @@ -18,8 +17,10 @@ import { type DType, DTypeClass, type EnumType, + type FloatType, type GroupWithChildren, type H5WebComplex, + type IntegerType, type NumericType, type OpaqueType, type PrintableType, @@ -52,32 +53,20 @@ export function getNameFromPath(path: string): string { /* ----------------- */ /* ----- TYPES ----- */ -export function intType(size = 32, h5tOrder = H5T_ORDER.LE): NumericType { +export function intType( + signed = true, + size = 32, + h5tOrder = H5T_ORDER.LE, +): IntegerType { return { class: DTypeClass.Integer, + signed, endianness: H5T_TO_ENDIANNESS[h5tOrder], size, }; } -export function uintType(size = 32, h5tOrder = H5T_ORDER.LE): NumericType { - return { - class: DTypeClass.Unsigned, - endianness: H5T_TO_ENDIANNESS[h5tOrder], - size, - }; -} - -export function intOrUintType( - h5tSign: H5T_SIGN, - size = 32, - h5tOrder = H5T_ORDER.LE, -): NumericType { - const func = h5tSign === H5T_SIGN.SIGN_2 ? intType : uintType; - return func(size, h5tOrder); -} - -export function floatType(size = 32, h5tOrder = H5T_ORDER.LE): NumericType { +export function floatType(size = 32, h5tOrder = H5T_ORDER.LE): FloatType { return { class: DTypeClass.Float, endianness: H5T_TO_ENDIANNESS[h5tOrder], diff --git a/packages/shared/src/mock-utils.ts b/packages/shared/src/mock-utils.ts index fcc11aa32..696c4f9ba 100644 --- a/packages/shared/src/mock-utils.ts +++ b/packages/shared/src/mock-utils.ts @@ -302,7 +302,7 @@ function guessType(value: unknown): DType { } if (typeof value === 'boolean') { - return boolType(intType(8)); + return boolType(intType(true, 8)); } if (