import UnsupportedOperationException from '../UnsupportedOperationException' ; import CharacterSetECI from '../common/CharacterSetECI' ; /**
 * Responsible for en/decoding strings.
 */ export default class StringEncoding { /**
     * Allows the user to set a custom decoding function
     * so more encoding formats the native ones can be supported.
     */ public static customDecoder : ( bytes : Uint8Array , encodingName : string ) => string ; /**
     * Allows the user to set a custom encoding function
     * so more encoding formats the native ones can be supported.
     */ public static customEncoder : ( s : string , encodingName : string ) => Uint8Array ; /**
     * Decodes some Uint8Array to a string format.
     */ public static decode ( bytes , encoding ) { const encodingName = this . encodingName ( encoding ) ; if ( this . customDecoder ) { return this . customDecoder ( bytes , encodingName ) ; } if ( typeof TextDecoder === 'undefined' || this . shouldDecodeOnFallback ( encodingName ) ) { return this . decodeFallback ( bytes , encodingName ) ; } return new TextDecoder ( encodingName ) . decode ( bytes ) ; } param encodingName private static shouldDecodeOnFallback ( encodingName ) { return ! StringEncoding . isBrowser ( ) && encodingName === 'ISO-8859-1' ; } /**
     * Encodes some string into a Uint8Array.
     */ public static encode ( s , encoding ) { const encodingName = this . encodingName ( encoding ) ; if ( this . customEncoder ) { return this . customEncoder ( s , encodingName ) ; } if ( typeof TextEncoder === 'undefined' ) { return this . encodeFallback ( s ) ; } return new TextEncoder ( ) . encode ( s ) ; } private static isBrowser ( ) { return ( typeof window !== 'undefined' && { } . toString . call ( window ) === '[object Window]' ) ; } /**
     * Returns the string value from some encoding character set.
     */ public static encodingName ( encoding ) { return typeof encoding === 'string' ? encoding : encoding . getName ( ) ; } /**
     * Returns character set from some encoding character set.
     */ public static encodingCharacterSet ( encoding ) { if ( encoding instanceof CharacterSetECI ) { return encoding ; } return CharacterSetECI . getCharacterSetECIByName ( encoding ) ; } /**
     * Runs a fallback for the native decoding funcion.
     */ private static decodeFallback ( bytes , encoding ) { const characterSet = this . encodingCharacterSet ( encoding ) ; if ( StringEncoding . isDecodeFallbackSupported ( characterSet ) ) { let s = '' ; for ( let i = 0 , length = bytes . length ; i < length ; i ++ ) { let h = bytes [ i ] . toString ( 16 ) ; if ( h . length < 2 ) { h = '0' + h ; } s += '%' + h ; } return decodeURIComponent ( s ) ; } if ( characterSet . equals ( CharacterSetECI . UnicodeBigUnmarked ) ) { return String . fromCharCode . apply ( null , new Uint16Array ( bytes . buffer ) ) ; } throw new UnsupportedOperationException ( `Encoding ${ this . encodingName ( encoding ) } not supported by fallback.` ) ; } private static isDecodeFallbackSupported ( characterSet ) { return characterSet . equals ( CharacterSetECI . UTF8 ) || characterSet . equals ( CharacterSetECI . ISO8859_1 ) || characterSet . equals ( CharacterSetECI . ASCII ) ; } see https private static encodeFallback ( s ) { const encodedURIstring = btoa ( unescape ( encodeURIComponent ( s ) ) ) ; const charList = encodedURIstring . split ( '' ) ; const uintArray = [ ] ; for ( let i = 0 ; i < charList . length ; i ++ ) { uintArray . push ( charList [ i ] . charCodeAt ( 0 ) ) ; } return new Uint8Array ( uintArray ) ; } }