use std::iter::{DoubleEndedIterator, ExactSizeIterator, IntoIterator, Iterator};
use super::RingBuffer;
pub struct RingBufIter<'a, T> {
front_idx: isize,
back_idx: isize,
buf: &'a RingBuffer<T>,
}
impl<'a, T> RingBufIter<'a, T> {
pub fn new(buf: &'a RingBuffer<T>) -> Self {
RingBufIter {
buf,
front_idx: 0,
back_idx: buf.len as isize - 1,
}
}
}
impl<'a, T> Iterator for RingBufIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.front_idx > self.back_idx {
None
} else {
let elem = &self.buf[self.front_idx as usize];
self.front_idx += 1;
Some(elem)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'a, T> ExactSizeIterator for RingBufIter<'a, T> {
fn len(&self) -> usize {
((self.back_idx + 1) - self.front_idx).max(0) as usize
}
}
impl<'a, T> DoubleEndedIterator for RingBufIter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.back_idx < self.front_idx {
None
} else {
let elem = &self.buf[self.back_idx as usize];
self.back_idx -= 1;
Some(elem)
}
}
}
pub struct RingBufIntoIter<T> {
pub buf: RingBuffer<T>,
}
impl<T> Iterator for RingBufIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.buf.pop()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<T> ExactSizeIterator for RingBufIntoIter<T> {
fn len(&self) -> usize {
self.buf.len
}
}
impl<T> DoubleEndedIterator for RingBufIntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.buf.pop_oldest()
}
}
impl<'a, T> IntoIterator for &'a RingBuffer<T> {
type Item = &'a T;
type IntoIter = RingBufIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T> IntoIterator for RingBuffer<T> {
type Item = T;
type IntoIter = RingBufIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
RingBufIntoIter { buf: self }
}
}