use std::ptr::NonNull;
use crate::block::{drop_node, BlockNode, BLOCK_CAP};
pub struct Buffer {
pub(crate) head: Option<NonNull<BlockNode>>,
pub(crate) read_offset: usize,
pub(crate) len: usize,
}
impl Clone for Buffer {
fn clone(&self) -> Self {
let mut node = self.head;
while let Some(mut n) = node {
unsafe { n.as_mut().block.as_mut() }.ref_count += 1;
node = unsafe { n.as_ref() }.next;
}
Self {
head: self.head,
read_offset: self.read_offset,
len: self.len,
}
}
}
impl Buffer {
#[inline]
pub fn len(&self) -> usize {
self.len
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn advance(&mut self, cnt: usize) {
assert!(
cnt <= self.len(),
"cannot advance past `remaining`: {:?} <= {:?}",
cnt,
self.len(),
);
self.len -= cnt;
let mut offset = self.read_offset + cnt;
while offset > BLOCK_CAP {
offset -= BLOCK_CAP;
let mut to_drop = self.head.unwrap();
self.head = unsafe { to_drop.as_mut() }.next;
unsafe { drop_node(to_drop) };
}
if offset == BLOCK_CAP && self.head.is_some() {
if let Some(next) = unsafe { self.head.unwrap_unchecked().as_mut() }.next {
self.head = Some(next);
self.read_offset = 0;
}
}
self.read_offset = offset;
}
}