use std::cmp;
use std::marker::PhantomData;
use std::ops::Deref;
use crate::buffers::BufFactory;
use crate::buffers::DefaultBufFactory;
#[derive(Clone, Debug, Default)]
pub struct RangeBuf<F = DefaultBufFactory>
where
F: BufFactory,
{
pub(crate) data: F::Buf,
pub(crate) start: usize,
pub(crate) pos: usize,
pub(crate) len: usize,
pub(crate) off: u64,
pub(crate) fin: bool,
_bf: PhantomData<F>,
}
impl<F: BufFactory> RangeBuf<F>
where
F::Buf: Clone,
{
pub fn from(buf: &[u8], off: u64, fin: bool) -> RangeBuf<F> {
Self::from_raw(F::buf_from_slice(buf), off, fin)
}
pub fn from_raw(data: F::Buf, off: u64, fin: bool) -> RangeBuf<F> {
RangeBuf {
len: data.as_ref().len(),
data,
start: 0,
pos: 0,
off,
fin,
_bf: Default::default(),
}
}
pub fn fin(&self) -> bool {
self.fin
}
pub fn off(&self) -> u64 {
(self.off - self.start as u64) + self.pos as u64
}
pub fn max_off(&self) -> u64 {
self.off() + self.len() as u64
}
pub fn len(&self) -> usize {
self.len - (self.pos - self.start)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn consume(&mut self, count: usize) {
self.pos += count;
}
pub fn split_off(&mut self, at: usize) -> RangeBuf<F>
where
F::Buf: Clone + AsRef<[u8]>,
{
assert!(
at <= self.len,
"`at` split index (is {}) should be <= len (is {})",
at,
self.len
);
let buf = RangeBuf {
data: self.data.clone(),
start: self.start + at,
pos: cmp::max(self.pos, self.start + at),
len: self.len - at,
off: self.off + at as u64,
_bf: Default::default(),
fin: self.fin,
};
self.pos = cmp::min(self.pos, self.start + at);
self.len = at;
self.fin = false;
buf
}
}
impl<F: BufFactory> Deref for RangeBuf<F> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.data.as_ref()[self.pos..self.start + self.len]
}
}
impl<F: BufFactory> Ord for RangeBuf<F> {
fn cmp(&self, other: &RangeBuf<F>) -> cmp::Ordering {
self.off.cmp(&other.off).reverse()
}
}
impl<F: BufFactory> PartialOrd for RangeBuf<F> {
fn partial_cmp(&self, other: &RangeBuf<F>) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<F: BufFactory> Eq for RangeBuf<F> {}
impl<F: BufFactory> PartialEq for RangeBuf<F> {
fn eq(&self, other: &RangeBuf<F>) -> bool {
self.off == other.off
}
}