import { Base64 } from "../encoding/base64" ; /**
 * Convert arrays to and from different formats.
 */ export class Converter { internal private static ENCODE_LOOKUP : string [ ] | undefined ; internal private static DECODE_LOOKUP : number [ ] | undefined ; param array param startIndex param length returns public static bytesToUtf8 ( array , startIndex ? , length ? ) { const start = startIndex ?? 0 ; const len = length ?? array . length ; let str = "" ; for ( let i = start ; i < start + len ; i ++ ) { const value = array [ i ] ; if ( value < 0x80 ) { str += String . fromCharCode ( value ) ; } else if ( value > 0xbf && value < 0xe0 ) { str += String . fromCharCode ( ( ( value & 0x1f ) << 6 ) | ( array [ i + 1 ] & 0x3f ) ) ; i += 1 ; } else if ( value > 0xdf && value < 0xf0 ) { str += String . fromCharCode ( ( ( value & 0x0f ) << 12 ) | ( ( array [ i + 1 ] & 0x3f ) << 6 ) | ( array [ i + 2 ] & 0x3f ) ) ; i += 2 ; } else { const charCode = ( ( ( value & 0x07 ) << 18 ) | ( ( array [ i + 1 ] & 0x3f ) << 12 ) | ( ( array [ i + 2 ] & 0x3f ) << 6 ) | ( array [ i + 3 ] & 0x3f ) ) - 0x010000 ; str += String . fromCharCode ( ( charCode >> 10 ) | 0xd800 , ( charCode & 0x03ff ) | 0xdc00 ) ; i += 3 ; } } return str ; } param utf8 returns public static utf8ToBytes ( utf8 ) { const bytes = [ ] ; for ( let i = 0 ; i < utf8 . length ; i ++ ) { let charcode = utf8 . charCodeAt ( i ) ; if ( charcode < 0x80 ) { bytes . push ( charcode ) ; } else if ( charcode < 0x800 ) { bytes . push ( 0xc0 | ( charcode >> 6 ) , 0x80 | ( charcode & 0x3f ) ) ; } else if ( charcode < 0xd800 || charcode >= 0xe000 ) { bytes . push ( 0xe0 | ( charcode >> 12 ) , 0x80 | ( ( charcode >> 6 ) & 0x3f ) , 0x80 | ( charcode & 0x3f ) ) ; } else { i ++ ; charcode = 0x10000 + ( ( ( charcode & 0x3ff ) << 10 ) | ( utf8 . charCodeAt ( i ) & 0x3ff ) ) ; bytes . push ( 0xf0 | ( charcode >> 18 ) , 0x80 | ( ( charcode >> 12 ) & 0x3f ) , 0x80 | ( ( charcode >> 6 ) & 0x3f ) , 0x80 | ( charcode & 0x3f ) ) ; } } return Uint8Array . from ( bytes ) ; } param array param startIndex param length param reverse returns public static bytesToHex ( array , startIndex ? , length ? , reverse ? ) { let hex = "" ; this . buildHexLookups ( ) ; if ( Converter . ENCODE_LOOKUP ) { const len = length ?? array . length ; const start = startIndex ?? 0 ; if ( reverse ) { for ( let i = 0 ; i < len ; i ++ ) { hex = Converter . ENCODE_LOOKUP [ array [ start + i ] ] + hex ; } } else { for ( let i = 0 ; i < len ; i ++ ) { hex += Converter . ENCODE_LOOKUP [ array [ start + i ] ] ; } } } return hex ; } param hex param reverse returns public static hexToBytes ( hex , reverse ? ) { const sizeof = hex . length >> 1 ; const length = sizeof << 1 ; const array = new Uint8Array ( sizeof ) ; this . buildHexLookups ( ) ; if ( Converter . DECODE_LOOKUP ) { let i = 0 ; let n = 0 ; while ( i < length ) { array [ n ++ ] = ( Converter . DECODE_LOOKUP [ hex . charCodeAt ( i ++ ) ] << 4 ) | Converter . DECODE_LOOKUP [ hex . charCodeAt ( i ++ ) ] ; } if ( reverse ) { array . reverse ( ) ; } } return array ; } param utf8 returns public static utf8ToHex ( utf8 ) { return Converter . bytesToHex ( Converter . utf8ToBytes ( utf8 ) ) ; } param hex returns public static hexToUtf8 ( hex ) { return Converter . bytesToUtf8 ( Converter . hexToBytes ( hex ) ) ; } param value returns public static isHex ( value ) { if ( value . length % 2 === 1 ) { return false ; } return /^[\da-f]+$/g . test ( value ) ; } param bytes returns public static bytesToBinary ( bytes ) { const b = [ ] ; for ( let i = 0 ; i < bytes . length ; i ++ ) { b . push ( bytes [ i ] . toString ( 2 ) . padStart ( 8 , "0" ) ) ; } return b . join ( "" ) ; } param binary returns public static binaryToBytes ( binary ) { const bytes = new Uint8Array ( Math . ceil ( binary . length / 8 ) ) ; for ( let i = 0 ; i < bytes . length ; i ++ ) { bytes [ i ] = Number . parseInt ( binary . slice ( i * 8 , ( i + 1 ) * 8 ) , 2 ) ; } return bytes ; } param bytes returns public static bytesToBase64 ( bytes ) { return Base64 . encode ( bytes ) ; } param base64 returns public static base64ToBytes ( base64 ) { return Base64 . decode ( base64 ) ; } internal private static buildHexLookups ( ) { if ( ! Converter . ENCODE_LOOKUP || ! Converter . DECODE_LOOKUP ) { const alphabet = "0123456789abcdef" ; Converter . ENCODE_LOOKUP = [ ] ; Converter . DECODE_LOOKUP = [ ] ; for ( let i = 0 ; i < 256 ; i ++ ) { Converter . ENCODE_LOOKUP [ i ] = alphabet [ ( i >> 4 ) & 0xf ] + alphabet [ i & 0xf ] ; if ( i < 16 ) { if ( i < 10 ) { Converter . DECODE_LOOKUP [ 0x30 + i ] = i ; } else { Converter . DECODE_LOOKUP [ 0x61 - 10 + i ] = i ; } } } } } }