jsonata 0.0.0

An (incomplete) implementation of JSONata in Rust
Documentation
use std::iter::Iterator;

use super::Value;

pub struct MemberIterator<'a> {
    value: &'a Value<'a>,
    front: usize,
    back: usize,
    back_done: bool,
}

impl<'a> MemberIterator<'a> {
    pub fn new(value: &'a Value<'a>) -> Self {
        Self {
            value,
            front: 0,
            back: value.len().saturating_sub(1),
            back_done: false,
        }
    }
}

impl<'a> Iterator for MemberIterator<'a> {
    type Item = &'a Value<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.front < self.value.len() {
            let result = match self.value {
                Value::Array(array, _) => array.get(self.front).copied(),
                Value::Range(range) => range.nth(self.front),
                _ => unreachable!(),
            };
            self.front += 1;
            result
        } else {
            None
        }
    }
}

impl<'a> DoubleEndedIterator for MemberIterator<'a> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.back_done {
            return None;
        }

        let result = match self.value {
            Value::Array(array, _) => array.get(self.back).copied(),
            Value::Range(range) => range.nth(self.back),
            _ => unreachable!(),
        };

        if self.back == 0 {
            self.back_done = true;
            return result;
        }

        self.back -= 1;
        result
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use bumpalo::Bump;

    #[test]
    fn forward() {
        let arena = Bump::new();
        let range = Value::range(&arena, 1, 5);
        let mut iter = MemberIterator::new(range);
        assert_eq!(*iter.next().unwrap(), 1_isize);
        assert_eq!(*iter.next().unwrap(), 2_isize);
        assert_eq!(*iter.next().unwrap(), 3_isize);
        assert_eq!(*iter.next().unwrap(), 4_isize);
        assert_eq!(*iter.next().unwrap(), 5_isize);
        assert!(iter.next().is_none());
    }

    #[test]
    fn backward() {
        let arena = Bump::new();
        let range = Value::range(&arena, 1, 5);
        let mut iter = MemberIterator::new(range);
        assert_eq!(*iter.next_back().unwrap(), 5_isize);
        assert_eq!(*iter.next_back().unwrap(), 4_isize);
        assert_eq!(*iter.next_back().unwrap(), 3_isize);
        assert_eq!(*iter.next_back().unwrap(), 2_isize);
        assert_eq!(*iter.next_back().unwrap(), 1_isize);
        assert!(iter.next_back().is_none());
    }

    #[test]
    fn reverse() {
        let arena = Bump::new();
        let range = Value::range(&arena, 1, 5);
        let mut iter = MemberIterator::new(range).rev();
        assert_eq!(*iter.next().unwrap(), 5_isize);
        assert_eq!(*iter.next().unwrap(), 4_isize);
        assert_eq!(*iter.next().unwrap(), 3_isize);
        assert_eq!(*iter.next().unwrap(), 2_isize);
        assert_eq!(*iter.next().unwrap(), 1_isize);
        assert!(iter.next().is_none());
    }
}