import { settingsDefault , windefSet , _UNICODE_HOLDER , _WIN64_HOLDER , } from './config' ; import { DataTypes , FnParam , LoadSettings , MacroDef , MacroMap , } from './ffi.model' ; export function parse_windef ( windefObj , macroMap , settings ? ) { const ww = clone_filter_windef ( windefObj ) ; const macroSrc = prepare_macro ( macroMap , settings ) ; const ret = prepare_windef_ref ( ww , macroSrc ) ; validateWinData ( ret , windefSet ) ; return ret ; } /**
 * convert typeof array of param to string
 * such like ['_WIN64_HOLDER_', 'int64', 'int32'], no changed returning when string
 */ function parse_param_placeholder ( param , settings ? ) { if ( typeof param === 'string' ) { return param ; } else if ( ! param ) { throw new Error ( 'parse_param_placeholder(ps, settings) value of ps invalid' ) ; } else if ( ! Array . isArray ( param ) || param . length !== 3 ) { throw new Error ( 'parse_param_placeholder(ps, settings) value of ps must Array and has THREE elements' ) ; } const st = parse_settings ( settings ) ; let ps = '' ; switch ( param [ 0 ] ) { case _WIN64_HOLDER : ps = parse_placeholder_arch ( param , st . _WIN64 as boolean ) ; break ; case _UNICODE_HOLDER : ps = parse_placeholder_unicode ( param , st . _UNICODE as boolean ) ; break ; default : throw new Error ( 'the value of param placeholder invlaid:' + param [ 0 ] ) ; } return ps ; } function parse_placeholder_arch ( param , _WIN64 ) { if ( typeof param === 'string' ) { return param ; } else if ( ! param || param . length !== 3 ) { throw new Error ( '_WIN64 macro should be Array and has 3 items' ) ; } return _WIN64 ? param [ 1 ] : param [ 2 ] ; } function parse_placeholder_unicode ( param , _UNICODE ) { if ( typeof param === 'string' ) { return param ; } else if ( ! param || param . length !== 3 ) { throw new Error ( '_UNICODE macro should be Array and has 3 items' ) ; } return _UNICODE ? param [ 1 ] : param [ 2 ] ; } /**
 * parse ['_WIN64_HOLDER', 'int64*', 'int32*'] to 'int64*' or 'int32'
 * or ['_UNICODE_HOLDER_', 'uint16*', 'uint8*'] to 'uint16*' or 'uint8*'
 */ function prepare_macro ( macroMap , settings ? ) { const ret = new Map < string , FnParam > ( ) ; for ( const [ k , v ] of macroMap . entries ( ) ) { ret . set ( k , parse_param_placeholder ( v , settings ) ) ; } return ret ; } /**
 * parse const HANDLE = 'PVOID' to the realy FFIParam (like 'uint32*')
 * macroMap <['PVOID', 'uint32*'], ...>
 */ function prepare_windef_ref ( ww , macroSrc ) { const ret = { } ; const map = new Map < string , string > ( ) ; for ( const x of Object . keys ( ww ) ) { if ( map . has ( x ) ) { continue ; } if ( macroSrc . has ( x ) ) { const vv = macroSrc . get ( x ) ; if ( vv ) { map . set ( x , vv ) ; } else { throw new Error ( `Value of macroSrc item "${ x }" blank` ) ; } } else { continue ; } } for ( const [ k , v ] of Object . entries ( ww ) ) { if ( map . has ( k ) ) { continue ; } if ( typeof v === 'string' ) { if ( windefSet . has ( v ) ) { map . set ( k , v ) ; } else { const value = lookupRef ( v , ww , macroSrc ) ; if ( typeof value === 'string' && value ) { map . set ( k , value ) ; } else { map . set ( k , v ) ; } } } else { throw new Error ( `prepare_windef_ref() missing entry for k/v: ${ k }/"N/A"` ) ; } } map . forEach ( ( v , k ) => { ret [ k ] = v ; } ) ; return ret ; } function clone_filter_windef ( windef ) { const ret = { } ; for ( const x of Object . keys ( windef ) ) { if ( typeof windef [ x ] === 'string' ) { Object . defineProperty ( ret , x , { value : windef [ x ] , writable : true , enumerable : true , configurable : true , } ) ; } else { throw new Error ( `typeof value of ${ x } NOT string` ) ; } } return ret ; } function parse_settings ( settings ? ) { const st = { ... settingsDefault } ; if ( typeof settings !== 'undefined' && Object . keys ( settings ) . length ) { Object . assign ( st , settings ) ; } return st ; } export function lookupRef ( key , ww , macroSrc ) { let ret = _lookupRef ( key , ww , macroSrc ) ; if ( ! ret ) { return '' ; } for ( let i = 0 , len = 3 ; i < len ; i += 1 ) { const tmp = _lookupRef ( ret , ww , macroSrc ) ; if ( tmp ) { ret = tmp ; } else { break ; } } return ret ; } function _lookupRef ( key , ww , macroSrc ) { if ( macroSrc . has ( key ) ) { return macroSrc . get ( key ) as string ; } if ( typeof ww [ key ] === 'string' ) { const ret = ww [ key ] ; if ( ret && macroSrc . has ( ret ) ) { return macroSrc . get ( ret ) as string ; } return ret ; } return '' ; } export function isValidDataDef ( key , srcSet ) { return ! ! srcSet . has ( key ) ; } export function validateWinData ( windef , srcSet ) { for ( const [ k , v ] of Object . entries ( windef ) ) { if ( ! k || ! v ) { throw new Error ( `validateWinData() k or v empty: "${ k }"/"${ v }"` ) ; } if ( typeof v !== 'string' ) { throw new Error ( `validateWinData() v not typeof string: "${ k }"/"N/A"` ) ; } if ( ! isValidDataDef ( v , srcSet ) ) { throw new Error ( `validateWinData() value is invalid ffi param value: "${ k }"/"${ v }", may extra space` ) ; } } }