use std::{collections::VecDeque, io};
#[derive(Debug)]
pub(crate) struct Chunks {
seq: VecDeque<Chunk>,
len: usize,
}
impl Chunks {
pub(crate) fn new() -> Self {
Chunks {
seq: VecDeque::new(),
len: 0,
}
}
pub(crate) fn len(&self) -> usize {
self.len - self.seq.front().map(|c| c.offset()).unwrap_or(0)
}
pub(crate) fn push(&mut self, x: Vec<u8>) {
self.len += x.len();
if !x.is_empty() {
self.seq.push_back(Chunk {
cursor: io::Cursor::new(x),
})
}
}
pub(crate) fn pop(&mut self) -> Option<Chunk> {
let chunk = self.seq.pop_front();
self.len -= chunk.as_ref().map(|c| c.len() + c.offset()).unwrap_or(0);
chunk
}
pub(crate) fn front_mut(&mut self) -> Option<&mut Chunk> {
self.seq.front_mut()
}
}
#[derive(Debug)]
pub(crate) struct Chunk {
cursor: io::Cursor<Vec<u8>>,
}
impl Chunk {
pub(crate) fn is_empty(&self) -> bool {
self.len() == 0
}
pub(crate) fn len(&self) -> usize {
self.cursor.get_ref().len() - self.offset()
}
pub(crate) fn offset(&self) -> usize {
self.cursor.position() as usize
}
pub(crate) fn advance(&mut self, amount: usize) {
assert!({
let pos = self.offset().checked_add(amount);
let max = self.cursor.get_ref().len();
pos.is_some() && pos <= Some(max)
});
self.cursor
.set_position(self.cursor.position() + amount as u64);
}
pub(crate) fn into_vec(self) -> Vec<u8> {
self.cursor.into_inner()
}
}
impl AsRef<[u8]> for Chunk {
fn as_ref(&self) -> &[u8] {
&self.cursor.get_ref()[self.offset()..]
}
}