@@ -88,38 +88,70 @@ const inputStream = new ReadableStream({
88
88
// Convert the streaming data to Uint8Arrays, if necessary:
89
89
const textEncoderStream = new TextEncoderStream ();
90
90
91
+ // You can use whatever stream chunking size you like here, depending on your use case:
92
+ const OUTPUT_SIZE = 100 ;
93
+
91
94
// Create a stream to incrementally compress the data as it streams:
92
95
const compressStream = new brotli.CompressStream ();
93
96
const compressionStream = new TransformStream ({
94
- start () { },
95
97
transform (chunk , controller ) {
96
- // Compress data, producing 1024 bytes of output at a time (i.e. limiting the output):
97
- controller .enqueue (compressStream .compress (chunk, 1024 ));
98
+ let resultCode;
99
+ let inputOffset = 0 ;
100
+
101
+ // Compress this chunk, producing up to OUTPUT_SIZE output bytes at a time, until the
102
+ // entire input has been compressed.
103
+
104
+ do {
105
+ const input = chunk .slice (inputOffset);
106
+ const result = compressStream .compress (input, OUTPUT_SIZE );
107
+ controller .enqueue (result .buf );
108
+ resultCode = result .code ;
109
+ inputOffset += result .input_offset ;
110
+ } while (resultCode === brotli .BrotliStreamResultCode .NeedsMoreOutput );
111
+ if (resultCode !== brotli .BrotliStreamResultCode .NeedsMoreInput ) {
112
+ controller .error (` Brotli compression failed when transforming with code ${ resultCode} ` );
113
+ }
98
114
},
99
115
flush (controller ) {
100
- // Stream remaining compressed data after input finishes, 1024 bytes of output at a time:
101
- while (
102
- compressStream .result () === brotli .BrotliStreamResult .NeedsMoreInput ||
103
- compressStream .result () === brotli .BrotliStreamResult .NeedsMoreOutput
104
- ) {
105
- controller .enqueue (compressStream .compress (undefined , 1024 ));
116
+ // Once the chunks are finished, flush any remaining data (again in repeated fixed-output
117
+ // chunks) to finish the stream:
118
+ let resultCode;
119
+ do {
120
+ const result = compressStream .compress (undefined , OUTPUT_SIZE );
121
+ controller .enqueue (result .buf );
122
+ resultCode = result .code ;
123
+ } while (resultCode === brotli .BrotliStreamResultCode .NeedsMoreOutput )
124
+ if (resultCode !== brotli .BrotliStreamResultCode .ResultSuccess ) {
125
+ controller .error (` Brotli compression failed when flushing with code ${ resultCode} ` );
106
126
}
107
127
controller .terminate ();
108
128
}
109
129
});
110
130
111
131
const decompressStream = new brotli.DecompressStream ();
112
132
const decompressionStream = new TransformStream ({
113
- start () { },
114
133
transform (chunk , controller ) {
115
- // Decompress, producing 1024 bytes of output at a time:
116
- controller .enqueue (decompressStream .decompress (chunk, 1024 ));
134
+ let resultCode;
135
+ let inputOffset = 0 ;
136
+
137
+ // Decompress this chunk, producing up to OUTPUT_SIZE output bytes at a time, until the
138
+ // entire input has been decompressed.
139
+
140
+ do {
141
+ const input = chunk .slice (inputOffset);
142
+ const result = decompressStream .decompress (input, OUTPUT_SIZE );
143
+ controller .enqueue (result .buf );
144
+ resultCode = result .code ;
145
+ inputOffset += result .input_offset ;
146
+ } while (resultCode === brotli .BrotliStreamResultCode .NeedsMoreOutput );
147
+ if (
148
+ resultCode !== brotli .BrotliStreamResultCode .NeedsMoreInput &&
149
+ resultCode !== brotli .BrotliStreamResultCode .ResultSuccess
150
+ ) {
151
+ controller .error (` Brotli decompression failed with code ${ resultCode} ` )
152
+ }
117
153
},
118
154
flush (controller ) {
119
- // Decompress all remaining output after input finishes, 1024 bytes at a time:
120
- while (decompressStream .result () === brotli .BrotliStreamResult .NeedsMoreOutput ) {
121
- controller .enqueue (decompressStream .decompress (new Uint8Array (0 ), 1024 ));
122
- }
123
155
controller .terminate ();
124
156
}
125
157
});
0 commit comments