@@ -49,6 +49,7 @@ const {
4949    ERR_INVALID_ARG_TYPE , 
5050    ERR_OUT_OF_RANGE , 
5151    ERR_ZLIB_INITIALIZATION_FAILED , 
52+     ERR_ZSTD_INVALID_PARAM , 
5253  } , 
5354  genericNodeError, 
5455  hideStackFrames, 
@@ -88,9 +89,12 @@ const {
8889  // Node's compression stream modes (node_zlib_mode) 
8990  DEFLATE ,  DEFLATERAW ,  INFLATE ,  INFLATERAW ,  GZIP ,  GUNZIP ,  UNZIP , 
9091  BROTLI_DECODE ,  BROTLI_ENCODE , 
92+   ZSTD_COMPRESS ,  ZSTD_DECOMPRESS , 
9193  // Brotli operations (~flush levels) 
9294  BROTLI_OPERATION_PROCESS ,  BROTLI_OPERATION_FLUSH , 
9395  BROTLI_OPERATION_FINISH ,  BROTLI_OPERATION_EMIT_METADATA , 
96+   // Zstd end directives (~flush levels) 
97+   ZSTD_e_continue,  ZSTD_e_flush,  ZSTD_e_end, 
9498}  =  constants ; 
9599
96100// Translation table for return codes. 
@@ -237,9 +241,11 @@ const checkRangesOrGetDefault = hideStackFrames(
237241const  FLUSH_BOUND  =  [ 
238242  [  Z_NO_FLUSH ,  Z_BLOCK  ] , 
239243  [  BROTLI_OPERATION_PROCESS ,  BROTLI_OPERATION_EMIT_METADATA  ] , 
244+   [  ZSTD_e_continue ,  ZSTD_e_end  ] , 
240245] ; 
241246const  FLUSH_BOUND_IDX_NORMAL  =  0 ; 
242247const  FLUSH_BOUND_IDX_BROTLI  =  1 ; 
248+ const  FLUSH_BOUND_IDX_ZSTD  =  2 ; 
243249
244250// The base class for all Zlib-style streams. 
245251function  ZlibBase ( opts ,  mode ,  handle ,  {  flush,  finishFlush,  fullFlush } )  { 
@@ -248,13 +254,15 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) {
248254  // The ZlibBase class is not exported to user land, the mode should only be 
249255  // passed in by us. 
250256  assert ( typeof  mode  ===  'number' ) ; 
251-   assert ( mode  >=  DEFLATE  &&  mode  <=  BROTLI_ENCODE ) ; 
257+   assert ( mode  >=  DEFLATE  &&  mode  <=  ZSTD_DECOMPRESS ) ; 
252258
253259  let  flushBoundIdx ; 
254-   if  ( mode  !==  BROTLI_ENCODE  &&  mode  !==  BROTLI_DECODE )  { 
255-     flushBoundIdx  =  FLUSH_BOUND_IDX_NORMAL ; 
256-   }  else  { 
260+   if  ( mode  ===  BROTLI_ENCODE  ||  mode  ===  BROTLI_DECODE )  { 
257261    flushBoundIdx  =  FLUSH_BOUND_IDX_BROTLI ; 
262+   }  else  if  ( mode  ===  ZSTD_COMPRESS  ||  mode  ===  ZSTD_DECOMPRESS )  { 
263+     flushBoundIdx  =  FLUSH_BOUND_IDX_ZSTD ; 
264+   }  else  { 
265+     flushBoundIdx  =  FLUSH_BOUND_IDX_NORMAL ; 
258266  } 
259267
260268  if  ( opts )  { 
@@ -888,6 +896,77 @@ ObjectSetPrototypeOf(BrotliDecompress.prototype, Brotli.prototype);
888896ObjectSetPrototypeOf ( BrotliDecompress ,  Brotli ) ; 
889897
890898
899+ const  kMaxZstdParam  =  MathMaxApply ( ArrayPrototypeMap ( 
900+   ObjectKeys ( constants ) , 
901+   ( key )  =>  ( StringPrototypeStartsWith ( key ,  'ZSTD_c_' )  ?
902+     constants [ key ]  :
903+     0 ) , 
904+ ) ) ; 
905+ 
906+ const  zstdInitParamsArray  =  new  Uint32Array ( kMaxZstdParam  +  1 ) ; 
907+ 
908+ const  zstdDefaultOpts  =  { 
909+   flush : ZSTD_e_continue ,  // BROTLI_OPERATION_PROCESS, 
910+   finishFlush : ZSTD_e_end ,  // BROTLI_OPERATION_FINISH, 
911+   fullFlush : ZSTD_e_flush ,  // BROTLI_OPERATION_FLUSH, 
912+ } ; 
913+ function  Zstd ( opts ,  mode )  { 
914+   assert ( mode  ===  ZSTD_COMPRESS  ||  mode  ===  ZSTD_DECOMPRESS ) ; 
915+ 
916+   TypedArrayPrototypeFill ( zstdInitParamsArray ,  - 1 ) ; 
917+   if  ( opts ?. params )  { 
918+     ArrayPrototypeForEach ( ObjectKeys ( opts . params ) ,  ( origKey )  =>  { 
919+       const  key  =  + origKey ; 
920+       if  ( NumberIsNaN ( key )  ||  key  <  0  ||  key  >  kMaxZstdParam  || 
921+           ( zstdInitParamsArray [ key ]  |  0 )  !==  - 1 )  { 
922+         throw  new  ERR_ZSTD_INVALID_PARAM ( origKey ) ; 
923+       } 
924+ 
925+       const  value  =  opts . params [ origKey ] ; 
926+       if  ( typeof  value  !==  'number'  &&  typeof  value  !==  'boolean' )  { 
927+         throw  new  ERR_INVALID_ARG_TYPE ( 'options.params[key]' , 
928+                                        'number' ,  opts . params [ origKey ] ) ; 
929+       } 
930+       zstdInitParamsArray [ key ]  =  value ; 
931+     } ) ; 
932+   } 
933+ 
934+   const  handle  =  mode  ===  ZSTD_COMPRESS  ?
935+       new  binding . ZstdCompress ( )  : new  binding . ZstdDecompress ( ) ; 
936+ 
937+   this . _writeState  =  new  Uint32Array ( 2 ) ; 
938+   if  ( ! handle . init ( zstdInitParamsArray , 
939+                    this . _writeState , 
940+                    processCallback ) )  { 
941+     throw  new  ERR_ZLIB_INITIALIZATION_FAILED ( ) ; 
942+   } 
943+ 
944+   ReflectApply ( ZlibBase ,  this ,  [ opts ,  mode ,  handle ,  zstdDefaultOpts ] ) ; 
945+ } 
946+ ObjectSetPrototypeOf ( Zstd . prototype ,  ZlibBase . prototype ) ; 
947+ ObjectSetPrototypeOf ( Zstd ,  ZlibBase ) ; 
948+ 
949+ 
950+ function  ZstdCompress ( opts )  { 
951+   if  ( ! ( this  instanceof  ZstdCompress ) ) 
952+     return  new  ZstdCompress ( opts ) ; 
953+ 
954+   ReflectApply ( Zstd ,  this ,  [ opts ,  ZSTD_COMPRESS ] ) ; 
955+ } 
956+ ObjectSetPrototypeOf ( ZstdCompress . prototype ,  Zstd . prototype ) ; 
957+ ObjectSetPrototypeOf ( ZstdCompress ,  Zstd ) ; 
958+ 
959+ 
960+ function  ZstdDecompress ( opts )  { 
961+   if  ( ! ( this  instanceof  ZstdDecompress ) ) 
962+     return  new  ZstdDecompress ( opts ) ; 
963+ 
964+   ReflectApply ( Zstd ,  this ,  [ opts ,  ZSTD_DECOMPRESS ] ) ; 
965+ } 
966+ ObjectSetPrototypeOf ( ZstdDecompress . prototype ,  Zstd . prototype ) ; 
967+ ObjectSetPrototypeOf ( ZstdDecompress ,  Zstd ) ; 
968+ 
969+ 
891970function  createProperty ( ctor )  { 
892971  return  { 
893972    __proto__ : null , 
@@ -917,6 +996,8 @@ module.exports = {
917996  Unzip, 
918997  BrotliCompress, 
919998  BrotliDecompress, 
999+   ZstdCompress, 
1000+   ZstdDecompress, 
9201001
9211002  // Convenience methods. 
9221003  // compress/decompress a string or buffer in one step. 
@@ -938,6 +1019,10 @@ module.exports = {
9381019  brotliCompressSync : createConvenienceMethod ( BrotliCompress ,  true ) , 
9391020  brotliDecompress : createConvenienceMethod ( BrotliDecompress ,  false ) , 
9401021  brotliDecompressSync : createConvenienceMethod ( BrotliDecompress ,  true ) , 
1022+   zstdCompress : createConvenienceMethod ( ZstdCompress ,  false ) , 
1023+   zstdCompressSync : createConvenienceMethod ( ZstdCompress ,  true ) , 
1024+   zstdDecompress : createConvenienceMethod ( ZstdDecompress ,  false ) , 
1025+   zstdDecompressSync : createConvenienceMethod ( ZstdDecompress ,  true ) , 
9411026} ; 
9421027
9431028ObjectDefineProperties ( module . exports ,  { 
@@ -950,6 +1035,8 @@ ObjectDefineProperties(module.exports, {
9501035  createUnzip : createProperty ( Unzip ) , 
9511036  createBrotliCompress : createProperty ( BrotliCompress ) , 
9521037  createBrotliDecompress : createProperty ( BrotliDecompress ) , 
1038+   createZstdCompress : createProperty ( ZstdCompress ) , 
1039+   createZstdDecompress : createProperty ( ZstdDecompress ) , 
9531040  constants : { 
9541041    __proto__ : null , 
9551042    configurable : false , 
0 commit comments