| 
1 | 1 | // The structure is from the MDN docs: https://developer.mozilla.org/en-US/docs/Web/API/TransformStream  | 
2 | 2 | 
 
  | 
3 |  | -import type { CompressStream, BrotliWasmType } from 'brotli-wasm'  | 
 | 3 | +import type { CompressStream, BrotliWasmType, DecompressStream } from 'brotli-wasm'  | 
4 | 4 | 
 
  | 
5 | 5 | interface BrotliCompressTransformer extends Transformer<Uint8Array, Uint8Array> {  | 
6 | 6 |   brotliWasm: BrotliWasmType  | 
@@ -49,3 +49,44 @@ export class BrotliCompressTransformStream extends TransformStream<Uint8Array, U  | 
49 | 49 |     super(brotliCompressTransformerBuilder(brotliWasm, outputSize, quality))  | 
50 | 50 |   }  | 
51 | 51 | }  | 
 | 52 | + | 
 | 53 | +interface BrotliDecompressTransformer extends Transformer<Uint8Array, Uint8Array> {  | 
 | 54 | +  brotliWasm: BrotliWasmType  | 
 | 55 | +  outputSize: number  | 
 | 56 | +  stream: DecompressStream  | 
 | 57 | +}  | 
 | 58 | + | 
 | 59 | +const brotliDecompressTransformerBuilder: (  | 
 | 60 | +  brotliWasm: BrotliWasmType,  | 
 | 61 | +  outputSize: number  | 
 | 62 | +) => BrotliDecompressTransformer = (brotliWasm, outputSize) => ({  | 
 | 63 | +  brotliWasm,  | 
 | 64 | +  outputSize,  | 
 | 65 | +  stream: new brotliWasm.DecompressStream(),  | 
 | 66 | +  start() {},  | 
 | 67 | +  transform(chunk, controller) {  | 
 | 68 | +    let resultCode  | 
 | 69 | +    let inputOffset = 0  | 
 | 70 | +    do {  | 
 | 71 | +      const input = chunk.slice(inputOffset)  | 
 | 72 | +      const result = this.stream.decompress(input, this.outputSize)  | 
 | 73 | +      controller.enqueue(result.buf)  | 
 | 74 | +      resultCode = result.code  | 
 | 75 | +      inputOffset += result.input_offset  | 
 | 76 | +    } while (resultCode === brotliWasm.BrotliStreamResultCode.NeedsMoreOutput)  | 
 | 77 | +    if (  | 
 | 78 | +      resultCode !== brotliWasm.BrotliStreamResultCode.NeedsMoreInput &&  | 
 | 79 | +      resultCode !== brotliWasm.BrotliStreamResultCode.ResultSuccess  | 
 | 80 | +    ) {  | 
 | 81 | +      controller.error(`Brotli decompression failed with code ${resultCode}`)  | 
 | 82 | +    }  | 
 | 83 | +  },  | 
 | 84 | +  // Brotli decompression does not need flushing  | 
 | 85 | +  flush() {},  | 
 | 86 | +})  | 
 | 87 | + | 
 | 88 | +export class BrotliDecompressTransformStream extends TransformStream<Uint8Array, Uint8Array> {  | 
 | 89 | +  constructor(brotliWasm: BrotliWasmType, outputSize: number) {  | 
 | 90 | +    super(brotliDecompressTransformerBuilder(brotliWasm, outputSize))  | 
 | 91 | +  }  | 
 | 92 | +}  | 
0 commit comments