UNPKG

@hugoalh/djb2a

Version:

A CLI and module to get the non-cryptographic hash of the data with algorithm DJB2a.

130 lines (129 loc) 3.49 kB
import "./_dnt.polyfills.js"; /** * Get the non-cryptographic hash of the data with algorithm DJB2a (32 bits). */ export class DJB2a { get [Symbol.toStringTag]() { return "DJB2a"; } #freezed = false; #hash = null; #bin = 5381n; /** * Initialize. * @param {DJB2aAcceptDataType} [data] Data. Can append later via the method {@linkcode DJB2a.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 non-cryptographic hash of the data, in original format. * @returns {bigint} */ hash() { if (this.#hash === null) { this.#hash = BigInt.asUintN(32, this.#bin); } return this.#hash; } /** * Get the non-cryptographic hash of the data, in Base16. * @returns {string} */ hashBase16() { return this.hashBigInt().toString(16).toUpperCase(); } /** * Get the non-cryptographic hash 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 non-cryptographic hash of the data, in Base36. * @returns {string} */ hashBase36() { return this.hashBigInt().toString(36).toUpperCase(); } /** * Get the non-cryptographic hash of the data, in big integer. * @returns {bigint} */ hashBigInt() { return this.hash(); } /** * Get the non-cryptographic hash of the data, in big integer. * @returns {bigint} */ hashBigInteger = this.hashBigInt; /** * Get the non-cryptographic hash of the data, in hex/hexadecimal without padding. * @returns {string} */ hashHex() { return this.hashBase16(); } /** * Get the non-cryptographic hash of the data, in hex/hexadecimal with padding. * @returns {string} */ hashHexPadding() { return this.hashHex().padStart(8, "0"); } /** * Get the non-cryptographic hash of the data, in number. * @returns {number} */ hashNumber() { return Number(this.hash()); } /** * Append data. * @param {DJB2aAcceptDataType} data Data. * @returns {this} */ update(data) { if (this.#freezed) { throw new Error(`Instance is freezed!`); } this.#hash = null; const raw = (typeof data === "string") ? data : new TextDecoder().decode(data); for (let index = 0; index < raw.length; index += 1) { this.#bin = this.#bin * 33n ^ BigInt(raw.charCodeAt(index)); } return this; } /** * Initialize from the readable stream, asynchronously. * @param {ReadableStream<DJB2aAcceptDataType>} stream Readable stream. * @returns {Promise<DJB2a>} */ static async fromStream(stream) { const instance = new this(); for await (const chunk of stream) { instance.update(chunk); } return instance; } } export default DJB2a;