Skip to content

Commit cecfdce

Browse files
authored
zlib: accept ArrayBuffer dictionary in Zstd
Fixes: #64598 Signed-off-by: islandryu <shimaryuhei@gmail.com> PR-URL: #64599 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent 8cf16b3 commit cecfdce

3 files changed

Lines changed: 33 additions & 3 deletions

File tree

doc/api/zlib.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,10 @@ added:
10991099
- v23.8.0
11001100
- v22.15.0
11011101
changes:
1102+
- version: REPLACEME
1103+
pr-url: https://github.com/nodejs/node/pull/64599
1104+
description: The `dictionary` option can be a `TypedArray`, `DataView`, or
1105+
`ArrayBuffer`.
11021106
- version: v26.5.0
11031107
pr-url: https://github.com/nodejs/node/pull/64023
11041108
description: The `rejectGarbageAfterEnd` option was added.
@@ -1115,8 +1119,8 @@ Each Zstd-based class takes an `options` object. All options are optional.
11151119
* `maxOutputLength` {integer} Limits output size when using
11161120
[convenience methods][]. **Default:** [`buffer.kMaxLength`][]
11171121
* `info` {boolean} If `true`, returns an object with `buffer` and `engine`. **Default:** `false`
1118-
* `dictionary` {Buffer} Optional dictionary used to
1119-
improve compression efficiency when compressing or decompressing data that
1122+
* `dictionary` {Buffer|TypedArray|DataView|ArrayBuffer} Optional dictionary used
1123+
to improve compression efficiency when compressing or decompressing data that
11201124
shares common patterns with the dictionary.
11211125
* `rejectGarbageAfterEnd` {boolean} If `true`, decompression fails when
11221126
input remains after the first complete compressed stream. **Default:** `false`

lib/zlib.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const {
3333
ObjectSetPrototypeOf,
3434
Symbol,
3535
Uint32Array,
36+
Uint8Array,
3637
} = primordials;
3738

3839
const {
@@ -926,6 +927,15 @@ class Zstd extends ZlibBase {
926927
});
927928
}
928929

930+
let dictionary = opts?.dictionary;
931+
if (dictionary !== undefined && !isArrayBufferView(dictionary)) {
932+
if (isAnyArrayBuffer(dictionary)) {
933+
dictionary = new Uint8Array(dictionary);
934+
} else {
935+
dictionary = undefined;
936+
}
937+
}
938+
929939
const handle = mode === ZSTD_COMPRESS ?
930940
new binding.ZstdCompress() : new binding.ZstdDecompress();
931941

@@ -938,7 +948,7 @@ class Zstd extends ZlibBase {
938948
pledgedSrcSize,
939949
writeState,
940950
processCallback,
941-
opts?.dictionary && isArrayBufferView(opts.dictionary) ? opts.dictionary : undefined,
951+
dictionary,
942952
);
943953

944954
super(opts, mode, handle, zstdDefaultOpts);

test/parallel/test-zlib-zstd-dictionary.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@ zlib.zstdCompress(input, { dictionary }, common.mustSucceed((compressed) => {
2424
assert.strictEqual(decompressed.toString(), input.toString());
2525
}));
2626
}));
27+
28+
const baseline = zlib.zstdCompressSync(input, { dictionary }).length;
29+
30+
const arrayBuffer = dictionary.buffer.slice(
31+
dictionary.byteOffset, dictionary.byteOffset + dictionary.byteLength);
32+
const uint8 = new Uint8Array(arrayBuffer);
33+
const dataView = new DataView(arrayBuffer);
34+
35+
for (const dict of [arrayBuffer, uint8, dataView]) {
36+
assert.strictEqual(zlib.zstdCompressSync(input, { dictionary: dict }).length,
37+
baseline);
38+
39+
const compressed = zlib.zstdCompressSync(input, { dictionary: dict });
40+
const decompressed = zlib.zstdDecompressSync(compressed, { dictionary: dict });
41+
assert.strictEqual(decompressed.toString(), input.toString());
42+
}

0 commit comments

Comments
 (0)