@tootallnate/ivfc 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
1
 
2
- > @tootallnate/ivfc@0.0.1 build /home/runner/work/switch-tools/switch-tools/packages/ivfc
2
+ > @tootallnate/ivfc@0.0.2 build /home/runner/work/switch-tools/switch-tools/packages/ivfc
3
3
  > tsc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @tootallnate/ivfc
2
2
 
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - e49c0ff: Optimize IVFC hash tree building by batching all per-level SHA-256 block hashes via `Promise.all` instead of sequential awaits, and skip redundant zero-fill for full blocks
8
+
3
9
  ## 0.0.1
4
10
 
5
11
  ### Patch Changes
package/dist/index.js CHANGED
@@ -44,6 +44,9 @@ async function sha256(data, crypto = globalThis.crypto) {
44
44
  /**
45
45
  * Create an IVFC level: hash each block of the source data with SHA-256.
46
46
  * Returns the hash data padded to the IVFC block size boundary.
47
+ *
48
+ * Optimized: hashes all blocks in parallel via Promise.all to reduce
49
+ * per-block async overhead, and avoids redundant zero-fill for full blocks.
47
50
  */
48
51
  async function createLevel(sourceData, crypto = globalThis.crypto) {
49
52
  const blockSize = IVFC_HASH_BLOCK_SIZE;
@@ -54,17 +57,26 @@ async function createLevel(sourceData, crypto = globalThis.crypto) {
54
57
  // Pad to block size boundary
55
58
  const paddedSize = align(hashDataSize, blockSize);
56
59
  const hashes = new Uint8Array(paddedSize);
57
- // Hash each block
58
- const block = new Uint8Array(blockSize);
60
+ // Hash all blocks in parallel
61
+ const hashPromises = [];
59
62
  for (let i = 0; i < numBlocks; i++) {
60
63
  const offset = i * blockSize;
61
64
  const remaining = sourceSize - offset;
62
65
  const readSize = Math.min(remaining, blockSize);
63
- // Zero-fill the block buffer (important for the last partial block)
64
- block.fill(0);
65
- block.set(sourceData.subarray(offset, offset + readSize));
66
- const hash = await sha256(block.subarray(0, readSize), crypto);
67
- hashes.set(hash, i * HASH_SIZE);
66
+ if (readSize === blockSize) {
67
+ // Full block — hash the subarray directly (no copy needed)
68
+ hashPromises.push(sha256(sourceData.subarray(offset, offset + blockSize), crypto));
69
+ }
70
+ else {
71
+ // Partial (last) block — zero-pad a copy
72
+ const block = new Uint8Array(blockSize);
73
+ block.set(sourceData.subarray(offset, offset + readSize));
74
+ hashPromises.push(sha256(block.subarray(0, readSize), crypto));
75
+ }
76
+ }
77
+ const hashResults = await Promise.all(hashPromises);
78
+ for (let i = 0; i < numBlocks; i++) {
79
+ hashes.set(hashResults[i], i * HASH_SIZE);
68
80
  }
69
81
  return { hashes, hashDataSize };
70
82
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tootallnate/ivfc",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "description": "IVFC (Integrity Verification File Collection) hash tree builder for Nintendo Switch",
6
6
  "main": "dist/index.js",
package/src/index.ts CHANGED
@@ -56,6 +56,9 @@ async function sha256(
56
56
  /**
57
57
  * Create an IVFC level: hash each block of the source data with SHA-256.
58
58
  * Returns the hash data padded to the IVFC block size boundary.
59
+ *
60
+ * Optimized: hashes all blocks in parallel via Promise.all to reduce
61
+ * per-block async overhead, and avoids redundant zero-fill for full blocks.
59
62
  */
60
63
  async function createLevel(
61
64
  sourceData: Uint8Array,
@@ -72,19 +75,29 @@ async function createLevel(
72
75
  const paddedSize = align(hashDataSize, blockSize);
73
76
  const hashes = new Uint8Array(paddedSize);
74
77
 
75
- // Hash each block
76
- const block = new Uint8Array(blockSize);
78
+ // Hash all blocks in parallel
79
+ const hashPromises: Promise<Uint8Array>[] = [];
77
80
  for (let i = 0; i < numBlocks; i++) {
78
81
  const offset = i * blockSize;
79
82
  const remaining = sourceSize - offset;
80
83
  const readSize = Math.min(remaining, blockSize);
81
84
 
82
- // Zero-fill the block buffer (important for the last partial block)
83
- block.fill(0);
84
- block.set(sourceData.subarray(offset, offset + readSize));
85
+ if (readSize === blockSize) {
86
+ // Full block — hash the subarray directly (no copy needed)
87
+ hashPromises.push(
88
+ sha256(sourceData.subarray(offset, offset + blockSize), crypto)
89
+ );
90
+ } else {
91
+ // Partial (last) block — zero-pad a copy
92
+ const block = new Uint8Array(blockSize);
93
+ block.set(sourceData.subarray(offset, offset + readSize));
94
+ hashPromises.push(sha256(block.subarray(0, readSize), crypto));
95
+ }
96
+ }
85
97
 
86
- const hash = await sha256(block.subarray(0, readSize), crypto);
87
- hashes.set(hash, i * HASH_SIZE);
98
+ const hashResults = await Promise.all(hashPromises);
99
+ for (let i = 0; i < numBlocks; i++) {
100
+ hashes.set(hashResults[i], i * HASH_SIZE);
88
101
  }
89
102
 
90
103
  return { hashes, hashDataSize };