@@ -139,6 +139,27 @@ export class ScvdFormatSpecifier {
139139 const n = Number ( v ) ;
140140 return Number . isFinite ( n ) ? n : NaN ;
141141 }
142+ // Convert Uint8Array to number (little-endian)
143+ if ( v instanceof Uint8Array ) {
144+ if ( v . length === 0 ) {
145+ return 0 ;
146+ }
147+ if ( v . length <= 4 ) {
148+ let out = 0 ;
149+ for ( const b of Array . from ( v ) . reverse ( ) ) {
150+ out = ( out << 8 ) | ( b & 0xff ) ;
151+ }
152+ return out >>> 0 ;
153+ }
154+ if ( v . length === 8 ) {
155+ let out = 0n ;
156+ for ( let i = 0 ; i < 8 ; i ++ ) {
157+ // eslint-disable-next-line security/detect-object-injection
158+ out |= BigInt ( v [ i ] ) << BigInt ( 8 * i ) ;
159+ }
160+ return out ;
161+ }
162+ }
142163 return NaN ;
143164 } ;
144165
@@ -158,7 +179,9 @@ export class ScvdFormatSpecifier {
158179 if ( typeof n === 'number' ) {
159180 n = Math . trunc ( n ) ;
160181 }
161- return this . formatNumberByType ( n , numOpts ( 'int' ) ) ;
182+ // Legacy compatibility: if type is unsigned (uint8/uint16/uint32), format as unsigned
183+ const isUnsigned = typeInfo ?. kind === 'uint' ;
184+ return this . formatNumberByType ( n , numOpts ( isUnsigned ? 'uint' : 'int' ) ) ;
162185 }
163186 case 'u' : {
164187 let n = toNumber ( value ) ;
@@ -168,11 +191,15 @@ export class ScvdFormatSpecifier {
168191 return this . formatNumberByType ( n , numOpts ( 'uint' ) ) ;
169192 }
170193 case 'x' : {
194+ const isStringValue = typeof value === 'string' ;
171195 let n = toNumeric ( value ) ;
172196 if ( typeof n === 'number' && ( typeInfo ?. kind ?? 'unknown' ) !== 'float' ) {
173197 n = Math . trunc ( n ) ;
174198 }
175- return this . format_x ( n , typeInfo , padHex ) ;
199+ // Always pad hex values when type info is available OR when value is a string (8-bit→2, 16-bit→4, 32-bit→8 hex digits)
200+ const shouldPad = padHex || ( typeInfo ?. bits !== undefined ) || isStringValue ;
201+ const effectiveType = typeInfo ?? ( isStringValue ? { kind : 'int' as const , bits : 32 } : undefined ) ;
202+ return this . format_x ( n , effectiveType , shouldPad ) ;
176203 }
177204 case 't' : {
178205 if ( typeof value === 'string' ) {
@@ -258,17 +285,42 @@ export class ScvdFormatSpecifier {
258285 if ( typeof value === 'bigint' ) {
259286 const widthRaw = bits ? Math . ceil ( bits / 4 ) : 0 ;
260287 const width = padZeroes && widthRaw > 0 ? Math . min ( widthRaw , 16 ) : 0 ;
261- const hex = value . toString ( 16 ) ;
288+ // Mask to bit width if specified
289+ let maskedValue = value ;
290+ if ( bits && bits > 0 && bits < 64 ) {
291+ const mask = ( BigInt ( 1 ) << BigInt ( bits ) ) - BigInt ( 1 ) ;
292+ maskedValue = value & mask ;
293+ }
294+ const hex = maskedValue . toString ( 16 ) . toUpperCase ( ) ;
262295 const padded = width > 0 ? hex . padStart ( width , '0' ) : hex ;
263296 return '0x' + padded ;
264297 }
265298 const n = Number ( value ) ;
266299 if ( ! Number . isFinite ( n ) ) {
267300 return `${ value } ` ;
268301 }
302+
303+ // For 64-bit values, convert to bigint to properly handle the full range
304+ if ( bits && bits === 64 ) {
305+ const bi = BigInt ( Math . trunc ( n ) ) ;
306+ const mask = ( BigInt ( 1 ) << BigInt ( 64 ) ) - BigInt ( 1 ) ;
307+ const maskedValue = bi & mask ;
308+ const widthRaw = Math . ceil ( bits / 4 ) ;
309+ const width = padZeroes && widthRaw > 0 ? Math . min ( widthRaw , 16 ) : 0 ;
310+ const hex = maskedValue . toString ( 16 ) . toUpperCase ( ) ;
311+ const padded = width > 0 ? hex . padStart ( width , '0' ) : hex ;
312+ return '0x' + padded ;
313+ }
314+
269315 const widthRaw = bits ? Math . ceil ( bits / 4 ) : 0 ;
270316 const width = padZeroes && widthRaw > 0 ? Math . min ( widthRaw , 16 ) : 0 ; // cap padding to 64-bit to avoid runaway zeros
271- const hex = ( n >>> 0 ) . toString ( 16 ) ;
317+ // Mask to bit width if specified, otherwise use 32-bit unsigned
318+ let maskedValue = n >>> 0 ;
319+ if ( bits && bits > 0 && bits < 32 ) {
320+ const mask = ( 1 << bits ) - 1 ;
321+ maskedValue = ( n >>> 0 ) & mask ;
322+ }
323+ const hex = maskedValue . toString ( 16 ) . toUpperCase ( ) ;
272324 const padded = width > 0 ? hex . padStart ( width , '0' ) : hex ;
273325 return '0x' + padded ;
274326 }
@@ -331,7 +383,11 @@ export class ScvdFormatSpecifier {
331383 if ( ! Number . isFinite ( n ) ) {
332384 return `${ value } ` ;
333385 }
334- return this . formatHex ( n , typeInfo , padZeroes ) ;
386+ // When value is a string and no typeInfo provided, default to 32-bit for padding
387+ const isStringValue = typeof value === 'string' ;
388+ const effectiveType = typeInfo ?? ( isStringValue ? { kind : 'int' as const , bits : 32 } : undefined ) ;
389+ const effectivePadding = padZeroes || isStringValue ; // Always pad string values
390+ return this . formatHex ( n , effectiveType , effectivePadding ) ;
335391 }
336392
337393 public format_address_like ( value : number | string ) : string {
0 commit comments