use std::ops::{Add, AddAssign, Index, IndexMut, Range, Sub, SubAssign};
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy, Default)]
pub struct Pointer(usize);
impl Pointer {
pub fn abs(&self) -> usize {
self.0
}
}
impl Add<usize> for Pointer {
type Output = Pointer;
fn add(self, rhs: usize) -> Self::Output {
Self(self.0 + rhs)
}
}
impl AddAssign<usize> for Pointer {
fn add_assign(&mut self, rhs: usize) {
self.0 += rhs
}
}
impl Sub<usize> for Pointer {
type Output = Pointer;
fn sub(self, rhs: usize) -> Self::Output {
Self(self.0 - rhs)
}
}
impl SubAssign<usize> for Pointer {
fn sub_assign(&mut self, rhs: usize) {
self.0 -= rhs
}
}
impl Sub<Pointer> for Pointer {
type Output = usize;
fn sub(self, rhs: Pointer) -> Self::Output {
self.0 - rhs.0
}
}
pub struct ShiftBuffer<T> {
buf: Vec<T>,
offset: Pointer,
lower: Pointer,
upper: Pointer,
}
impl<T: Default + Copy> ShiftBuffer<T> {
pub fn new(init_size: usize) -> Self {
let buf = (0..init_size).map(|_| T::default()).collect();
Self {
buf,
offset: Pointer::default(),
lower: Pointer::default(),
upper: Pointer::default(),
}
}
pub fn shrink(&mut self, n: usize) -> Pointer {
assert!(self.lower + n < self.upper);
self.lower += n;
self.lower
}
pub fn extend(&mut self, n: usize) -> Pointer {
assert!(self.relative_pos(self.upper) + n <= self.buf.len());
self.upper += n;
self.upper
}
pub fn make_room(&mut self) -> &mut [T] {
if self.relative_pos(self.upper) == self.buf.len() {
if self.lower == self.offset {
self.buf.extend((0..self.buf.len()).map(|_| T::default()))
} else {
self.shift();
}
}
self.free()
}
pub fn shift(&mut self) {
let d = self.upper.abs() - self.lower.abs();
for p in 0..d {
self.buf[p] = self.buf[p + d]
}
self.offset = self.lower;
}
pub fn free(&mut self) -> &mut [T] {
let r = self.relative_pos(self.upper);
&mut self.buf[r..]
}
pub fn lower(&self) -> Pointer {
self.lower
}
pub fn upper(&self) -> Pointer {
self.upper
}
pub fn relative_pos(&self, p: Pointer) -> usize {
debug_assert!(self.lower <= p && p <= self.upper);
p - self.offset
}
pub fn clone_window(&self) -> ShiftBuffer<T> {
let (l, u) = (self.lower, self.upper);
ShiftBuffer {
buf: self[l..u].to_vec(),
offset: l,
lower: l,
upper: u,
}
}
}
impl<T: Default + Copy> Index<Pointer> for ShiftBuffer<T> {
type Output = T;
fn index(&self, index: Pointer) -> &Self::Output {
debug_assert!(self.lower <= index && index <= self.upper);
&self.buf[self.relative_pos(index)]
}
}
impl<T: Default + Copy> IndexMut<Pointer> for ShiftBuffer<T> {
fn index_mut(&mut self, index: Pointer) -> &mut Self::Output {
debug_assert!(self.lower <= index && index <= self.upper);
let r = self.relative_pos(index);
&mut self.buf[r]
}
}
impl<T: Default + Copy> Index<Range<Pointer>> for ShiftBuffer<T> {
type Output = [T];
fn index(&self, r: Range<Pointer>) -> &Self::Output {
debug_assert!(r.start <= r.end);
debug_assert!(self.lower <= r.start && r.start <= self.upper);
debug_assert!(self.lower <= r.end && r.end <= self.upper);
&self.buf[self.relative_pos(r.start)..self.relative_pos(r.end)]
}
}
#[cfg(test)]
mod tests {
use super::ShiftBuffer;
#[test]
fn store_simple_string() {
let input_string = "ABC";
let mut sbuf = ShiftBuffer::<u8>::new(1 << 10);
let (lower, upper) = (sbuf.lower(), sbuf.extend(3));
let mut cursor = lower;
for b in input_string.as_bytes() {
sbuf[cursor] = *b;
cursor += 1;
}
assert_eq!(&sbuf[lower..upper], input_string.as_bytes());
}
}