garnish_lang_simple_data 0.0.24-alpha

Data implementation for garnish runtimes using simple list of variants
Documentation
use crate::data::number::SimpleNumber;
use garnish_lang_traits::GarnishNumber;

/// Custom size iterator for [`garnish_lang_traits::GarnishData`] implementation.
pub struct SizeIterator {
    min: usize,
    max: usize,
    current_front: usize,
    current_back: usize,
}

impl SizeIterator {
    pub fn new(min: usize, max: usize) -> Self {
        Self {
            min,
            max,
            current_front: min,
            current_back: max,
        }
    }

    pub fn reset(&mut self) {
        self.current_front = self.min;
        self.current_back = self.max;
    }
}

impl Iterator for SizeIterator {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current_front >= self.current_back {
            return None;
        }

        self.current_front += 1;
        return Some(self.current_front - 1);
    }
}

impl DoubleEndedIterator for SizeIterator {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current_back == 0 || self.current_back <= self.current_front {
            return None;
        }

        self.current_back -= 1;
        return Some(self.current_back);
    }
}

/// Custom size iterator for [`garnish_lang_traits::GarnishData`] implementation.
pub struct NumberIterator {
    min: SimpleNumber,
    max: SimpleNumber,
    current_front: SimpleNumber,
    current_back: SimpleNumber,
}

impl NumberIterator {
    pub fn new(min: SimpleNumber, max: SimpleNumber) -> Self {
        Self {
            min,
            max,
            current_front: min,
            current_back: max,
        }
    }

    pub fn reset(&mut self) {
        self.current_front = self.min;
        self.current_back = self.max;
    }
}

impl Iterator for NumberIterator {
    type Item = SimpleNumber;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current_front >= self.current_back {
            return None;
        }

        self.current_front = self.current_front.plus(SimpleNumber::Integer(1)).unwrap_or(self.max);
        return Some(self.current_front.subtract(SimpleNumber::Integer(1)).unwrap_or(self.min));
    }
}

impl DoubleEndedIterator for NumberIterator {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.current_back == SimpleNumber::Integer(0) || self.current_back <= self.current_front {
            return None;
        }

        self.current_back = self.current_back.subtract(SimpleNumber::Integer(1)).unwrap_or(self.min);
        return Some(self.current_back);
    }
}

pub struct DataIndexIterator {
    items: Vec<usize>,
    current: usize,
}

impl DataIndexIterator {
    pub fn new(items: Vec<usize>) -> Self {
        Self { items, current: 0 }
    }
}

impl Iterator for DataIndexIterator {
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.items.len() {
            None
        } else {
            let item = Some(self.items[self.current]);
            self.current += 1;
            item
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::DataIndexIterator;
    use crate::data::SizeIterator;

    #[test]
    fn forward_iteration_full() {
        let mut iter = SizeIterator::new(0, 5);

        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), Some(3));
        assert_eq!(iter.next(), Some(4));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn backward_iteration_full() {
        let mut iter = SizeIterator::new(0, 5);

        assert_eq!(iter.next_back(), Some(4));
        assert_eq!(iter.next_back(), Some(3));
        assert_eq!(iter.next_back(), Some(2));
        assert_eq!(iter.next_back(), Some(1));
        assert_eq!(iter.next_back(), Some(0));
        assert_eq!(iter.next_back(), None);
    }

    #[test]
    fn front_passes_back() {
        let mut iter = SizeIterator::new(0, 5);

        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next_back(), Some(4));
        assert_eq!(iter.next_back(), Some(3));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next_back(), None);
    }

    #[test]
    fn back_passes_front() {
        let mut iter = SizeIterator::new(0, 5);

        assert_eq!(iter.next_back(), Some(4));
        assert_eq!(iter.next_back(), Some(3));
        assert_eq!(iter.next_back(), Some(2));
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next_back(), None);
    }

    #[test]
    fn reset() {
        let mut iter = SizeIterator::new(0, 5);

        assert_eq!(iter.next_back(), Some(4));
        assert_eq!(iter.next_back(), Some(3));
        assert_eq!(iter.next_back(), Some(2));
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next_back(), None);

        iter.reset();

        assert_eq!(iter.next_back(), Some(4));
        assert_eq!(iter.next_back(), Some(3));
        assert_eq!(iter.next_back(), Some(2));
        assert_eq!(iter.next(), Some(0));
        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next_back(), None);
    }

    #[test]
    fn list_iterator() {
        let mut iter = DataIndexIterator::new(vec![1, 2, 3]);

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