bufferring 0.0.2

Ring buffers for Rust
Documentation
//! Ringbuffer iteration.

use core::iter::FusedIterator;

use crate::RingBuffer;

/// The iterator resulting from [`RingBuffer::iter()`].
#[derive(Clone, Debug)]
pub struct Iter<'a, RBuf: RingBuffer + ?Sized> {
    buf: &'a RBuf,
    beg: usize,
    end: usize,
}

impl<'a, RBuf: RingBuffer + ?Sized> Iter<'a, RBuf> {
    /// Construct a new [`Iter`].
    pub(crate) fn new(buf: &'a RBuf) -> Self {
        Self { buf, beg: 0, end: buf.len() }
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> Iterator for Iter<'a, RBuf> {
    type Item = &'a RBuf::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: We know that 'beg' is a valid position.
            let item = unsafe { self.buf.get(self.beg).unwrap_unchecked() };

            self.beg += 1;
            Some(item)
        } else { None }
    }

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

    fn count(self) -> usize {
        self.end - self.beg
    }

    fn last(self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: We know that 'end - 1' is a valid position.
            Some(unsafe { self.buf.get(self.end - 1).unwrap_unchecked() })
        } else { None }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if self.beg + n < self.end {
            // SAFETY: We know that 'beg + n' is a valid position.
            let item = unsafe { self.buf.get(self.beg+n).unwrap_unchecked() };

            self.beg += n + 1;
            Some(item)
        } else {
            self.beg = self.end;
            None
        }
    }

    fn for_each<F: FnMut(Self::Item)>(self, mut f: F) {
        for i in self.beg .. self.end {
            // SAFETY: We know that 'i' is a valid position.
            (f)(unsafe { self.buf.get(i).unwrap_unchecked() });
        }
    }

    fn fold<B, F>(self, mut state: B, mut f: F) -> B
    where F: FnMut(B, Self::Item) -> B {
        for i in self.beg .. self.end {
            // SAFETY: We know that 'i' is a valid position.
            state = (f)(state, unsafe { self.buf.get(i).unwrap_unchecked() });
        }
        state
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> ExactSizeIterator for Iter<'a, RBuf> {
    fn len(&self) -> usize {
        self.end - self.beg
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> FusedIterator for Iter<'a, RBuf> {}

impl<'a, RBuf: RingBuffer + ?Sized> DoubleEndedIterator for Iter<'a, RBuf> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: We know that 'end - 1' is a valid position.
            let item = unsafe { self.buf.get(self.end-1).unwrap_unchecked() };

            self.end -= 1;
            Some(item)
        } else { None }
    }

    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
        if self.beg + n < self.end {
            // SAFETY: We know that 'end - n - 1' is a valid position.
            let item = unsafe { self.buf.get(self.end-n-1).unwrap_unchecked() };

            self.end -= n - 1;
            Some(item)
        } else {
            self.beg = self.end;
            None
        }
    }

    fn rfold<B, F>(self, mut state: B, mut f: F) -> B
    where F: FnMut(B, Self::Item) -> B {
        for i in (self.beg .. self.end).rev() {
            // SAFETY: We know that 'i' is a valid position.
            state = (f)(state, unsafe { self.buf.get(i).unwrap_unchecked() });
        }
        state
    }
}

/// The iterator resulting from [`RingBuffer::iter_mut()`].
#[derive(Debug)]
pub struct IterMut<'a, RBuf: RingBuffer + ?Sized> {
    buf: &'a RBuf,
    beg: usize,
    end: usize,
}

impl<'a, RBuf: RingBuffer + ?Sized> IterMut<'a, RBuf> {
    /// Construct a new [`IterMut`].
    pub(crate) fn new(buf: &'a mut RBuf) -> Self {
        Self { buf, beg: 0, end: buf.len() }
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> Iterator for IterMut<'a, RBuf> {
    type Item = &'a mut RBuf::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: `off` refers to the next item with every iteration, and
            // items are only held for the lifetime that the buffer is held by
            // the iterator; during this time, the buffer is not changed or used
            // in any other way.
            let item = unsafe { self.buf.get_disjoint_mut(self.beg) };
            self.beg += 1;
            Some(item)
        } else { None }
    }

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

    fn count(self) -> usize {
        self.end - self.beg
    }

    fn last(self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: We know that 'end - 1' is a valid position that we have
            // not used yet.
            Some(unsafe { self.buf.get_disjoint_mut(self.end - 1) })
        } else { None }
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        if self.beg + n < self.end {
            // SAFETY: We know that 'beg + n' is a valid position that we have
            // not used yet.
            let item = unsafe { self.buf.get_disjoint_mut(self.beg+n) };

            self.beg += n + 1;
            Some(item)
        } else {
            self.beg = self.end;
            None
        }
    }

    fn for_each<F: FnMut(Self::Item)>(self, mut f: F) {
        for i in self.beg .. self.end {
            // SAFETY: We know that 'i' is a valid position that we have not
            // used yet.
            (f)(unsafe { self.buf.get_disjoint_mut(i) });
        }
    }

    fn fold<B, F>(self, mut state: B, mut f: F) -> B
    where F: FnMut(B, Self::Item) -> B {
        for i in self.beg .. self.end {
            // SAFETY: We know that 'i' is a valid position that we have not
            // used yet.
            state = (f)(state, unsafe { self.buf.get_disjoint_mut(i) });
        }
        state
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> ExactSizeIterator for IterMut<'a, RBuf> {
    fn len(&self) -> usize {
        self.end - self.beg
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> FusedIterator for IterMut<'a, RBuf> {}

impl<'a, RBuf: RingBuffer + ?Sized> DoubleEndedIterator for IterMut<'a, RBuf> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.beg < self.end {
            // SAFETY: We know that 'end - 1' is a valid position that we have
            // not used yet.
            let item = unsafe { self.buf.get_disjoint_mut(self.end-1) };

            self.end -= 1;
            Some(item)
        } else { None }
    }

    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
        if self.beg + n < self.end {
            // SAFETY: We know that 'end - n - 1' is a valid position.
            let item = unsafe { self.buf.get_disjoint_mut(self.end-n-1) };

            self.end -= n - 1;
            Some(item)
        } else {
            self.beg = self.end;
            None
        }
    }

    fn rfold<B, F>(self, mut state: B, mut f: F) -> B
    where F: FnMut(B, Self::Item) -> B {
        for i in (self.beg .. self.end).rev() {
            // SAFETY: We know that 'i' is a valid position.
            state = (f)(state, unsafe { self.buf.get_disjoint_mut(i) });
        }
        state
    }
}

/// The iterator resulting from [`RingBuffer::drain()`].
#[derive(Debug)]
pub struct Drain<'a, RBuf: RingBuffer + ?Sized> {
    buf: &'a mut RBuf,
}

impl<'a, RBuf: RingBuffer + ?Sized> Drain<'a, RBuf> {
    /// Construct a new [`Drain`].
    pub(crate) fn new(buf: &'a mut RBuf) -> Self {
        Self { buf }
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> Iterator for Drain<'a, RBuf> {
    type Item = RBuf::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.buf.dequeue()
    }

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

    fn count(self) -> usize {
        self.buf.clear();
        self.buf.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.nth(self.buf.len() - 1)
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.buf.skip(n);
        self.buf.dequeue()
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> ExactSizeIterator for Drain<'a, RBuf> {
    fn len(&self) -> usize {
        self.buf.len()
    }
}

impl<'a, RBuf: RingBuffer + ?Sized> FusedIterator for Drain<'a, RBuf> {}