UNPKG

@hugoalh/adler32

Version:

A CLI and module to get the checksum of the data with algorithm Adler32.

131 lines (130 loc) 3.35 kB
import "./_dnt.polyfills.js"; /** * Get the checksum of the data with algorithm Adler32. */ export class Adler32 { get [Symbol.toStringTag]() { return "Adler32"; } #freezed = false; #hash = null; #a = 1n; #b = 0n; /** * Initialize. * @param {Adler32AcceptDataType} [data] Data. Can append later via the method {@linkcode Adler32.update}. */ constructor(data) { if (typeof data !== "undefined") { this.update(data); } } /** * Whether the instance is freezed. * @returns {boolean} */ get freezed() { return this.#freezed; } /** * Freeze the instance to prevent any update. * @returns {this} */ freeze() { this.#freezed = true; return this; } /** * Get the checksum of the data, in original format. * @returns {bigint} */ hash() { if (this.#hash === null) { this.#hash = this.#b * 65536n + this.#a; } return this.#hash; } /** * Get the checksum of the data, in Base16. * @returns {string} */ hashBase16() { return this.hashBigInt().toString(16).toUpperCase(); } /** * Get the checksum of the data, in Base32Hex ({@link https://datatracker.ietf.org/doc/html/rfc4648#section-7 RFC 4648 §7}). * @returns {string} */ hashBase32Hex() { return this.hashBigInt().toString(32).toUpperCase(); } /** * Get the checksum of the data, in Base36. * @returns {string} */ hashBase36() { return this.hashBigInt().toString(36).toUpperCase(); } /** * Get the checksum of the data, in big integer. * @returns {bigint} */ hashBigInt() { return this.hash(); } /** * Get the checksum of the data, in big integer. * @returns {bigint} */ hashBigInteger = this.hashBigInt; /** * Get the checksum of the data, in hex/hexadecimal without padding. * @returns {string} */ hashHex() { return this.hashBase16(); } /** * Get the checksum of the data, in hex/hexadecimal with padding. * @returns {string} */ hashHexPadding() { return this.hashHex().padStart(8, "0"); } /** * Get the checksum of the data, in number. * @returns {number} */ hashNumber() { return Number(this.hash()); } /** * Append data. * @param {Adler32AcceptDataType} data Data. * @returns {this} */ update(data) { if (this.#freezed) { throw new Error(`Instance is freezed!`); } this.#hash = null; for (const byte of ((typeof data === "string") ? new TextEncoder().encode(data) : data)) { this.#a = (this.#a + BigInt(byte)) % 65521n; this.#b = (this.#b + this.#a) % 65521n; } return this; } /** * Initialize from the readable stream, asynchronously. * @param {ReadableStream<Adler32AcceptDataType>} stream Readable stream. * @returns {Promise<Adler32>} */ static async fromStream(stream) { const instance = new this(); for await (const chunk of stream) { instance.update(chunk); } return instance; } } export default Adler32;