@@ -324,7 +324,8 @@ class ZstdCompressContext final : public ZstdContext { |
324 | 324 | CompressionError ResetStream(); |
325 | 325 |
|
326 | 326 | // Zstd specific: |
327 | | - CompressionError Init(uint64_t pledged_src_size); |
| 327 | + CompressionError Init(uint64_t pledged_src_size, |
| 328 | + std::string_view dictionary = {}); |
328 | 329 | CompressionError SetParameter(int key, int value); |
329 | 330 |
|
330 | 331 | // Wrap ZSTD_freeCCtx to remove the return type. |
@@ -349,7 +350,9 @@ class ZstdDecompressContext final : public ZstdContext { |
349 | 350 | CompressionError ResetStream(); |
350 | 351 |
|
351 | 352 | // Zstd specific: |
352 | | - CompressionError Init(uint64_t pledged_src_size); |
| 353 | + CompressionError Init(uint64_t pledged_src_size, |
| 354 | + std::string_view dictionary = {}); |
| 355 | + |
353 | 356 | CompressionError SetParameter(int key, int value); |
354 | 357 |
|
355 | 358 | // Wrap ZSTD_freeDCtx to remove the return type. |
@@ -875,8 +878,10 @@ class ZstdStream final : public CompressionStream<CompressionContext> { |
875 | 878 | Environment* env = Environment::GetCurrent(args); |
876 | 879 | Local<Context> context = env->context(); |
877 | 880 |
|
878 | | - CHECK(args.Length() == 4 && |
879 | | - "init(params, pledgedSrcSize, writeResult, writeCallback)"); |
| 881 | + CHECK((args.Length() == 4 || args.Length() == 5) && |
| 882 | + "init(params, pledgedSrcSize, writeResult, writeCallback[, " |
| 883 | + "dictionary])"); |
| 884 | + |
880 | 885 | ZstdStream* wrap; |
881 | 886 | ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This()); |
882 | 887 |
|
@@ -904,7 +909,19 @@ class ZstdStream final : public CompressionStream<CompressionContext> { |
904 | 909 | } |
905 | 910 |
|
906 | 911 | AllocScope alloc_scope(wrap); |
907 | | - CompressionError err = wrap->context()->Init(pledged_src_size); |
| 912 | + std::string_view dictionary; |
| 913 | + ArrayBufferViewContents<char> contents; |
| 914 | + if (args.Length() == 5 && !args[4]->IsUndefined()) { |
| 915 | + if (!args[4]->IsArrayBufferView()) { |
| 916 | + THROW_ERR_INVALID_ARG_TYPE( |
| 917 | + wrap->env(), "dictionary must be an ArrayBufferView if provided"); |
| 918 | + return; |
| 919 | + } |
| 920 | + contents.ReadValue(args[4]); |
| 921 | + dictionary = std::string_view(contents.data(), contents.length()); |
| 922 | + } |
| 923 | + |
| 924 | + CompressionError err = wrap->context()->Init(pledged_src_size, dictionary); |
908 | 925 | if (err.IsError()) { |
909 | 926 | wrap->EmitError(err); |
910 | 927 | THROW_ERR_ZLIB_INITIALIZATION_FAILED(wrap->env(), err.message); |
@@ -1509,14 +1526,26 @@ CompressionError ZstdCompressContext::SetParameter(int key, int value) { |
1509 | 1526 | return {}; |
1510 | 1527 | } |
1511 | 1528 |
|
1512 | | -CompressionError ZstdCompressContext::Init(uint64_t pledged_src_size) { |
| 1529 | +CompressionError ZstdCompressContext::Init(uint64_t pledged_src_size, |
| 1530 | + std::string_view dictionary) { |
1513 | 1531 | pledged_src_size_ = pledged_src_size; |
1514 | 1532 | cctx_.reset(ZSTD_createCCtx()); |
1515 | 1533 | if (!cctx_) { |
1516 | 1534 | return CompressionError("Could not initialize zstd instance", |
1517 | 1535 | "ERR_ZLIB_INITIALIZATION_FAILED", |
1518 | 1536 | -1); |
1519 | 1537 | } |
| 1538 | + |
| 1539 | + if (!dictionary.empty()) { |
| 1540 | + size_t ret = ZSTD_CCtx_loadDictionary( |
| 1541 | + cctx_.get(), dictionary.data(), dictionary.size()); |
| 1542 | + if (ZSTD_isError(ret)) { |
| 1543 | + return CompressionError("Failed to load zstd dictionary", |
| 1544 | + "ERR_ZLIB_DICTIONARY_LOAD_FAILED", |
| 1545 | + -1); |
| 1546 | + } |
| 1547 | + } |
| 1548 | + |
1520 | 1549 | size_t result = ZSTD_CCtx_setPledgedSrcSize(cctx_.get(), pledged_src_size); |
1521 | 1550 | if (ZSTD_isError(result)) { |
1522 | 1551 | return CompressionError( |
@@ -1549,13 +1578,24 @@ CompressionError ZstdDecompressContext::SetParameter(int key, int value) { |
1549 | 1578 | return {}; |
1550 | 1579 | } |
1551 | 1580 |
|
1552 | | -CompressionError ZstdDecompressContext::Init(uint64_t pledged_src_size) { |
| 1581 | +CompressionError ZstdDecompressContext::Init(uint64_t pledged_src_size, |
| 1582 | + std::string_view dictionary) { |
1553 | 1583 | dctx_.reset(ZSTD_createDCtx()); |
1554 | 1584 | if (!dctx_) { |
1555 | 1585 | return CompressionError("Could not initialize zstd instance", |
1556 | 1586 | "ERR_ZLIB_INITIALIZATION_FAILED", |
1557 | 1587 | -1); |
1558 | 1588 | } |
| 1589 | + |
| 1590 | + if (!dictionary.empty()) { |
| 1591 | + size_t ret = ZSTD_DCtx_loadDictionary( |
| 1592 | + dctx_.get(), dictionary.data(), dictionary.size()); |
| 1593 | + if (ZSTD_isError(ret)) { |
| 1594 | + return CompressionError("Failed to load zstd dictionary", |
| 1595 | + "ERR_ZLIB_DICTIONARY_LOAD_FAILED", |
| 1596 | + -1); |
| 1597 | + } |
| 1598 | + } |
1559 | 1599 | return {}; |
1560 | 1600 | } |
1561 | 1601 |
|
|