@@ -49,6 +49,7 @@ const {
49
49
ERR_INVALID_ARG_TYPE ,
50
50
ERR_OUT_OF_RANGE ,
51
51
ERR_ZLIB_INITIALIZATION_FAILED ,
52
+ ERR_ZSTD_INVALID_PARAM ,
52
53
} ,
53
54
genericNodeError,
54
55
hideStackFrames,
@@ -88,9 +89,12 @@ const {
88
89
// Node's compression stream modes (node_zlib_mode)
89
90
DEFLATE , DEFLATERAW , INFLATE , INFLATERAW , GZIP , GUNZIP , UNZIP ,
90
91
BROTLI_DECODE , BROTLI_ENCODE ,
92
+ ZSTD_COMPRESS , ZSTD_DECOMPRESS ,
91
93
// Brotli operations (~flush levels)
92
94
BROTLI_OPERATION_PROCESS , BROTLI_OPERATION_FLUSH ,
93
95
BROTLI_OPERATION_FINISH , BROTLI_OPERATION_EMIT_METADATA ,
96
+ // Zstd end directives (~flush levels)
97
+ ZSTD_e_continue, ZSTD_e_flush, ZSTD_e_end,
94
98
} = constants ;
95
99
96
100
// Translation table for return codes.
@@ -237,9 +241,11 @@ const checkRangesOrGetDefault = hideStackFrames(
237
241
const FLUSH_BOUND = [
238
242
[ Z_NO_FLUSH , Z_BLOCK ] ,
239
243
[ BROTLI_OPERATION_PROCESS , BROTLI_OPERATION_EMIT_METADATA ] ,
244
+ [ ZSTD_e_continue , ZSTD_e_end ] ,
240
245
] ;
241
246
const FLUSH_BOUND_IDX_NORMAL = 0 ;
242
247
const FLUSH_BOUND_IDX_BROTLI = 1 ;
248
+ const FLUSH_BOUND_IDX_ZSTD = 2 ;
243
249
244
250
// The base class for all Zlib-style streams.
245
251
function ZlibBase ( opts , mode , handle , { flush, finishFlush, fullFlush } ) {
@@ -248,13 +254,15 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) {
248
254
// The ZlibBase class is not exported to user land, the mode should only be
249
255
// passed in by us.
250
256
assert ( typeof mode === 'number' ) ;
251
- assert ( mode >= DEFLATE && mode <= BROTLI_ENCODE ) ;
257
+ assert ( mode >= DEFLATE && mode <= ZSTD_DECOMPRESS ) ;
252
258
253
259
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 ) {
257
261
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 ;
258
266
}
259
267
260
268
if ( opts ) {
@@ -888,6 +896,77 @@ ObjectSetPrototypeOf(BrotliDecompress.prototype, Brotli.prototype);
888
896
ObjectSetPrototypeOf ( BrotliDecompress , Brotli ) ;
889
897
890
898
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 ,
910
+ finishFlush : ZSTD_e_end ,
911
+ fullFlush : ZSTD_e_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
+
891
970
function createProperty ( ctor ) {
892
971
return {
893
972
__proto__ : null ,
@@ -917,6 +996,8 @@ module.exports = {
917
996
Unzip,
918
997
BrotliCompress,
919
998
BrotliDecompress,
999
+ ZstdCompress,
1000
+ ZstdDecompress,
920
1001
921
1002
// Convenience methods.
922
1003
// compress/decompress a string or buffer in one step.
@@ -938,6 +1019,10 @@ module.exports = {
938
1019
brotliCompressSync : createConvenienceMethod ( BrotliCompress , true ) ,
939
1020
brotliDecompress : createConvenienceMethod ( BrotliDecompress , false ) ,
940
1021
brotliDecompressSync : createConvenienceMethod ( BrotliDecompress , true ) ,
1022
+ zstdCompress : createConvenienceMethod ( ZstdCompress , false ) ,
1023
+ zstdCompressSync : createConvenienceMethod ( ZstdCompress , true ) ,
1024
+ zstdDecompress : createConvenienceMethod ( ZstdDecompress , false ) ,
1025
+ zstdDecompressSync : createConvenienceMethod ( ZstdDecompress , true ) ,
941
1026
} ;
942
1027
943
1028
ObjectDefineProperties ( module . exports , {
@@ -950,6 +1035,8 @@ ObjectDefineProperties(module.exports, {
950
1035
createUnzip : createProperty ( Unzip ) ,
951
1036
createBrotliCompress : createProperty ( BrotliCompress ) ,
952
1037
createBrotliDecompress : createProperty ( BrotliDecompress ) ,
1038
+ createZstdCompress : createProperty ( ZstdCompress ) ,
1039
+ createZstdDecompress : createProperty ( ZstdDecompress ) ,
953
1040
constants : {
954
1041
__proto__ : null ,
955
1042
configurable : false ,
0 commit comments