///|
/// Stateful decoder accepting arbitrarily fragmented byte chunks.
pub struct Decoder {
buffer : Array[Byte]
max_frame_size : Int
max_buffer_size : Int
header_value : Array[Int]
header_shift : Array[Int]
header_bytes : Array[Int]
frame_header_bytes : Array[Int]
expected_length : Array[Int]
}
///|
pub fn Decoder::new(
max_frame_size? : Int = 1048576,
max_buffer_size? : Int = max_frame_size + 5,
) -> Decoder {
Decoder::{
buffer: [],
max_frame_size,
max_buffer_size,
header_value: [0],
header_shift: [0],
header_bytes: [0],
frame_header_bytes: [0],
expected_length: [-1],
}
}
///|
/// Number of bytes retained while waiting for a complete frame.
pub fn Decoder::buffered(self : Decoder) -> Int {
self.header_bytes[0] + self.frame_header_bytes[0] + self.buffer.length()
}
///|
/// Discard partial data so a caller can recover at a known boundary.
pub fn Decoder::reset(self : Decoder) -> Unit {
self.buffer.clear()
self.header_value[0] = 0
self.header_shift[0] = 0
self.header_bytes[0] = 0
self.frame_header_bytes[0] = 0
self.expected_length[0] = -1
}
///|
/// Feed any chunk size and return every complete frame now available.
pub fn Decoder::feed(
self : Decoder,
chunk : Bytes,
) -> Result[Array[Bytes], FrameError] {
let frames : Array[Bytes] = []
for byte in chunk {
if self.expected_length[0] < 0 {
let part = byte.to_int()
let byte_index = self.header_bytes[0]
if byte_index == 4 && ((part & 0x80) != 0 || (part & 0x78) != 0) {
return Err(MalformedVarint)
}
self.header_value[0] = self.header_value[0] |
((part & 0x7f) << self.header_shift[0])
self.header_bytes[0] = byte_index + 1
if (part & 0x80) == 0 {
let length = self.header_value[0]
if length > self.max_frame_size {
return Err(FrameTooLarge(length, self.max_frame_size))
}
self.expected_length[0] = length
self.frame_header_bytes[0] = self.header_bytes[0]
self.header_value[0] = 0
self.header_shift[0] = 0
self.header_bytes[0] = 0
if length == 0 {
frames.push(b"")
self.expected_length[0] = -1
self.frame_header_bytes[0] = 0
}
} else {
self.header_shift[0] = self.header_shift[0] + 7
}
} else {
self.buffer.push(byte)
if self.buffer.length() == self.expected_length[0] {
frames.push(Bytes::from_array(self.buffer))
self.buffer.clear()
self.expected_length[0] = -1
self.frame_header_bytes[0] = 0
}
}
let retained = self.buffered()
if retained > self.max_buffer_size {
let actual = retained
self.reset()
return Err(BufferLimitExceeded(actual, self.max_buffer_size))
}
}
Ok(frames)
}
///|
/// Signal end-of-input. A partial header or payload is an explicit error.
pub fn Decoder::finish(self : Decoder) -> Result[Unit, FrameError] {
if self.buffered() == 0 && self.expected_length[0] < 0 {
Ok(())
} else {
Err(NeedMore)
}
}