///|
/// Callback wrapper used by stream-style APIs.
///
/// The wrapped function receives `(data, is_final)`. `data` is the produced
/// output chunk and `is_final` is `true` for the final callback of a stream.
pub(all) struct FlateStreamHandler((FixedArray[Byte], Bool) -> Unit)
///|
fn call_handler(
h : FlateStreamHandler,
data : FixedArray[Byte],
final_ : Bool,
) -> Unit {
(h.0)(data, final_)
}
///|
/// Chunk-oriented raw DEFLATE compressor.
///
/// Set `ondata` before calling `push`. Input chunks are buffered until a call
/// with `final_=true`, then compressed with `deflate_sync` and emitted through
/// `ondata`.
pub(all) struct DeflateStream {
/// Called with compressed data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv o : DeflateOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create a raw DEFLATE compression stream.
pub fn DeflateStream::new(
opts? : DeflateOptions = DeflateOptions::default(),
) -> DeflateStream {
{ ondata: None, o: opts, chunks: [] }
}
///|
/// Push one input chunk into the raw DEFLATE compression stream.
///
/// Chunks are buffered until `final_` is `true`. On the final push, compressed
/// output is sent to `ondata` if a handler is installed.
pub fn DeflateStream::push(
self : DeflateStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = deflate_sync(data, opts=self.o)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
fn concat_chunks(chunks : Array[FixedArray[Byte]]) -> FixedArray[Byte] {
let mut total = 0
for i in 0.. InflateStream {
{ ondata: None, chunks: [], opts }
}
///|
/// Push one input chunk into the raw DEFLATE decompression stream.
///
/// Chunks are buffered until `final_` is `true`. On the final push, decompressed
/// output is sent to `ondata` if a handler is installed.
pub fn InflateStream::push(
self : InflateStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit raise FzipError {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = inflate_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
/// Chunk-oriented GZIP compressor.
///
/// Input chunks are buffered until the final push, then encoded with
/// `gzip_sync` and emitted through `ondata`.
pub(all) struct GzipStream {
/// Called with compressed GZIP data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv opts : GzipOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create a GZIP compression stream.
pub fn GzipStream::new(
opts? : GzipOptions = GzipOptions::default(),
) -> GzipStream {
{ ondata: None, opts, chunks: [] }
}
///|
/// Push one input chunk into the GZIP compression stream.
pub fn GzipStream::push(
self : GzipStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = gzip_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
/// Chunk-oriented GZIP decompressor.
///
/// Input chunks are buffered until the final push, then decoded with
/// `gunzip_sync` and emitted through `ondata`.
pub(all) struct GunzipStream {
/// Called with decompressed data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv opts : GunzipOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create a GZIP decompression stream.
pub fn GunzipStream::new(
opts? : GunzipOptions = GunzipOptions::default(),
) -> GunzipStream {
{ ondata: None, opts, chunks: [] }
}
///|
/// Push one input chunk into the GZIP decompression stream.
pub fn GunzipStream::push(
self : GunzipStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit raise FzipError {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = gunzip_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
/// Chunk-oriented Zlib compressor.
///
/// Input chunks are buffered until the final push, then encoded with
/// `zlib_sync` and emitted through `ondata`.
pub(all) struct ZlibStream {
/// Called with compressed Zlib data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv opts : ZlibOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create a Zlib compression stream.
pub fn ZlibStream::new(
opts? : ZlibOptions = ZlibOptions::default(),
) -> ZlibStream {
{ ondata: None, opts, chunks: [] }
}
///|
/// Push one input chunk into the Zlib compression stream.
pub fn ZlibStream::push(
self : ZlibStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = zlib_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
/// Chunk-oriented Zlib decompressor.
///
/// Input chunks are buffered until the final push, then decoded with
/// `unzlib_sync` and emitted through `ondata`.
pub(all) struct UnzlibStream {
/// Called with decompressed data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv opts : UnzlibOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create a Zlib decompression stream.
pub fn UnzlibStream::new(
opts? : UnzlibOptions = UnzlibOptions::default(),
) -> UnzlibStream {
{ ondata: None, opts, chunks: [] }
}
///|
/// Push one input chunk into the Zlib decompression stream.
pub fn UnzlibStream::push(
self : UnzlibStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit raise FzipError {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = unzlib_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}
///|
/// Chunk-oriented decompressor with automatic format detection.
///
/// Input chunks are buffered until the final push, then decoded with
/// `decompress_sync`. GZIP, Zlib, and raw DEFLATE inputs are supported.
pub(all) struct DecompressStream {
/// Called with decompressed data when a final chunk is pushed.
mut ondata : FlateStreamHandler?
priv opts : InflateOptions
priv mut chunks : Array[FixedArray[Byte]]
}
///|
/// Create an auto-detecting decompression stream.
pub fn DecompressStream::new(
opts? : InflateOptions = InflateOptions::default(),
) -> DecompressStream {
{ ondata: None, opts, chunks: [] }
}
///|
/// Push one input chunk into the auto-detecting decompression stream.
pub fn DecompressStream::push(
self : DecompressStream,
chunk : FixedArray[Byte],
final_? : Bool = false,
) -> Unit raise FzipError {
self.chunks.push(chunk)
if final_ {
let data = concat_chunks(self.chunks)
let result = decompress_sync(data, opts=self.opts)
match self.ondata {
Some(h) => call_handler(h, result, true)
None => ()
}
self.chunks = []
}
}