1- import * as Base85 from 'base85' ;
2- import * as zlib from 'minizlib' ;
3- import { Buffer } from 'node:buffer' ;
1+ import { ascii85Decode } from './ascii85' ;
2+ import * as pako from 'pako' ;
3+
4+ const textDecoder = new TextDecoder ( ) ;
5+ const textEncoder = new TextEncoder ( ) ;
6+
7+ /**
8+ * Inflate compressed data with support for partial/truncated streams.
9+ * Captures output chunks via onData to handle Z_SYNC_FLUSH correctly.
10+ */
11+ function inflateData ( data : Uint8Array , raw : boolean ) : Uint8Array | undefined {
12+ const chunks : Uint8Array [ ] = [ ] ;
13+ const inflator = new pako . Inflate ( { windowBits : raw ? - 15 : 15 } ) ;
14+ inflator . onData = ( chunk : Uint8Array ) => {
15+ chunks . push ( chunk ) ;
16+ } ;
17+ inflator . push ( data , 2 ) ; // Z_SYNC_FLUSH
18+
19+ if ( chunks . length === 0 ) return undefined ;
20+ if ( chunks . length === 1 ) return chunks [ 0 ] ;
21+
22+ const totalLen = chunks . reduce ( ( sum , c ) => sum + c . length , 0 ) ;
23+ const result = new Uint8Array ( totalLen ) ;
24+ let offset = 0 ;
25+ for ( const chunk of chunks ) {
26+ result . set ( chunk , offset ) ;
27+ offset += chunk . length ;
28+ }
29+ return result ;
30+ }
431
532enum MIAMVersion {
633 V1 = 1 ,
@@ -155,34 +182,34 @@ export class MIAMCoreUtils {
155182 } ;
156183 }
157184
158- let hdr = Base85 . decode ( '<~' + rawHdr + '~>' , 'ascii85 ') ;
185+ let hdr = ascii85Decode ( '<~' + rawHdr + '~>' ) ;
159186 if ( ! hdr || hdr . length < hpad ) {
160187 return {
161188 decoded : false ,
162189 error : 'Ascii85 decode failed for MIAM message header' ,
163190 } ;
164191 }
165192
166- let body : Buffer | undefined = undefined ;
193+ let body : Uint8Array | undefined = undefined ;
167194
168195 const rawBody = txt . substring ( delimIdx + 1 ) ;
169196 if ( rawBody . length > 0 ) {
170197 if ( '0123' . indexOf ( bpad ) >= 0 ) {
171198 const bpadValue = parseInt ( bpad ) ;
172199
173- body = Base85 . decode ( '<~' + rawBody + '~>' , 'ascii85 ') || undefined ;
200+ body = ascii85Decode ( '<~' + rawBody + '~>' ) || undefined ;
174201 if ( body && body . length >= bpadValue ) {
175202 body = body . subarray ( 0 , body . length - bpadValue ) ;
176203 }
177204 } else if ( bpad === '-' ) {
178- body = Buffer . from ( rawBody ) ;
205+ body = textEncoder . encode ( rawBody ) ;
179206 }
180207 }
181208
182209 hdr = hdr . subarray ( 0 , hdr . length - hpad ) ;
183210
184- const version = hdr . readUInt8 ( 0 ) & 0xf ;
185- const pduType = ( hdr . readUInt8 ( 0 ) >> 4 ) & 0xf ;
211+ const version = hdr [ 0 ] & 0xf ;
212+ const pduType = ( hdr [ 0 ] >> 4 ) & 0xf ;
186213
187214 if ( isMIAMVersion ( version ) && isMIAMCorePdu ( pduType ) ) {
188215 const versionPduHandler =
@@ -225,7 +252,7 @@ export class MIAMCoreUtils {
225252 } ,
226253 } ;
227254
228- private static arincCrc16 ( buf : Buffer , seed ?: number ) {
255+ private static arincCrc16 ( buf : Uint8Array , seed ?: number ) {
229256 const crctable = [
230257 0x0000 , 0x1021 , 0x2042 , 0x3063 , 0x4084 , 0x50a5 , 0x60c6 , 0x70e7 , 0x8108 ,
231258 0x9129 , 0xa14a , 0xb16b , 0xc18c , 0xd1ad , 0xe1ce , 0xf1ef , 0x1231 , 0x0210 ,
@@ -263,14 +290,14 @@ export class MIAMCoreUtils {
263290 for ( let i = 0 ; i < buf . length ; i ++ ) {
264291 crc =
265292 ( ( ( crc << 8 ) >>> 0 ) ^
266- crctable [ ( ( ( crc >>> 8 ) ^ buf . readUInt8 ( i ) ) >>> 0 ) & 0xff ] ) >>>
293+ crctable [ ( ( ( crc >>> 8 ) ^ buf [ i ] ) >>> 0 ) & 0xff ] ) >>>
267294 0 ;
268295 }
269296
270297 return crc & 0xffff ;
271298 }
272299
273- private static arinc665Crc32 ( buf : Buffer , seed ?: number ) {
300+ private static arinc665Crc32 ( buf : Uint8Array , seed ?: number ) {
274301 const crctable = [
275302 0x00000000 , 0x04c11db7 , 0x09823b6e , 0x0d4326d9 , 0x130476dc , 0x17c56b6b ,
276303 0x1a864db2 , 0x1e475005 , 0x2608edb8 , 0x22c9f00f , 0x2f8ad6d6 , 0x2b4bcb61 ,
@@ -321,9 +348,7 @@ export class MIAMCoreUtils {
321348
322349 for ( let i = 0 ; i < buf . length ; i ++ ) {
323350 crc =
324- ( ( ( crc << 8 ) >>> 0 ) ^
325- crctable [ ( ( crc >>> 24 ) ^ buf . readUInt8 ( i ) ) >>> 0 ] ) >>>
326- 0 ;
351+ ( ( ( crc << 8 ) >>> 0 ) ^ crctable [ ( ( crc >>> 24 ) ^ buf [ i ] ) >>> 0 ] ) >>> 0 ;
327352 }
328353
329354 return crc ;
@@ -347,8 +372,8 @@ export class MIAMCoreUtils {
347372 version : MIAMVersion ,
348373 minHdrSize : number ,
349374 crcLen : number ,
350- hdr : Buffer ,
351- body ?: Buffer ,
375+ hdr : Uint8Array ,
376+ body ?: Uint8Array ,
352377 ) : PduDecodingResult {
353378 if ( hdr . length < minHdrSize ) {
354379 return {
@@ -369,7 +394,7 @@ export class MIAMCoreUtils {
369394 let pduAppType : number = 0 ;
370395 let pduAppId : string = '' ;
371396 let pduCrc : number = 0 ;
372- let pduData : Buffer | null = null ;
397+ let pduData : Uint8Array | null = null ;
373398 let pduCrcIsOk : boolean = false ;
374399 let pduIsComplete : boolean = true ;
375400
@@ -380,8 +405,7 @@ export class MIAMCoreUtils {
380405 let ackOptions : number = 0 ;
381406
382407 if ( version === MIAMVersion . V1 ) {
383- pduSize =
384- ( hdr . readUInt8 ( 1 ) << 16 ) | ( hdr . readUInt8 ( 2 ) << 8 ) | hdr . readUInt8 ( 3 ) ;
408+ pduSize = ( hdr [ 1 ] << 16 ) | ( hdr [ 2 ] << 8 ) | hdr [ 3 ] ;
385409
386410 const msgSize = hdr . length + ( body === undefined ? 0 : body . length ) ;
387411 if ( pduSize > msgSize ) {
@@ -392,20 +416,19 @@ export class MIAMCoreUtils {
392416 }
393417 hdr = hdr . subarray ( 4 ) ;
394418
395- tail = hdr . subarray ( 0 , 7 ) . toString ( 'ascii' ) ;
419+ tail = textDecoder . decode ( hdr . subarray ( 0 , 7 ) ) ;
396420 hdr = hdr . subarray ( 7 ) ;
397421 } else if ( version === MIAMVersion . V2 ) {
398422 hdr = hdr . subarray ( 1 ) ;
399423 }
400424
401- msgNum = ( hdr . readUInt8 ( 0 ) >> 1 ) & 0x7f ;
402- ackOptions = hdr . readUInt8 ( 0 ) & 1 ;
425+ msgNum = ( hdr [ 0 ] >> 1 ) & 0x7f ;
426+ ackOptions = hdr [ 0 ] & 1 ;
403427 hdr = hdr . subarray ( 1 ) ;
404428
405- pduCompression =
406- ( ( hdr . readUInt8 ( 0 ) << 2 ) | ( ( hdr . readUInt8 ( 1 ) >> 6 ) & 0x3 ) ) & 0x7 ;
407- pduEncoding = ( hdr . readUInt8 ( 1 ) >> 4 ) & 0x3 ;
408- pduAppType = hdr . readUInt8 ( 1 ) & 0xf ;
429+ pduCompression = ( ( hdr [ 0 ] << 2 ) | ( ( hdr [ 1 ] >> 6 ) & 0x3 ) ) & 0x7 ;
430+ pduEncoding = ( hdr [ 1 ] >> 4 ) & 0x3 ;
431+ pduAppType = hdr [ 1 ] & 0xf ;
409432 hdr = hdr . subarray ( 2 ) ;
410433
411434 let appIdLen ;
@@ -440,17 +463,13 @@ export class MIAMCoreUtils {
440463 } ;
441464 }
442465
443- pduAppId = hdr . subarray ( 0 , appIdLen ) . toString ( 'ascii' ) ;
466+ pduAppId = textDecoder . decode ( hdr . subarray ( 0 , appIdLen ) ) ;
444467 hdr = hdr . subarray ( appIdLen ) ;
445468
446469 if ( crcLen === 4 ) {
447- pduCrc =
448- ( hdr . readUInt8 ( 0 ) << 24 ) |
449- ( hdr . readUInt8 ( 1 ) << 16 ) |
450- ( hdr . readUInt8 ( 2 ) << 8 ) |
451- hdr . readUInt8 ( 3 ) ; // crc
470+ pduCrc = ( hdr [ 0 ] << 24 ) | ( hdr [ 1 ] << 16 ) | ( hdr [ 2 ] << 8 ) | hdr [ 3 ] ; // crc
452471 } else if ( crcLen === 2 ) {
453- pduCrc = ( hdr . readUInt8 ( 0 ) << 8 ) | hdr . readUInt8 ( 1 ) ; // crc
472+ pduCrc = ( hdr [ 0 ] << 8 ) | hdr [ 1 ] ; // crc
454473 }
455474 hdr = hdr . subarray ( crcLen ) ;
456475
@@ -461,10 +480,7 @@ export class MIAMCoreUtils {
461480 ) >= 0
462481 ) {
463482 try {
464- const decompress = new zlib . InflateRaw ( { } ) ;
465- decompress . write ( body ) ;
466- decompress . flush ( zlib . constants . Z_SYNC_FLUSH ) ;
467- pduData = decompress . read ( ) ;
483+ pduData = inflateData ( body , true ) || null ;
468484 } catch ( e ) {
469485 pduErrors . push ( 'Inflation failed for body: ' + e ) ;
470486 }
@@ -483,9 +499,9 @@ export class MIAMCoreUtils {
483499 if ( pduData !== null ) {
484500 const crcAlgoHandlerByVersion : Record <
485501 MIAMVersion ,
486- ( buf : Buffer , seed ?: number ) => number
502+ ( buf : Uint8Array , seed ?: number ) => number
487503 > = {
488- [ MIAMVersion . V1 ] : ( buf : Buffer , seed ?: number ) => {
504+ [ MIAMVersion . V1 ] : ( buf : Uint8Array , seed ?: number ) => {
489505 return ~ this . arinc665Crc32 ( buf , seed ) ;
490506 } ,
491507 [ MIAMVersion . V2 ] : this . arincCrc16 ,
@@ -537,12 +553,12 @@ export class MIAMCoreUtils {
537553 label,
538554 ...( sublabel ? { sublabel } : { } ) ,
539555 ...( mfi ? { mfi } : { } ) ,
540- ...( pduData ? { text : pduData . toString ( 'ascii' ) } : { } ) ,
556+ ...( pduData ? { text : textDecoder . decode ( pduData ) } : { } ) ,
541557 } ;
542558 } else {
543559 pdu . non_acars = {
544560 appId : pduAppId ,
545- ...( pduData ? { text : pduData . toString ( 'ascii' ) } : { } ) ,
561+ ...( pduData ? { text : textDecoder . decode ( pduData ) } : { } ) ,
546562 } ;
547563 }
548564
@@ -556,10 +572,13 @@ export class MIAMCoreUtils {
556572
557573 static VersionPduHandlerTable : Record <
558574 MIAMVersion ,
559- Record < MIAMCorePdu , ( hdr : Buffer , body ?: Buffer ) => PduDecodingResult >
575+ Record <
576+ MIAMCorePdu ,
577+ ( hdr : Uint8Array , body ?: Uint8Array ) => PduDecodingResult
578+ >
560579 > = {
561580 [ MIAMVersion . V1 ] : {
562- [ MIAMCorePdu . Data ] : ( hdr : Buffer , body ?: Buffer ) => {
581+ [ MIAMCorePdu . Data ] : ( hdr : Uint8Array , body ?: Uint8Array ) => {
563582 return this . corePduDataHandler (
564583 MIAMVersion . V1 ,
565584 20 ,
@@ -579,7 +598,7 @@ export class MIAMCoreUtils {
579598 } ,
580599 } ,
581600 [ MIAMVersion . V2 ] : {
582- [ MIAMCorePdu . Data ] : ( hdr : Buffer , body ?: Buffer ) => {
601+ [ MIAMCorePdu . Data ] : ( hdr : Uint8Array , body ?: Uint8Array ) => {
583602 return this . corePduDataHandler (
584603 MIAMVersion . V2 ,
585604 7 ,
0 commit comments