@hugoalh/adler32
Version:
A CLI and module to get the checksum of the data with algorithm Adler32.
131 lines (130 loc) • 3.35 kB
JavaScript
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;