zlib: add dictionary support to zstdCompress and zstdDecompress · nodejs/node@2013045

@@ -324,7 +324,8 @@ class ZstdCompressContext final : public ZstdContext {

324324

CompressionError ResetStream();

325325326326

// Zstd specific:

327-

CompressionError Init(uint64_t pledged_src_size);

327+

CompressionError Init(uint64_t pledged_src_size,

328+

std::string_view dictionary = {});

328329

CompressionError SetParameter(int key, int value);

329330330331

// Wrap ZSTD_freeCCtx to remove the return type.

@@ -349,7 +350,9 @@ class ZstdDecompressContext final : public ZstdContext {

349350

CompressionError ResetStream();

350351351352

// Zstd specific:

352-

CompressionError Init(uint64_t pledged_src_size);

353+

CompressionError Init(uint64_t pledged_src_size,

354+

std::string_view dictionary = {});

355+353356

CompressionError SetParameter(int key, int value);

354357355358

// Wrap ZSTD_freeDCtx to remove the return type.

@@ -875,8 +878,10 @@ class ZstdStream final : public CompressionStream<CompressionContext> {

875878

Environment* env = Environment::GetCurrent(args);

876879

Local<Context> context = env->context();

877880878-

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+880885

ZstdStream* wrap;

881886

ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());

882887

@@ -904,7 +909,19 @@ class ZstdStream final : public CompressionStream<CompressionContext> {

904909

}

905910906911

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);

908925

if (err.IsError()) {

909926

wrap->EmitError(err);

910927

THROW_ERR_ZLIB_INITIALIZATION_FAILED(wrap->env(), err.message);

@@ -1509,14 +1526,26 @@ CompressionError ZstdCompressContext::SetParameter(int key, int value) {

15091526

return {};

15101527

}

151115281512-

CompressionError ZstdCompressContext::Init(uint64_t pledged_src_size) {

1529+

CompressionError ZstdCompressContext::Init(uint64_t pledged_src_size,

1530+

std::string_view dictionary) {

15131531

pledged_src_size_ = pledged_src_size;

15141532

cctx_.reset(ZSTD_createCCtx());

15151533

if (!cctx_) {

15161534

return CompressionError("Could not initialize zstd instance",

15171535

"ERR_ZLIB_INITIALIZATION_FAILED",

15181536

-1);

15191537

}

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+15201549

size_t result = ZSTD_CCtx_setPledgedSrcSize(cctx_.get(), pledged_src_size);

15211550

if (ZSTD_isError(result)) {

15221551

return CompressionError(

@@ -1549,13 +1578,24 @@ CompressionError ZstdDecompressContext::SetParameter(int key, int value) {

15491578

return {};

15501579

}

155115801552-

CompressionError ZstdDecompressContext::Init(uint64_t pledged_src_size) {

1581+

CompressionError ZstdDecompressContext::Init(uint64_t pledged_src_size,

1582+

std::string_view dictionary) {

15531583

dctx_.reset(ZSTD_createDCtx());

15541584

if (!dctx_) {

15551585

return CompressionError("Could not initialize zstd instance",

15561586

"ERR_ZLIB_INITIALIZATION_FAILED",

15571587

-1);

15581588

}

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+

}

15591599

return {};

15601600

}

15611601