import type { ArrayShape , Attribute , ComplexType , CompoundType , Dataset , DType , Entity , Group , NumericType , ScalarShape , Shape , } from '@h5web/shared' ; import { DTypeClass , Endianness , isGroup } from '@h5web/shared' ; import type { HsdsAttribute , HsdsCompoundType , HsdsEntity , HsdsNumericType , HsdsShape , HsdsType , } from './models' ; export function isHsdsGroup ( entity ) { return isGroup ( entity ) ; } export function assertHsdsEntity ( entity ) { if ( ! ( 'id' in entity ) ) { throw new Error ( 'Expected entity to be HSDS entity' ) ; } } export function assertHsdsDataset ( dataset ) { if ( ! ( 'id' in dataset ) ) { throw new Error ( 'Expected entity to be HSDS dataset' ) ; } } function assertHsdsNumericType ( type ) { if ( type . class !== 'H5T_INTEGER' && type . class !== 'H5T_FLOAT' ) { throw new Error ( 'Expected HSDS numeric type' ) ; } } export function convertHsdsShape ( shape ) { const { class : shapeClass , dims } = shape ; return dims || ( shapeClass === 'H5S_SCALAR' ? [ ] : null ) ; } function convertHsdsNumericType ( hsdsType ) { const { class : hsdsClass , base } = hsdsType ; const regex = /H5T_(?:STD|IEEE)_([A-Z])(\d+)(BE|LE)/u ; const matches = regex . exec ( base ) ; if ( ! matches ) { throw new Error ( `Unrecognized base ${ base }` ) ; } const [ , sign , size , endianness ] = matches ; return { class : hsdsClass === 'H5T_FLOAT' ? DTypeClass . Float : sign === 'U' ? DTypeClass . Unsigned : DTypeClass . Integer , endianness : Endianness [ endianness as 'BE' | 'LE' ] , size : Number . parseInt ( size , 10 ) , } ; } function convertHsdsCompoundType ( hsdsType ) { const { fields } = hsdsType ; if ( fields . length === 2 && fields [ 0 ] . name === 'r' && fields [ 1 ] . name === 'i' ) { const [ { type : realType } , { type : imagType } ] = fields ; assertHsdsNumericType ( realType ) ; assertHsdsNumericType ( imagType ) ; return { class : DTypeClass . Complex , realType : convertHsdsNumericType ( realType ) , imagType : convertHsdsNumericType ( imagType ) , } ; } return { class : DTypeClass . Compound , fields : Object . fromEntries ( hsdsType . fields . map ( ( v ) => [ v . name , convertHsdsType ( v . type ) ] ) ) , } ; } export function convertHsdsType ( hsdsType ) { switch ( hsdsType . class ) { case 'H5T_INTEGER' : case 'H5T_FLOAT' : return convertHsdsNumericType ( hsdsType ) ; case 'H5T_COMPOUND' : return convertHsdsCompoundType ( hsdsType ) ; case 'H5T_STRING' : return { class : DTypeClass . String , charSet : hsdsType . charSet . endsWith ( 'ASCII' ) ? 'ASCII' : 'UTF-8' , length : hsdsType . length === 'H5T_VARIABLE' ? undefined : hsdsType . length , } ; case 'H5T_ARRAY' : case 'H5T_VLEN' : return { class : hsdsType . class === 'H5T_ARRAY' ? DTypeClass . Array : DTypeClass . VLen , base : convertHsdsType ( hsdsType . base ) , dims : hsdsType . dims , } ; case 'H5T_ENUM' : if ( hsdsType . mapping . FALSE === 0 ) { return { class : DTypeClass . Bool } ; } return { class : DTypeClass . Enum , base : convertHsdsType ( hsdsType . base ) , mapping : hsdsType . mapping , } ; default : return { class : DTypeClass . Unknown } ; } } export function convertHsdsAttributes ( attrs ) { return attrs . map ( ( attr ) => ( { name : attr . name , shape : convertHsdsShape ( attr . shape ) , type : convertHsdsType ( attr . type ) , } ) ) ; }