A streaming Zstandard (RFC 8878) decoder in pure MoonBit: arbitrary input chunks, bounded output slices, memory bounded by the window.
moon add gaato/zstd///|
test "decompress a whole stream" {
let compressed = b"\x28\xb5\x2f\xfd\x20\x05\x29\x00\x00\x68\x65\x6c\x6c\x6f" // zstd.compress(b"hello")
let text = @zstd.decompress(compressed, max_output=16 * 1024 * 1024)
assert_eq(text, b"hello")
}///|
fn decode_all(chunks : Array[Bytes], sink : (BytesView) -> Unit) -> Unit raise {
let decoder = @zstd.Decoder(max_window_bits=23) // 8 MiB, as RFC 9659 asks of HTTP
let out = FixedArray::make(64 * 1024, b'\x00')
for i, chunk in chunks {
let mut input = chunk[:]
for ;; {
let status = decoder.step_into(input, out, end=i == chunks.length() - 1)
input = input[decoder.last_consumed():]
sink(Bytes::from_array(out[:decoder.last_produced()]))
match status {
Done => return
NeedMoreInput => break
NeedMoreOutput => ()
}
}
}
}
///|
test "decode a stream chunk by chunk" {
let decoded = Buffer()
decode_all(
[b"\x28\xb5\x2f", b"\xfd\x20\x05\x29\x00\x00\x68", b"\x65\x6c\x6c\x6f"],
bytes => decoded.write_bytes(bytes.to_owned()),
)
assert_eq(decoded.to_bytes(), b"hello")
}moon add gaato/zstd///|
test "decompress a whole stream" {
let compressed = b"\x28\xb5\x2f\xfd\x20\x05\x29\x00\x00\x68\x65\x6c\x6c\x6f" // zstd.compress(b"hello")
let text = @zstd.decompress(compressed, max_output=16 * 1024 * 1024)
assert_eq(text, b"hello")
}///|
fn decode_all(chunks : Array[Bytes], sink : (BytesView) -> Unit) -> Unit raise {
let decoder = @zstd.Decoder(max_window_bits=23) // 8 MiB, as RFC 9659 asks of HTTP
let out = FixedArray::make(64 * 1024, b'\x00')
for i, chunk in chunks {
let mut input = chunk[:]
for ;; {
let status = decoder.step_into(input, out, end=i == chunks.length() - 1)
input = input[decoder.last_consumed():]
sink(Bytes::from_array(out[:decoder.last_produced()]))
match status {
Done => return
NeedMoreInput => break
NeedMoreOutput => ()
}
}
}
}
///|
test "decode a stream chunk by chunk" {
let decoded = Buffer()
decode_all(
[b"\x28\xb5\x2f", b"\xfd\x20\x05\x29\x00\x00\x68", b"\x65\x6c\x6c\x6f"],
bytes => decoded.write_bytes(bytes.to_owned()),
)
assert_eq(decoded.to_bytes(), b"hello")
}pub struct Decoder {
// private fields
}fn Decoder::step(self : Decoder, input : BytesView, output : MutArrayView[Byte], end? : Bool) -> Status raise ZstdErrorfn decompress(input : BytesView, max_output? : Int, max_window_bits? : Int) -> Bytes raise ZstdErrorInstall
Download zipA streaming Zstandard (RFC 8878) decoder in pure MoonBit: arbitrary input chunks, bounded output slices, memory bounded by the window.