| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Tobias Koppers @sokra*/"use strict";const AbstractMethodError = require("../AbstractMethodError");const BULK_SIZE = 1000;class Hash {	/**	 * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}	 * @param {string|Buffer} data data	 * @param {string=} inputEncoding data encoding	 * @returns {this} updated hash	 */	update(data, inputEncoding) {		throw new AbstractMethodError();	}	/**	 * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}	 * @param {string=} encoding encoding of the return value	 * @returns {string|Buffer} digest	 */	digest(encoding) {		throw new AbstractMethodError();	}}class BulkUpdateDecorator extends Hash {	/**	 * @param {Hash} hash hash	 */	constructor(hash) {		super();		this.hash = hash;		this.buffer = "";	}	/**	 * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}	 * @param {string|Buffer} data data	 * @param {string=} inputEncoding data encoding	 * @returns {this} updated hash	 */	update(data, inputEncoding) {		if (			inputEncoding !== undefined ||			typeof data !== "string" ||			data.length > BULK_SIZE		) {			if (this.buffer.length > 0) {				this.hash.update(this.buffer);				this.buffer = "";			}			this.hash.update(data, inputEncoding);		} else {			this.buffer += data;			if (this.buffer.length > BULK_SIZE) {				this.hash.update(this.buffer);				this.buffer = "";			}		}		return this;	}	/**	 * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}	 * @param {string=} encoding encoding of the return value	 * @returns {string|Buffer} digest	 */	digest(encoding) {		if (this.buffer.length > 0) {			this.hash.update(this.buffer);		}		var digestResult = this.hash.digest(encoding);		return typeof digestResult === "string"			? digestResult			: digestResult.toString();	}}/** * istanbul ignore next */class DebugHash extends Hash {	constructor() {		super();		this.string = "";	}	/**	 * Update hash {@link https://nodejs.org/api/crypto.html#crypto_hash_update_data_inputencoding}	 * @param {string|Buffer} data data	 * @param {string=} inputEncoding data encoding	 * @returns {this} updated hash	 */	update(data, inputEncoding) {		if (typeof data !== "string") data = data.toString("utf-8");		this.string += data;		return this;	}	/**	 * Calculates the digest {@link https://nodejs.org/api/crypto.html#crypto_hash_digest_encoding}	 * @param {string=} encoding encoding of the return value	 * @returns {string|Buffer} digest	 */	digest(encoding) {		return this.string.replace(/[^a-z0-9]+/gi, m =>			Buffer.from(m).toString("hex")		);	}}/** @type {typeof import("crypto") | undefined} */let crypto = undefined;/** @type {typeof import("./hash/md4") | undefined} */let createMd4 = undefined;/** @type {typeof import("./hash/BatchedHash") | undefined} */let BatchedHash = undefined;/** @type {number} */const NODE_MAJOR_VERSION = parseInt(process.versions.node, 10);/** * Creates a hash by name or function * @param {string | HashConstructor} algorithm the algorithm name or a constructor creating a hash * @returns {Hash} the hash */module.exports = algorithm => {	if (typeof algorithm === "function") {		return new BulkUpdateDecorator(new algorithm());	}	switch (algorithm) {		// TODO add non-cryptographic algorithm here		case "debug":			return new DebugHash();		case "md4":			if (NODE_MAJOR_VERSION >= 18) {				if (createMd4 === undefined) {					createMd4 = require("./hash/md4");					if (BatchedHash === undefined) {						BatchedHash = require("./hash/BatchedHash");					}				}				return new /** @type {typeof import("./hash/BatchedHash")} */ (BatchedHash)(					createMd4()				);			}		// If we are on Node.js < 18, fall through to the default case		// eslint-disable-next-line no-fallthrough		case "native-md4":			if (NODE_MAJOR_VERSION >= 18) {				if (crypto === undefined) crypto = require("crypto");				return new BulkUpdateDecorator(					/** @type {typeof import("crypto")} */ (crypto).createHash("md4")				);			}		// If we are on Node.js < 18, fall through to the default case		// eslint-disable-next-line no-fallthrough		default:			if (crypto === undefined) crypto = require("crypto");			return new BulkUpdateDecorator(crypto.createHash(algorithm));	}};module.exports.Hash = Hash;/** @typedef {typeof Hash} HashConstructor */
 |