#![warn(
missing_docs,
rustdoc::missing_crate_level_docs,
unused_results,
clippy::complexity,
clippy::perf,
clippy::style
)]
#![deny(clippy::correctness, clippy::suspicious)]
pub mod sync;
use std::{
cell::RefCell,
ops::{Index, Range},
rc::Rc,
};
#[derive(Debug)]
pub struct IndexHandler {
index: usize,
now: Option<Range<usize>>,
next: Option<Range<usize>>,
}
impl IndexHandler {
fn new(now: Option<Range<usize>>, next: Option<Range<usize>>) -> Self {
let mut index = 0;
if let Some(range) = &now {
index = range.start;
}
Self { index, now, next }
}
pub fn set_range(&mut self, range: Range<usize>) {
self.index = range.start;
self.now = Some(range);
}
pub fn clear_range(&mut self) {
self.now = None;
}
pub fn set_next_range(&mut self, range: Range<usize>) {
self.next = Some(range);
}
pub fn clear_next_range(&mut self) {
self.next = None;
}
fn next_index(&mut self) -> Option<usize> {
if self.now.is_none() && self.next.is_some() {
self.now = self.next.take();
self.next = None;
if let Some(range) = &self.now {
self.index = range.start;
}
}
if let Some(range) = &self.now {
if range.contains(&self.index) {
let result = Some(self.index);
self.index += 1;
return result;
} else {
self.clear_range();
self.now = self.next.take();
if let Some(range) = &self.now {
self.index = range.start;
}
}
}
None
}
pub fn is_contained(&self, range: &Range<usize>) -> bool {
range.contains(&self.index)
}
}
pub struct Diterator<T: Index<usize>>
where
T::Output: Clone + Default,
{
data: T,
handler: Rc<RefCell<IndexHandler>>,
}
impl<T: Index<usize>> Diterator<T>
where
T::Output: Clone + Default,
{
pub fn new(data: T) -> (Self, Rc<RefCell<IndexHandler>>) {
let handler = Rc::new(RefCell::new(IndexHandler::new(None, None)));
let handler_ = handler.clone();
(Self { data, handler }, handler_)
}
}
impl<T: Index<usize>> Iterator for Diterator<T>
where
T::Output: Clone + Default,
{
type Item = T::Output;
fn next(&mut self) -> Option<Self::Item> {
if let Some(index) = self.handler.borrow_mut().next_index() {
return Some(self.data[index].clone());
}
Some(T::Output::default())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_diterator() {
let data = vec![1, 2, 3, 4, 5];
let (mut diter, handler) = Diterator::new(data);
handler.borrow_mut().set_range(1..4);
assert_eq!(diter.next(), Some(2));
assert_eq!(diter.next(), Some(3));
assert_eq!(diter.next(), Some(4));
assert_eq!(diter.next(), Some(0));
assert_eq!(diter.next(), Some(0));
handler.borrow_mut().set_range(0..5);
assert_eq!(diter.next(), Some(1));
assert_eq!(diter.next(), Some(2));
assert_eq!(diter.next(), Some(3));
assert_eq!(diter.next(), Some(4));
assert_eq!(diter.next(), Some(5));
assert_eq!(diter.next(), Some(0));
assert_eq!(diter.next(), Some(0));
}
#[test]
fn test_diterator_map() {
let data = vec![1, 2, 3, 4, 5];
let (diter, handler) = Diterator::new(data);
let mut iter = diter.map(|x| x * 2);
handler.borrow_mut().set_range(1..4);
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(6));
handler.borrow_mut().set_range(0..5);
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(4));
handler.borrow_mut().clear_range();
handler.borrow_mut().set_next_range(1..4);
assert_eq!(iter.next(), Some(4));
}
}