///|
/// A queue of immutable input chunks. Bytes are copied only by `copy_exact`.
pub struct ChunkBuffer {
mut chunks : Array[Bytes]
mut first_chunk : Int
mut first_offset : Int
mut available_bytes : Int
mut copied_bytes_value : Int
} derive(Debug)
///|
pub fn ChunkBuffer::new() -> ChunkBuffer {
{
chunks: [],
first_chunk: 0,
first_offset: 0,
available_bytes: 0,
copied_bytes_value: 0,
}
}
///|
pub fn ChunkBuffer::append(self : ChunkBuffer, chunk : Bytes) -> Unit {
if chunk.length() != 0 {
self.chunks.push(chunk)
self.available_bytes = self.available_bytes + chunk.length()
}
}
///|
pub fn ChunkBuffer::available(self : ChunkBuffer) -> Int {
self.available_bytes
}
///|
pub fn ChunkBuffer::chunk_count(self : ChunkBuffer) -> Int {
self.chunks.length() - self.first_chunk
}
///|
pub fn ChunkBuffer::copied_bytes(self : ChunkBuffer) -> Int {
self.copied_bytes_value
}
///|
pub fn ChunkBuffer::peek_byte(self : ChunkBuffer, offset : Int) -> Byte? {
if offset < 0 || offset >= self.available_bytes {
return None
}
let mut remaining = offset
let mut index = self.first_chunk
let mut position = self.first_offset
while index < self.chunks.length() {
let chunk = self.chunks[index]
let usable = chunk.length() - position
if remaining < usable {
return Some(chunk[position + remaining])
}
remaining = remaining - usable
index = index + 1
position = 0
}
None
}
///|
pub fn ChunkBuffer::copy_exact(self : ChunkBuffer, length : Int) -> Bytes? {
if length < 0 || length > self.available_bytes {
return None
}
let output = @buffer.Buffer(size_hint=length)
for i = 0; i < length; i = i + 1 {
match self.peek_byte(i) {
Some(byte) => output.write_byte(byte)
None => return None
}
}
self.copied_bytes_value = self.copied_bytes_value + length
Some(output.to_bytes())
}
///|
pub fn ChunkBuffer::discard(self : ChunkBuffer, length : Int) -> Bool {
if length < 0 || length > self.available_bytes {
return false
}
let mut left = length
while left > 0 {
let chunk = self.chunks[self.first_chunk]
let usable = chunk.length() - self.first_offset
if left < usable {
self.first_offset = self.first_offset + left
left = 0
} else {
left = left - usable
self.first_chunk = self.first_chunk + 1
self.first_offset = 0
}
}
self.available_bytes = self.available_bytes - length
if self.available_bytes == 0 {
self.clear()
}
true
}
///|
pub fn ChunkBuffer::clear(self : ChunkBuffer) -> Unit {
self.chunks = []
self.first_chunk = 0
self.first_offset = 0
self.available_bytes = 0
self.copied_bytes_value = 0
}