ringvec 0.1.0

A simple ring buffer implementation based on a vector
Documentation
#[derive(Debug)]
pub struct RingVec<T> {
    capacity: usize,
    container: Vec<T>,
    start: usize,
    end: usize,
    len: usize,
}

impl<T> RingVec<T>
where
    T: Default,
{
    pub fn new(capacity: usize) -> Self {
        let mut container = Vec::with_capacity(capacity);

        for _ in 0..capacity {
            container.push(T::default());
        }

        Self {
            capacity,
            container,
            start: 0,
            end: 0,
            len: 0,
        }
    }

    pub fn capacity(&self) -> usize {
        self.capacity
    }
    pub fn len(&self) -> usize {
        self.len
    }

    #[inline(always)]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline(always)]
    pub fn is_full(&self) -> bool {
        self.len == self.capacity
    }

    #[inline(always)]
    fn inc_start(&mut self) {
        self.start += 1;
        self.start %= self.capacity;
    }

    #[inline(always)]
    fn inc_end(&mut self) {
        self.end += 1;
        self.end %= self.capacity;
    }

    pub fn push(&mut self, element: T) {
        if self.is_full() {
            return;
        }

        let cell = self.container.get_mut(self.start).unwrap();

        *cell = element;

        self.len += 1;
        self.inc_start();
    }

    pub fn push_force(&mut self, element: T) {
        let cell = self.container.get_mut(self.start).unwrap();

        *cell = element;

        if self.is_full() {
            self.inc_end();
        } else {
            self.len += 1;
        }

        self.inc_start();
    }

    pub fn pop(&mut self) -> Option<T> {
        if !self.is_empty() {
            let cell = self.container.get_mut(self.end).unwrap();

            let result = std::mem::take(cell);

            self.len -= 1;
            self.inc_end();

            Some(result)
        } else {
            None
        }
    }

    pub fn peek_oldest(&self) -> Option<&T> {
        if !self.is_empty() {
            self.container.get(self.end)
        } else {
            None
        }
    }

    pub fn peek_newest(&self) -> Option<&T> {
        if !self.is_empty() {
            let index = (self.start + self.capacity - 1) % self.capacity;
            self.container.get(index)
        } else {
            None
        }
    }

    pub fn iter(&self) -> RingVecIterator<T> {
        RingVecIterator {
            ringvec: &self,
            current: self.end,
            length: self.len,
        }
    }
}

pub struct RingVecIterator<'ring, T> {
    ringvec: &'ring RingVec<T>,
    current: usize,
    length: usize,
}

impl<'ring, T> Iterator for RingVecIterator<'ring, T> {
    type Item = &'ring T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.length == 0 {
            None
        } else {
            let result = self.ringvec.container.get(self.current);

            self.length -= 1;
            self.current += 1;
            self.current %= self.ringvec.capacity;

            result
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.length, Some(self.length))
    }
}

impl<'ring, T> ExactSizeIterator for RingVecIterator<'ring, T> {}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn ringvec() {
        let mut v = RingVec::new(3);

        assert!(v.is_empty());
        assert!(!v.is_full());

        v.push(1);
        v.push(2);
        v.push(3);
        v.push_force(4);
        v.push_force(5);

        assert!(!v.is_empty());
        assert!(v.is_full());

        assert_eq!(v.peek_oldest(), Some(&3));
        assert_eq!(v.peek_newest(), Some(&5));
        assert_eq!(v.pop(), Some(3));

        assert!(!v.is_empty());
        assert!(!v.is_full());

        assert_eq!(v.pop(), Some(4));
        assert_eq!(v.pop(), Some(5));

        assert!(v.is_empty());
        assert!(!v.is_full());
    }

    #[test]
    fn ringvec2() {
        let mut v = RingVec::new(3);

        assert!(v.is_empty());
        assert!(!v.is_full());

        v.push_force(4);
        v.push_force(5);
        v.push_force(6);
        v.push_force(7);

        assert!(!v.is_empty());
        assert!(v.is_full());

        assert_eq!(v.peek_oldest(), Some(&5));
        assert_eq!(v.peek_newest(), Some(&7));
        assert_eq!(v.pop(), Some(5));

        assert!(!v.is_empty());
        assert!(!v.is_full());

        assert_eq!(v.pop(), Some(6));
        assert_eq!(v.pop(), Some(7));

        assert!(v.is_empty());
        assert!(!v.is_full());
    }

    #[test]
    fn ringvec3() {
        let mut v = RingVec::new(3);
        v.push_force(4);
        v.push_force(5);
        v.push_force(6);
        v.push_force(7);
        v.push_force(8);
        v.push_force(9);

        v.peek_newest();
    }

    #[test]
    fn iter() {
        let mut v = RingVec::new(3);

        assert!(v.is_empty());
        assert!(!v.is_full());

        v.push(1);
        v.push(2);
        v.push(3);

        dbg!(&v);

        let mut i = v.iter();

        assert_eq!(i.next(), Some(&1));
        assert_eq!(i.next(), Some(&2));
        assert_eq!(i.next(), Some(&3));
        assert_eq!(i.next(), None);
        assert_eq!(i.next(), None);
    }
}