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

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8// 65536 is the size of a wasm memory page
9// 64 is the maximum chunk size for every possible wasm hash implementation
10// 4 is the maximum number of bytes per char for string encoding (max is utf-8)
11// ~3 makes sure that it's always a block of 4 chars, so avoid partially encoded bytes for base64
12const MAX_SHORT_STRING = Math.floor((65536 - 64) / 4) & ~3;
13
14class WasmHash {
15 /**
16 * @param {WebAssembly.Instance} instance wasm instance
17 * @param {WebAssembly.Instance[]} instancesPool pool of instances
18 * @param {number} chunkSize size of data chunks passed to wasm
19 * @param {number} digestSize size of digest returned by wasm
20 */
21 constructor(instance, instancesPool, chunkSize, digestSize) {
22 const exports = /** @type {any} */ (instance.exports);
23 exports.init();
24 this.exports = exports;
25 this.mem = Buffer.from(exports.memory.buffer, 0, 65536);
26 this.buffered = 0;
27 this.instancesPool = instancesPool;
28 this.chunkSize = chunkSize;
29 this.digestSize = digestSize;
30 }
31
32 reset() {
33 this.buffered = 0;
34 this.exports.init();
35 }
36
37 /**
38 * @param {Buffer | string} data data
39 * @param {BufferEncoding=} encoding encoding
40 * @returns {this} itself
41 */
42 update(data, encoding) {
43 if (typeof data === "string") {
44 while (data.length > MAX_SHORT_STRING) {
45 this._updateWithShortString(data.slice(0, MAX_SHORT_STRING), encoding);
46 data = data.slice(MAX_SHORT_STRING);
47 }
48 this._updateWithShortString(data, encoding);
49 return this;
50 }
51 this._updateWithBuffer(data);
52 return this;
53 }
54
55 /**
56 * @param {string} data data
57 * @param {BufferEncoding=} encoding encoding
58 * @returns {void}
59 */
60 _updateWithShortString(data, encoding) {
61 const { exports, buffered, mem, chunkSize } = this;
62 let endPos;
63 if (data.length < 70) {
64 if (!encoding || encoding === "utf-8" || encoding === "utf8") {
65 endPos = buffered;
66 for (let i = 0; i < data.length; i++) {
67 const cc = data.charCodeAt(i);
68 if (cc < 0x80) mem[endPos++] = cc;
69 else if (cc < 0x800) {
70 mem[endPos] = (cc >> 6) | 0xc0;
71 mem[endPos + 1] = (cc & 0x3f) | 0x80;
72 endPos += 2;
73 } else {
74 // bail-out for weird chars
75 endPos += mem.write(data.slice(i), endPos, encoding);
76 break;
77 }
78 }
79 } else if (encoding === "latin1") {
80 endPos = buffered;
81 for (let i = 0; i < data.length; i++) {
82 const cc = data.charCodeAt(i);
83 mem[endPos++] = cc;
84 }
85 } else {
86 endPos = buffered + mem.write(data, buffered, encoding);
87 }
88 } else {
89 endPos = buffered + mem.write(data, buffered, encoding);
90 }
91 if (endPos < chunkSize) {
92 this.buffered = endPos;
93 } else {
94 const l = endPos & ~(this.chunkSize - 1);
95 exports.update(l);
96 const newBuffered = endPos - l;
97 this.buffered = newBuffered;
98 if (newBuffered > 0) mem.copyWithin(0, l, endPos);
99 }
100 }
101
102 /**
103 * @param {Buffer} data data
104 * @returns {void}
105 */
106 _updateWithBuffer(data) {
107 const { exports, buffered, mem } = this;
108 const length = data.length;
109 if (buffered + length < this.chunkSize) {
110 data.copy(mem, buffered, 0, length);
111 this.buffered += length;
112 } else {
113 const l = (buffered + length) & ~(this.chunkSize - 1);
114 if (l > 65536) {
115 let i = 65536 - buffered;
116 data.copy(mem, buffered, 0, i);
117 exports.update(65536);
118 const stop = l - buffered - 65536;
119 while (i < stop) {
120 data.copy(mem, 0, i, i + 65536);
121 exports.update(65536);
122 i += 65536;
123 }
124 data.copy(mem, 0, i, l - buffered);
125 exports.update(l - buffered - i);
126 } else {
127 data.copy(mem, buffered, 0, l - buffered);
128 exports.update(l);
129 }
130 const newBuffered = length + buffered - l;
131 this.buffered = newBuffered;
132 if (newBuffered > 0) data.copy(mem, 0, length - newBuffered, length);
133 }
134 }
135
136 /**
137 * @param {BufferEncoding} type type
138 * @returns {Buffer | string} digest
139 */
140 digest(type) {
141 const { exports, buffered, mem, digestSize } = this;
142 exports.final(buffered);
143 this.instancesPool.push(this);
144 const hex = mem.toString("latin1", 0, digestSize);
145 if (type === "hex") return hex;
146 if (type === "binary" || !type) return Buffer.from(hex, "hex");
147 return Buffer.from(hex, "hex").toString(type);
148 }
149}
150
151/**
152 * @param {TODO} wasmModule wasm module
153 * @param {WasmHash[]} instancesPool pool of instances
154 * @param {number} chunkSize size of data chunks passed to wasm
155 * @param {number} digestSize size of digest returned by wasm
156 * @returns {WasmHash} wasm hash
157 */
158const create = (wasmModule, instancesPool, chunkSize, digestSize) => {
159 if (instancesPool.length > 0) {
160 const old = /** @type {WasmHash} */ (instancesPool.pop());
161 old.reset();
162 return old;
163 }
164
165 return new WasmHash(
166 new WebAssembly.Instance(wasmModule),
167 instancesPool,
168 chunkSize,
169 digestSize
170 );
171};
172
173module.exports = create;
174module.exports.MAX_SHORT_STRING = MAX_SHORT_STRING;
Note: See TracBrowser for help on using the repository browser.