UNPKG

@stenway/reliabletxt

Version:

Encode and decode text files in a reliable way

744 lines 28 kB
/* (C) Stefan John / Stenway / ReliableTXT.com / 2023 */ export var ReliableTxtEncoding; (function (ReliableTxtEncoding) { ReliableTxtEncoding[ReliableTxtEncoding["Utf8"] = 0] = "Utf8"; ReliableTxtEncoding[ReliableTxtEncoding["Utf16"] = 1] = "Utf16"; ReliableTxtEncoding[ReliableTxtEncoding["Utf16Reverse"] = 2] = "Utf16Reverse"; ReliableTxtEncoding[ReliableTxtEncoding["Utf32"] = 3] = "Utf32"; })(ReliableTxtEncoding || (ReliableTxtEncoding = {})); // ---------------------------------------------------------------------- export class ReliableTxtEncodingUtil { static getPreambleSize(encoding) { if (encoding === ReliableTxtEncoding.Utf8) { return 3; } else if (encoding === ReliableTxtEncoding.Utf16) { return 2; } else if (encoding === ReliableTxtEncoding.Utf16Reverse) { return 2; } else if (encoding === ReliableTxtEncoding.Utf32) { return 4; } else { throw new RangeError(); } } static getPreambleBytes(encoding) { if (encoding === ReliableTxtEncoding.Utf8) { return new Uint8Array([0xEF, 0xBB, 0xBF]); } else if (encoding === ReliableTxtEncoding.Utf16) { return new Uint8Array([0xFE, 0xFF]); } else if (encoding === ReliableTxtEncoding.Utf16Reverse) { return new Uint8Array([0xFF, 0xFE]); } else if (encoding === ReliableTxtEncoding.Utf32) { return new Uint8Array([0x0, 0x0, 0xFE, 0xFF]); } else { throw new RangeError(); } } } // ---------------------------------------------------------------------- export class ReliableTxtLines { static join(lines) { return lines.join("\n"); } static split(text) { return text.split("\n"); } static getLineInfo(text, codeUnitIndex) { if (codeUnitIndex > text.length || codeUnitIndex < 0) { throw new RangeError("CodeUnit index out of range"); } if (codeUnitIndex === 0) { return [0, 0, 0]; } let charIndex = -1; let lineIndex = 0; let lineCharIndex = -1; let length = codeUnitIndex; if (codeUnitIndex === text.length) { length -= 1; } let wasLineBreak = false; for (let i = 0; i <= length; i++) { if (wasLineBreak) { wasLineBreak = false; charIndex = -1; lineCharIndex = -1; lineIndex++; } const firstCodeUnit = text.charCodeAt(i); if (firstCodeUnit === 0x0A) { wasLineBreak = true; } else if (firstCodeUnit >= 0xD800 && firstCodeUnit <= 0xDFFF) { if (firstCodeUnit >= 0xDC00) { throw new InvalidUtf16StringError(); } i++; if (i >= text.length) { throw new InvalidUtf16StringError(); } const secondCodeUnit = text.charCodeAt(i); if (!(secondCodeUnit >= 0xDC00 && secondCodeUnit <= 0xDFFF)) { throw new InvalidUtf16StringError(); } if (codeUnitIndex === text.length - 1 && i === text.length - 1) { charIndex++; lineCharIndex++; } } charIndex++; lineCharIndex++; } if (codeUnitIndex === text.length) { if (!wasLineBreak) { charIndex++; lineCharIndex++; } else { charIndex = 0; lineCharIndex = 0; lineIndex++; } } return [charIndex, lineIndex, lineCharIndex]; } } // ---------------------------------------------------------------------- export class InvalidUtf16StringError extends Error { constructor() { super("Invalid UTF16 string"); } } // ---------------------------------------------------------------------- export class StringDecodingError extends Error { constructor() { super("Could not decode string"); } } // ---------------------------------------------------------------------- export class NoReliableTxtPreambleError extends Error { constructor() { super("Document does not have a ReliableTXT preamble"); } } // ---------------------------------------------------------------------- export class Utf16String { static isValid(str) { for (let i = 0; i < str.length; i++) { const firstCodeUnit = str.charCodeAt(i); if (firstCodeUnit >= 0xD800 && firstCodeUnit <= 0xDFFF) { if (firstCodeUnit >= 0xDC00) { return false; } i++; if (i >= str.length) { return false; } const secondCodeUnit = str.charCodeAt(i); if (!(secondCodeUnit >= 0xDC00 && secondCodeUnit <= 0xDFFF)) { return false; } } } return true; } static validate(str) { if (!Utf16String.isValid(str)) { throw new InvalidUtf16StringError(); } } static getCodePointCount(str) { let count = 0; for (let i = 0; i < str.length; i++) { const firstCodeUnit = str.charCodeAt(i); if (firstCodeUnit >= 0xD800 && firstCodeUnit <= 0xDFFF) { if (firstCodeUnit >= 0xDC00) { throw new InvalidUtf16StringError(); } i++; if (i >= str.length) { throw new InvalidUtf16StringError(); } const secondCodeUnit = str.charCodeAt(i); if (!(secondCodeUnit >= 0xDC00 && secondCodeUnit <= 0xDFFF)) { throw new InvalidUtf16StringError(); } } count++; } return count; } static getCodePointArray(str) { const numCodePoints = Utf16String.getCodePointCount(str); const codePoints = new Array(numCodePoints); let codePointIndex = 0; for (let i = 0; i < str.length; i++) { let codePoint = str.charCodeAt(i); if (codePoint >= 0xD800 && codePoint <= 0xDBFF) { i++; const secondCodeUnit = str.charCodeAt(i); codePoint = (codePoint - 0xD800) * 0x400 + secondCodeUnit - 0xDC00 + 0x10000; } codePoints[codePointIndex] = codePoint; codePointIndex++; } return codePoints; } static getCodePoints(str) { const numCodePoints = Utf16String.getCodePointCount(str); const codePoints = new Uint32Array(numCodePoints); let codePointIndex = 0; for (let i = 0; i < str.length; i++) { let codePoint = str.charCodeAt(i); if (codePoint >= 0xD800 && codePoint <= 0xDBFF) { i++; const secondCodeUnit = str.charCodeAt(i); codePoint = (codePoint - 0xD800) * 0x400 + secondCodeUnit - 0xDC00 + 0x10000; } codePoints[codePointIndex] = codePoint; codePointIndex++; } return codePoints; } static getUtf8ByteCount(str) { let byteCount = 0; for (let i = 0; i < str.length; i++) { const firstCodeUnit = str.charCodeAt(i); if (firstCodeUnit <= 0x007F) { byteCount++; } else if (firstCodeUnit <= 0x07FF) { byteCount += 2; } else { if (firstCodeUnit >= 0xD800 && firstCodeUnit <= 0xDFFF) { if (firstCodeUnit >= 0xDC00) { return -1; } i++; if (i >= str.length) { return -1; } const secondCodeUnit = str.charCodeAt(i); if (!(secondCodeUnit >= 0xDC00 && secondCodeUnit <= 0xDFFF)) { return -1; } byteCount += 4; } else { byteCount += 3; } } } return byteCount; } static toUtf8Bytes(text) { Utf16String.validate(text); const utf8Encoder = new TextEncoder(); return utf8Encoder.encode(text); } static toUtf16Bytes(text, littleEndian = false) { const byteArray = new Uint8Array(text.length * 2); const dataView = new DataView(byteArray.buffer); let wasHighSurrogate = false; for (let i = 0; i < text.length; i++) { const codeUnit = text.charCodeAt(i); if (wasHighSurrogate) { if (!(codeUnit >= 0xDC00 && codeUnit <= 0xDFFF)) { throw new InvalidUtf16StringError(); } wasHighSurrogate = false; } else if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { if (codeUnit >= 0xDC00) { throw new InvalidUtf16StringError(); } wasHighSurrogate = true; } dataView.setUint16(i * 2, codeUnit, littleEndian); } if (wasHighSurrogate) { throw new InvalidUtf16StringError(); } return byteArray; } static toUtf32Bytes(str, littleEndian = false) { const numCodePoints = Utf16String.getCodePointCount(str); const byteArray = new Uint8Array(numCodePoints * 4); const dataView = new DataView(byteArray.buffer); let codePointIndex = 0; for (let i = 0; i < str.length; i++) { let codePoint = str.charCodeAt(i); if (codePoint >= 0xD800 && codePoint <= 0xDBFF) { i++; const secondCodeUnit = str.charCodeAt(i); codePoint = (codePoint - 0xD800) * 0x400 + secondCodeUnit - 0xDC00 + 0x10000; } dataView.setUint32(codePointIndex * 4, codePoint, littleEndian); codePointIndex++; } return byteArray; } static fromUtf8Bytes(bytes, skipFirstBom = false) { const utf8Decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: !skipFirstBom }); try { return utf8Decoder.decode(bytes); } catch (error) { if (error instanceof TypeError) { throw new StringDecodingError(); } else { throw error; } } } static fromUtf16Bytes(bytes, littleEndian, skipFirstBom = false) { const utf16Decoder = new TextDecoder("utf-16" + (littleEndian ? "le" : "be"), { fatal: true, ignoreBOM: !skipFirstBom }); try { return utf16Decoder.decode(bytes); } catch (error) { if (error instanceof TypeError) { throw new StringDecodingError(); } else { throw error; } } } static fromUtf32Bytes(bytes, littleEndian, skipFirstBom = false) { if (bytes.length % 4 !== 0) { throw new StringDecodingError(); } const numCodePoints = bytes.length / 4; let numCodeUnits = 0; const bytesDataView = new DataView(bytes.buffer); let startIndex = 0; if (skipFirstBom && bytesDataView.byteLength >= 4 && bytesDataView.getUint32(0, littleEndian) == 0xFEFF) { startIndex = 1; } for (let i = startIndex; i < numCodePoints; i++) { const codePoint = bytesDataView.getUint32(4 * i, littleEndian); if (codePoint > 0x010000) { numCodeUnits++; } if (codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) { throw new StringDecodingError(); } numCodeUnits++; } const utf16Bytes = new Uint8Array(numCodeUnits * 2); const dataView = new DataView(utf16Bytes.buffer); let codeUnitIndex = 0; for (let i = startIndex; i < numCodePoints; i++) { let codePoint = bytesDataView.getUint32(4 * i, littleEndian); if (codePoint > 0x010000) { codePoint -= 0x010000; const highSurrogate = (codePoint >> 10) + 0xD800; dataView.setUint16(codeUnitIndex * 2, highSurrogate, false); codeUnitIndex++; const lowSurrogate = (codePoint % 0x400) + 0xDC00; dataView.setUint16(codeUnitIndex * 2, lowSurrogate, false); } else { dataView.setUint16(codeUnitIndex * 2, codePoint, false); } codeUnitIndex++; } return Utf16String.fromUtf16Bytes(utf16Bytes, false); } static fromCodePointArray(codePoints) { let numCodeUnits = 0; for (let i = 0; i < codePoints.length; i++) { const codePoint = codePoints[i]; if (codePoint > 0x010000) { numCodeUnits++; } if (codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF)) { throw new StringDecodingError(); } numCodeUnits++; } const utf16Bytes = new Uint8Array(numCodeUnits * 2); const dataView = new DataView(utf16Bytes.buffer); let codeUnitIndex = 0; for (let i = 0; i < codePoints.length; i++) { let codePoint = codePoints[i]; if (codePoint > 0x010000) { codePoint -= 0x010000; const highSurrogate = (codePoint >> 10) + 0xD800; dataView.setUint16(codeUnitIndex * 2, highSurrogate, false); codeUnitIndex++; const lowSurrogate = (codePoint % 0x400) + 0xDC00; dataView.setUint16(codeUnitIndex * 2, lowSurrogate, false); } else { dataView.setUint16(codeUnitIndex * 2, codePoint, false); } codeUnitIndex++; } return Utf16String.fromUtf16Bytes(utf16Bytes, false); } } // ---------------------------------------------------------------------- export class ReliableTxtEncoder { static encode(text, encoding) { const textWithPreamble = "\uFEFF" + text; return ReliableTxtEncoder.encodePart(textWithPreamble, encoding); } static encodePart(text, encoding) { if (encoding === ReliableTxtEncoding.Utf8) { return Utf16String.toUtf8Bytes(text); } else if (encoding === ReliableTxtEncoding.Utf16) { return Utf16String.toUtf16Bytes(text, false); } else if (encoding === ReliableTxtEncoding.Utf16Reverse) { return Utf16String.toUtf16Bytes(text, true); } else if (encoding === ReliableTxtEncoding.Utf32) { return Utf16String.toUtf32Bytes(text, false); } else { throw new RangeError(); } } } // ---------------------------------------------------------------------- export class ReliableTxtDecoder { static getEncodingOrNull(bytes) { if (bytes.length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) { return ReliableTxtEncoding.Utf8; } else if (bytes.length >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) { return ReliableTxtEncoding.Utf16; } else if (bytes.length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) { return ReliableTxtEncoding.Utf16Reverse; } else if (bytes.length >= 4 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0xFE && bytes[3] == 0xFF) { return ReliableTxtEncoding.Utf32; } else { return null; } } static getEncoding(bytes) { const encoding = ReliableTxtDecoder.getEncodingOrNull(bytes); if (encoding === null) { throw new NoReliableTxtPreambleError(); } return encoding; } static decode(bytes) { const encoding = ReliableTxtDecoder.getEncoding(bytes); let text; if (encoding === ReliableTxtEncoding.Utf8) { text = Utf16String.fromUtf8Bytes(bytes, true); } else if (encoding === ReliableTxtEncoding.Utf16) { text = Utf16String.fromUtf16Bytes(bytes, false, true); } else if (encoding === ReliableTxtEncoding.Utf16Reverse) { text = Utf16String.fromUtf16Bytes(bytes, true, true); } else if (encoding === ReliableTxtEncoding.Utf32) { text = Utf16String.fromUtf32Bytes(bytes, false, true); } else { throw new RangeError(); } return new ReliableTxtDocument(text, encoding); } static decodePart(bytes, encoding) { if (encoding === ReliableTxtEncoding.Utf8) { return Utf16String.fromUtf8Bytes(bytes, false); } else if (encoding === ReliableTxtEncoding.Utf16) { return Utf16String.fromUtf16Bytes(bytes, false); } else if (encoding === ReliableTxtEncoding.Utf16Reverse) { return Utf16String.fromUtf16Bytes(bytes, true); } else if (encoding === ReliableTxtEncoding.Utf32) { return Utf16String.fromUtf32Bytes(bytes, false); } else { throw new RangeError(); } } } // ---------------------------------------------------------------------- export class InvalidBase64StringError extends Error { constructor() { super("Invalid Base64 string"); } } // ---------------------------------------------------------------------- class RawBase64String { static encodeBytes(bytes) { const numCompleteTriples = Math.floor(bytes.length / 3); const rest = bytes.length % 3; const utf16Bytes = new Uint8Array(numCompleteTriples * 4 * 2 + (rest !== 0 ? ((rest + 1) * 2) : 0)); const dataView = new DataView(utf16Bytes.buffer); const lookup = this.encoderLookup; for (let i = 0; i < numCompleteTriples; i++) { const b0 = bytes[i * 3]; const b1 = bytes[i * 3 + 1]; const b2 = bytes[i * 3 + 2]; const v24 = (b0 << 16) | (b1 << 8) | b2; const i0 = (v24 >> 18) & 0b111111; const i1 = (v24 >> 12) & 0b111111; const i2 = (v24 >> 6) & 0b111111; const i3 = v24 & 0b111111; const offset = i * 4 * 2; dataView.setUint16(offset, lookup[i0]); dataView.setUint16(offset + 2, lookup[i1]); dataView.setUint16(offset + 4, lookup[i2]); dataView.setUint16(offset + 6, lookup[i3]); } if (rest === 2) { const b0 = bytes[numCompleteTriples * 3]; const b1 = bytes[numCompleteTriples * 3 + 1]; const v16 = (b0 << 8) | b1; const i0 = (v16 >> 10) & 0b111111; const i1 = (v16 >> 4) & 0b111111; const i2 = (v16 << 2) & 0b111111; const offset = numCompleteTriples * 4 * 2; dataView.setUint16(offset, lookup[i0]); dataView.setUint16(offset + 2, lookup[i1]); dataView.setUint16(offset + 4, lookup[i2]); } else if (rest === 1) { const b0 = bytes[numCompleteTriples * 3]; const v8 = b0; const i0 = (v8 >> 2) & 0b111111; const i1 = (v8 << 4) & 0b111111; const offset = numCompleteTriples * 4 * 2; dataView.setUint16(offset, lookup[i0]); dataView.setUint16(offset + 2, lookup[i1]); } return Utf16String.fromUtf16Bytes(utf16Bytes, false); } static encodeText(text, encoding = ReliableTxtEncoding.Utf8) { const bytes = ReliableTxtEncoder.encode(text, encoding); return this.encodeBytes(bytes); } static decodeAsBytes(rawBase64Str) { if (rawBase64Str.endsWith("=")) { throw new InvalidBase64StringError(); } const numCompleteQuadruples = Math.floor(rawBase64Str.length / 4); const restLength = rawBase64Str.length % 4; if (restLength === 1) { throw new InvalidBase64StringError(); } const bytes = new Uint8Array(numCompleteQuadruples * 3 + (restLength !== 0 ? restLength - 1 : 0)); const lookup = this.decoderLookup; for (let i = 0; i < numCompleteQuadruples; i++) { const c0 = rawBase64Str.charCodeAt(i * 4); const c1 = rawBase64Str.charCodeAt(i * 4 + 1); const c2 = rawBase64Str.charCodeAt(i * 4 + 2); const c3 = rawBase64Str.charCodeAt(i * 4 + 3); if (c0 > 0x7A || c1 > 0x7A || c2 > 0x7A || c3 > 0x7A) { throw new InvalidBase64StringError(); } const n0 = lookup[c0]; const n1 = lookup[c1]; const n2 = lookup[c2]; const n3 = lookup[c3]; if (n0 < 0 || n1 < 0 || n2 < 0 || n3 < 0) { throw new InvalidBase64StringError(); } const v24 = (n0 << 18) | (n1 << 12) | (n2 << 6) | n3; const b0 = (v24 >> 16) & 0xFF; const b1 = (v24 >> 8) & 0xFF; const b2 = v24 & 0xFF; bytes[i * 3] = b0; bytes[i * 3 + 1] = b1; bytes[i * 3 + 2] = b2; } if (restLength === 3) { const c0 = rawBase64Str.charCodeAt(numCompleteQuadruples * 4); const c1 = rawBase64Str.charCodeAt(numCompleteQuadruples * 4 + 1); const c2 = rawBase64Str.charCodeAt(numCompleteQuadruples * 4 + 2); if (c0 > 0x7A || c1 > 0x7A || c2 > 0x7A) { throw new InvalidBase64StringError(); } const n0 = lookup[c0]; const n1 = lookup[c1]; const n2 = lookup[c2]; if (n0 < 0 || n1 < 0 || n2 < 0) { throw new InvalidBase64StringError(); } const v18 = (n0 << 12) | (n1 << 6) | n2; const b0 = (v18 >> 10) & 0xFF; const b1 = (v18 >> 2) & 0xFF; bytes[numCompleteQuadruples * 3] = b0; bytes[numCompleteQuadruples * 3 + 1] = b1; } else if (restLength === 2) { const c0 = rawBase64Str.charCodeAt(numCompleteQuadruples * 4); const c1 = rawBase64Str.charCodeAt(numCompleteQuadruples * 4 + 1); if (c0 > 0x7A || c1 > 0x7A) { throw new InvalidBase64StringError(); } const n0 = lookup[c0]; const n1 = lookup[c1]; if (n0 < 0 || n1 < 0) { throw new InvalidBase64StringError(); } const v12 = (n0 << 6) | n1; const b0 = (v12 >> 4) & 0xFF; bytes[numCompleteQuadruples * 3] = b0; } return bytes; } static decodeAsText(rawBase64Str) { const bytes = this.decodeAsBytes(rawBase64Str); return ReliableTxtDecoder.decode(bytes).text; } static encode(stringOrBytes) { if (stringOrBytes instanceof Uint8Array) { return this.encodeBytes(stringOrBytes); } else { return this.encodeText(stringOrBytes); } } static decode(rawBase64Str) { const bytes = this.decodeAsBytes(rawBase64Str); if (ReliableTxtDecoder.getEncodingOrNull(bytes) === null) { return bytes; } else { return ReliableTxtDecoder.decode(bytes).text; } } } RawBase64String.encoderLookup = [ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F ]; RawBase64String.decoderLookup = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, ]; export { RawBase64String }; // ---------------------------------------------------------------------- export class Base64String { static encodeBytes(bytes) { const result = RawBase64String.encodeBytes(bytes); return `Base64|${result}|`; } static encodeText(text, encoding = ReliableTxtEncoding.Utf8) { const bytes = ReliableTxtEncoder.encode(text, encoding); return this.encodeBytes(bytes); } static decodeAsBytes(base64Str) { if (!base64Str.startsWith("Base64|")) { throw new InvalidBase64StringError(); } if (base64Str.length < 8 || !base64Str.endsWith("|")) { throw new InvalidBase64StringError(); } base64Str = base64Str.substring(7, base64Str.length - 1); return RawBase64String.decodeAsBytes(base64Str); } static decodeAsText(base64Str) { const bytes = this.decodeAsBytes(base64Str); return ReliableTxtDecoder.decode(bytes).text; } static encode(stringOrBytes) { if (stringOrBytes instanceof Uint8Array) { return this.encodeBytes(stringOrBytes); } else { return this.encodeText(stringOrBytes); } } static decode(base64Str) { const bytes = this.decodeAsBytes(base64Str); if (ReliableTxtDecoder.getEncodingOrNull(bytes) === null) { return bytes; } else { return ReliableTxtDecoder.decode(bytes).text; } } } // ---------------------------------------------------------------------- export class ReliableTxtDocument { constructor(text = "", encoding = ReliableTxtEncoding.Utf8) { this.text = text; this.encoding = encoding; } toBytes() { return ReliableTxtEncoder.encode(this.text, this.encoding); } getLines() { return ReliableTxtLines.split(this.text); } setLines(lines) { this.text = ReliableTxtLines.join(lines); } getCodePoints() { return Utf16String.getCodePointArray(this.text); } setCodePoints(codePoints) { this.text = Utf16String.fromCodePointArray(codePoints); } toBase64String() { return Base64String.encodeText(this.text, this.encoding); } static fromBytes(bytes) { return ReliableTxtDecoder.decode(bytes); } static fromLines(lines, encoding = ReliableTxtEncoding.Utf8) { const document = new ReliableTxtDocument("", encoding); document.setLines(lines); return document; } static fromCodePoints(codePoints, encoding = ReliableTxtEncoding.Utf8) { const document = new ReliableTxtDocument("", encoding); document.setCodePoints(codePoints); return document; } static fromBase64String(base64Str) { const bytes = Base64String.decodeAsBytes(base64Str); return this.fromBytes(bytes); } } //# sourceMappingURL=reliabletxt.js.map