UNPKG

cesr

Version:

[![NPM Version](https://img.shields.io/npm/v/cesr.svg?style=flat)](https://www.npmjs.com/package/cesr) [![NPM License](https://img.shields.io/npm/l/cesr.svg?style=flat)](https://github.com/lenkan/cesr-js/blob/main/LICENSE)

154 lines (153 loc) 7.36 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _CodeTable_instances, _CodeTable_table, _CodeTable_hards, _CodeTable_strict, _CodeTable_encodeBinary, _CodeTable_encodeText; import { prepad, toArray } from "./array-utils.js"; import { decodeBase64Int, decodeBase64Url, encodeBase64Int, encodeBase64Url } from "./encoding-base64.js"; import { decodeUtf8, encodeUtf8 } from "./encoding-utf8.js"; import { lshift } from "./shifting.js"; function resolveSize(init) { return { hs: init.hs, fs: init.fs ?? 0, ls: init.ls ?? 0, os: init.os ?? 0, ss: init.ss ?? 0, xs: init.xs ?? 0, }; } export class CodeTable { constructor(table, options = {}) { _CodeTable_instances.add(this); _CodeTable_table.set(this, {}); _CodeTable_hards.set(this, {}); _CodeTable_strict.set(this, void 0); __classPrivateFieldSet(this, _CodeTable_strict, options.strict ?? false, "f"); for (const [key, value] of Object.entries(table)) { __classPrivateFieldGet(this, _CodeTable_hards, "f")[key.slice(0, 1)] = value.hs; __classPrivateFieldGet(this, _CodeTable_table, "f")[key] = resolveSize(value); } } /** * Finds the size table of a code * @param input The input to parse the code from */ lookup(input) { if (typeof input !== "string") { input = decodeUtf8(input.slice(0, 4)); } const hs = __classPrivateFieldGet(this, _CodeTable_hards, "f")[input.slice(0, 1)]; const hard = input.slice(0, hs ?? 4); const size = __classPrivateFieldGet(this, _CodeTable_table, "f")[hard]; if (size) { return size; } if (!__classPrivateFieldGet(this, _CodeTable_strict, "f")) { switch (hard.charAt(0)) { case "-": switch (hard.charAt(1)) { case "-": return resolveSize({ hs: 3, ss: 5, fs: 8 }); case "_": return resolveSize({ hs: 5, ss: 3, fs: 8 }); default: return resolveSize({ hs: 2, ss: 2, fs: 4 }); } } } throw new Error(`Unknown code ${hard}`); } encode(frame, domain = "text") { if (domain === "text") { return __classPrivateFieldGet(this, _CodeTable_instances, "m", _CodeTable_encodeText).call(this, frame); } return __classPrivateFieldGet(this, _CodeTable_instances, "m", _CodeTable_encodeBinary).call(this, frame); } decode(input) { if (typeof input === "string") { input = encodeUtf8(input); } const result = this.read(input); if (result.frame === null) { throw new Error("Not enough data in input"); } return result.frame; } /** * Tries to read a frame from the input. Returns an object with the frame and the number of bytes read. * @param input The input. May be longer than one frame, in which case only the first frame is returned. */ read(input) { if (input.length < 4) { return { frame: null, n: 0 }; } const size = this.lookup(input); if (!size) { throw new Error(`Unknown code ${input}`); } const ss = size.ss ?? 0; const cs = size.hs + ss; if (input.length < cs) { return { frame: null, n: 0 }; } const ls = size.ls ?? 0; const ps = (size.hs + ss) % 4; const ms = ss - (size.os ?? 0); const os = size.os ?? 0; const hard = decodeUtf8(input.slice(0, size.hs)); const soft0 = decodeBase64Int(decodeUtf8(input.slice(size.hs, cs))); const soft1 = decodeBase64Int(decodeUtf8(input.slice(size.hs + ms, size.hs + ms + os))); const fs = size.fs !== undefined && size.fs > 0 ? size.fs : cs + soft0 * 4; if (input.length < fs) { return { frame: null, n: 0 }; } const padding = "A".repeat(ps); const text = decodeUtf8(input.slice(0, fs)); const rawtext = padding + text.slice(cs, fs); const raw = decodeBase64Url(rawtext).slice(ps + ls); return { frame: { code: hard, count: soft0, index: soft0, ondex: soft1, raw, text }, n: fs }; } } _CodeTable_table = new WeakMap(), _CodeTable_hards = new WeakMap(), _CodeTable_strict = new WeakMap(), _CodeTable_instances = new WeakSet(), _CodeTable_encodeBinary = function _CodeTable_encodeBinary(frame) { const raw = frame.raw ?? new Uint8Array(0); // TODO: xs const size = this.lookup(frame.code); const cs = size.hs + size.ss; const ms = size.ss - size.os; const os = size.os; const n = Math.ceil((cs * 3) / 4); const soft = ms ? encodeBase64Int(frame.count ?? frame.index ?? (size.ls + raw.length) / 3, ms) : ""; const other = os ? encodeBase64Int(frame.ondex ?? 0, os ?? 0) : ""; const padding = 2 * (cs % 4); const bcode = toArray(lshift(decodeBase64Int(frame.code + soft + other), padding), n); const result = new Uint8Array(bcode.length + size.ls + raw.length); result.set(bcode, 0); result.set(raw, bcode.length + size.ls); return result; }, _CodeTable_encodeText = function _CodeTable_encodeText(frame) { const size = this.lookup(frame.code); if (frame.code.length !== size.hs) { throw new Error(`Frame code ${frame.code} length ${frame.code.length} does not match expected size ${size.hs}`); } const ls = size.ls ?? 0; const ms = (size.ss ?? 0) - (size.os ?? 0); const os = size.os ?? 0; const raw = frame.raw ?? new Uint8Array(0); const padSize = (3 - ((raw.byteLength + ls) % 3)) % 3; const padded = prepad(raw, padSize + ls); const soft = ms ? encodeBase64Int(frame.count ?? frame.index ?? padded.byteLength / 3, ms) : ""; const other = os ? encodeBase64Int(frame.ondex ?? 0, os ?? 0) : ""; const result = `${frame.code}${soft}${other}${encodeBase64Url(padded).slice(padSize)}`; if (size.fs !== undefined && size.fs > 0 && result.length < size.fs) { throw new Error(`Encoded size ${result.length} does not match expected size ${size.fs}`); } return encodeUtf8(result); };