// declare require to support dynamic text-encoding module loading in node declare function require(moduleName: string): any; // declare window to use in browser declare var window: any; import { TextDecoder as TextDecoderFromTE, TextEncoder as TextEncoderFromTE } from 'text-encoding'; import CharacterSetECI from './../common/CharacterSetECI'; import Exception from './../Exception'; export default class StringEncoding { public static decode(bytes: Uint8Array, encoding: string | CharacterSetECI): string { let encodingString: string; if (typeof encoding === 'string') { encodingString = encoding; } else { encodingString = encoding.getName(); } if (StringEncoding.isBrowser()) { // tslint:disable-next-line:no-string-literal const TextDecoderBrowser = window['TextDecoder']; // use TextEncoder if is available (should be in newer browsers) if (undefined !== TextDecoderBrowser) { // console.log(TextDecoderBrowser) return new TextDecoderBrowser(encoding).decode(bytes); } else { // fall back to minimal decoding return StringEncoding.decodeFallBack(bytes, encodingString); } } else { const TextDecoderFromTEClass: typeof TextDecoderFromTE = require('text-encoding').TextDecoder; return new TextDecoderFromTEClass(encodingString).decode(bytes); } } public static encode(s: string, encoding: string | CharacterSetECI): Uint8Array { let encodingString: string; if (typeof encoding === 'string') { encodingString = encoding; } else { encodingString = encoding.getName(); } if (StringEncoding.isBrowser()) { // tslint:disable-next-line:no-string-literal const TextEncoderBrowser = window['TextEncoder']; // use TextEncoder if is available (should be in newer browsers) const ec = CharacterSetECI.getCharacterSetECIByName(encodingString); if (undefined !== TextEncoderBrowser) { // TODO: TextEncoder only supports utf-8 encoding as per specs return new TextEncoderBrowser(encoding).encode(s); } else { // fall back to minimal decoding return StringEncoding.encodeFallBack(s, encodingString); } } else { // Note: NONSTANDARD_allowLegacyEncoding is required for other encodings than UTF8 // TextEncoder only encodes to UTF8 by default as specified by encoding.spec.whatwg.org const TextEncoderFromTEClass: typeof TextEncoderFromTE = require('text-encoding').TextEncoder; return new TextEncoderFromTEClass(encodingString, { NONSTANDARD_allowLegacyEncoding: true }).encode(s); } } private static isBrowser(): boolean { return typeof window !== 'undefined' && ({}).toString.call(window) === '[object Window]'; } private static decodeFallBack(bytes: Uint8Array, encoding: string): string { const ec = CharacterSetECI.getCharacterSetECIByName(encoding); if (ec.equals(CharacterSetECI.UTF8) || ec.equals(CharacterSetECI.ISO8859_1) || ec.equals(CharacterSetECI.ASCII)) { 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); } else if (ec.equals(CharacterSetECI.UnicodeBigUnmarked)) { return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer)); } else { throw new Exception(Exception.UnsupportedOperationException, `encoding ${encoding} not supported`); } } private static encodeFallBack(s: string, encoding: string): Uint8Array { // TODO: encode return null; } }