source: frontend/node_modules/webpack/lib/util/hash/hash-digest.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Alexander Akait @alexander-akait
4*/
5
6"use strict";
7
8/** @typedef {import("../Hash")} Hash */
9/** @typedef {import("../../../declarations/WebpackOptions").HashDigest} Encoding */
10
11/** @typedef {"26" | "32" | "36" | "49" | "52" | "58" | "62"} Base */
12
13/* cSpell:disable */
14
15/** @type {Record<Base, string>} */
16const ENCODE_TABLE = Object.freeze({
17 26: "abcdefghijklmnopqrstuvwxyz",
18 32: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
19 36: "0123456789abcdefghijklmnopqrstuvwxyz",
20 49: "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ",
21 52: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
22 58: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
23 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
24});
25
26/* cSpell:enable */
27
28const ZERO = BigInt("0");
29const EIGHT = BigInt("8");
30const FF = BigInt("0xff");
31
32/**
33 * It encodes octet arrays by doing long divisions on all significant digits in the array, creating a representation of that number in the new base.
34 * Then for every leading zero in the input (not significant as a number) it will encode as a single leader character.
35 * This is the first in the alphabet and will decode as 8 bits. The other characters depend upon the base.
36 * For example, a base58 alphabet packs roughly 5.858 bits per character.
37 * This means the encoded string 000f (using a base16, 0-f alphabet) will actually decode to 4 bytes unlike a canonical hex encoding which uniformly packs 4 bits into each character.
38 * While unusual, this does mean that no padding is required, and it works for bases like 43.
39 * @param {Buffer} buffer buffer
40 * @param {Base} base base
41 * @returns {string} encoded buffer
42 */
43const encode = (buffer, base) => {
44 if (buffer.length === 0) return "";
45 const bigIntBase = BigInt(ENCODE_TABLE[base].length);
46 // Convert buffer to BigInt efficiently using bitwise operations
47 let value = ZERO;
48 for (let i = 0; i < buffer.length; i++) {
49 value = (value << EIGHT) | BigInt(buffer[i]);
50 }
51 // Convert to baseX string efficiently using array
52 /** @type {string[]} */
53 const digits = [];
54 if (value === ZERO) return ENCODE_TABLE[base][0];
55 while (value > ZERO) {
56 const remainder = Number(value % bigIntBase);
57 digits.push(ENCODE_TABLE[base][remainder]);
58 value /= bigIntBase;
59 }
60 return digits.reverse().join("");
61};
62
63/**
64 * Returns buffer.
65 * @param {string} data string
66 * @param {Base} base base
67 * @returns {Buffer} buffer
68 */
69const decode = (data, base) => {
70 if (data.length === 0) return Buffer.from("");
71 const bigIntBase = BigInt(ENCODE_TABLE[base].length);
72 // Convert the baseX string to a BigInt value
73 let value = ZERO;
74 for (let i = 0; i < data.length; i++) {
75 const digit = ENCODE_TABLE[base].indexOf(data[i]);
76 if (digit === -1) {
77 throw new Error(`Invalid character at position ${i}: ${data[i]}`);
78 }
79 value = value * bigIntBase + BigInt(digit);
80 }
81 // If value is 0, return a single-byte buffer with value 0
82 if (value === ZERO) {
83 return Buffer.alloc(1);
84 }
85 // Determine buffer size efficiently by counting bytes
86 let temp = value;
87 let byteLength = 0;
88 while (temp > ZERO) {
89 temp >>= EIGHT;
90 byteLength++;
91 }
92 // Create buffer and fill it from right to left
93 const buffer = Buffer.alloc(byteLength);
94 for (let i = byteLength - 1; i >= 0; i--) {
95 buffer[i] = Number(value & FF);
96 value >>= EIGHT;
97 }
98 return buffer;
99};
100
101// Compatibility with the old hash libraries, they can return different structures, so let's stringify them firstly
102
103/**
104 * Returns a string representation.
105 * @param {string | { toString: (radix: number) => string }} value value
106 * @param {string} encoding encoding
107 * @returns {string} string
108 */
109const toString = (value, encoding) =>
110 typeof value === "string"
111 ? value
112 : Buffer.from(value.toString(16), "hex").toString(
113 /** @type {NodeJS.BufferEncoding} */
114 (encoding)
115 );
116
117/**
118 * Returns buffer.
119 * @param {Buffer | { toString: (radix: number) => string }} value value
120 * @returns {Buffer} buffer
121 */
122const toBuffer = (value) =>
123 Buffer.isBuffer(value) ? value : Buffer.from(value.toString(16), "hex");
124
125let isBase64URLSupported = false;
126
127try {
128 isBase64URLSupported = Boolean(Buffer.from("", "base64url"));
129} catch (_err) {
130 // Nothing
131}
132
133/**
134 * Processes the provided hash.
135 * @param {Hash} hash hash
136 * @param {string | Buffer} data data
137 * @param {Encoding=} encoding encoding of the return value
138 * @returns {void}
139 */
140const update = (hash, data, encoding) => {
141 if (encoding === "base64url" && !isBase64URLSupported) {
142 const base64String = /** @type {string} */ (data)
143 .replace(/-/g, "+")
144 .replace(/_/g, "/");
145 const buf = Buffer.from(base64String, "base64");
146 hash.update(buf);
147 return;
148 } else if (
149 typeof data === "string" &&
150 encoding &&
151 typeof ENCODE_TABLE[/** @type {Base} */ (encoding.slice(4))] !== "undefined"
152 ) {
153 const buf = decode(data, /** @type {Base} */ (encoding.slice(4)));
154 hash.update(buf);
155 return;
156 }
157
158 if (encoding) {
159 hash.update(/** @type {string} */ (data), encoding);
160 } else {
161 hash.update(data);
162 }
163};
164
165/**
166 * Returns digest.
167 * @overload
168 * @param {Hash} hash hash
169 * @returns {Buffer} digest
170 */
171/**
172 * Returns digest.
173 * @overload
174 * @param {Hash} hash hash
175 * @param {undefined} encoding encoding of the return value
176 * @param {boolean=} isSafe true when we await right types from digest(), otherwise false
177 * @returns {Buffer} digest
178 */
179/**
180 * Returns digest.
181 * @overload
182 * @param {Hash} hash hash
183 * @param {Encoding} encoding encoding of the return value
184 * @param {boolean=} isSafe true when we await right types from digest(), otherwise false
185 * @returns {string} digest
186 */
187/**
188 * Returns digest.
189 * @param {Hash} hash hash
190 * @param {Encoding=} encoding encoding of the return value
191 * @param {boolean=} isSafe true when we await right types from digest(), otherwise false
192 * @returns {string | Buffer} digest
193 */
194const digest = (hash, encoding, isSafe) => {
195 if (typeof encoding === "undefined") {
196 return isSafe ? hash.digest() : toBuffer(hash.digest());
197 }
198
199 if (encoding === "base64url" && !isBase64URLSupported) {
200 const digest = isSafe
201 ? hash.digest("base64")
202 : toString(hash.digest("base64"), "base64");
203
204 return digest.replace(/\+/g, "-").replace(/\//g, "_").replace(/[=]+$/, "");
205 } else if (
206 typeof ENCODE_TABLE[/** @type {Base} */ (encoding.slice(4))] !== "undefined"
207 ) {
208 const buf = isSafe ? hash.digest() : toBuffer(hash.digest());
209
210 return encode(
211 buf,
212 /** @type {Base} */
213 (encoding.slice(4))
214 );
215 }
216
217 return isSafe
218 ? hash.digest(encoding)
219 : toString(hash.digest(encoding), encoding);
220};
221
222module.exports.decode = decode;
223module.exports.digest = digest;
224module.exports.encode = encode;
225module.exports.update = update;
Note: See TracBrowser for help on using the repository browser.