fast-md5-web
Version:
A TypeScript project with tsup bundler for Rust WASM MD5 calculation
131 lines (129 loc) • 3.33 kB
JavaScript
"use client"
// src/md5-worker.ts
import WasmInit, { Md5Calculator } from "../wasm/pkg";
var calculator = null;
var sharedMemoryView = null;
var streamStates = /* @__PURE__ */ new Map();
self.onmessage = async function(e) {
const { id, type, data } = e.data;
if (type === "init_shared_memory") {
if (data?.sharedMemory) {
sharedMemoryView = new Uint8Array(data.sharedMemory);
}
return;
}
if (type === "calculate") {
try {
if (!calculator) {
await WasmInit();
calculator = new Md5Calculator();
}
if (data?.isStreamMode) {
await initializeStreamProcessing(id, data);
} else {
await processNormalFile(id, data);
}
} catch (error) {
streamStates.delete(id);
self.postMessage({
id,
type: "error",
data: { error: error.message }
});
}
}
if (type === "calculate_chunk") {
try {
await processChunk(id, data);
} catch (error) {
streamStates.delete(id);
self.postMessage({
id,
type: "error",
data: { error: error.message }
});
}
}
};
async function initializeStreamProcessing(id, data) {
if (!calculator) {
await WasmInit();
calculator = new Md5Calculator();
}
const hasher = new Md5Calculator();
hasher.start_incremental_md5(id);
streamStates.set(id, {
hasher,
processedChunks: 0,
totalChunks: data.totalChunks || 1,
totalSize: data.dataLength || 0,
processedSize: 0
});
}
async function processChunk(id, data) {
const state = streamStates.get(id);
if (!state) {
throw new Error("Stream state not found");
}
let chunkData;
if (data?.dataOffset !== void 0 && data?.dataLength !== void 0 && sharedMemoryView) {
chunkData = sharedMemoryView.slice(
data.dataOffset,
data.dataOffset + data.dataLength
);
} else if (data?.chunkData) {
chunkData = new Uint8Array(data.chunkData);
} else {
throw new Error("No valid chunk data provided");
}
const updateSuccess = state.hasher.update_incremental_md5(id, chunkData);
if (!updateSuccess) {
throw new Error("Failed to update incremental MD5");
}
state.processedChunks++;
state.processedSize += chunkData.length;
const progress = state.processedChunks / state.totalChunks * 100;
self.postMessage({
id,
type: "progress",
data: { progress }
});
if (state.processedChunks >= state.totalChunks) {
const result = state.hasher.finalize_incremental_md5(
id,
data.md5Length || 32
);
streamStates.delete(id);
self.postMessage({
id,
type: "result",
data: { result }
});
}
}
async function processNormalFile(id, data) {
if (!calculator) {
await WasmInit();
calculator = new Md5Calculator();
}
let fileData;
if (data?.dataOffset !== void 0 && data?.dataLength !== void 0 && sharedMemoryView) {
fileData = sharedMemoryView.slice(
data.dataOffset,
data.dataOffset + data.dataLength
);
} else if (data?.fileData) {
fileData = new Uint8Array(data.fileData);
} else {
throw new Error("No valid data source provided");
}
const result = await calculator.calculate_md5_async(
fileData,
data.md5Length
);
self.postMessage({
id,
type: "result",
data: { result }
});
}