diterator 0.1.4

A library for range-based iteration in Rust.
Documentation
//! Diterator
//!
//! 任意の範囲の値を無限にイテレートするためのライブラリ。
//! イテレートは、 for で行うことは想定せず、 next() メソッドを呼び出すことで行う。

#![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)
    }
}

/// データイテレーター
///
/// T: usize インデックスでアクセスできるデータ
/// (ただし、内部のデータが不変であることを前提としている)
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,
{
    /// 新しいデータイテレーターの作成
    ///
    /// # Arguments
    ///
    /// * `data` - データ
    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));
    }
}