jsonata/value/
range.rs

1use std::ops::Index;
2
3use bumpalo::Bump;
4
5use super::Value;
6
7#[derive(Debug)]
8pub struct Range<'a> {
9    arena: &'a Bump,
10    start: isize,
11    end: isize,
12}
13
14impl<'a> Range<'a> {
15    pub fn new(arena: &'a Bump, start: isize, end: isize) -> Self {
16        if end < start {
17            panic!("Tried to contruct a range with negative length");
18        }
19        Self { arena, start, end }
20    }
21
22    pub fn start(&self) -> isize {
23        self.start
24    }
25
26    pub fn end(&self) -> isize {
27        self.end
28    }
29
30    pub fn len(&self) -> usize {
31        (self.end - self.start + 1) as usize
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.len() == 0
36    }
37
38    pub fn nth(&self, index: usize) -> Option<&'a Value<'a>> {
39        if index < self.len() {
40            Some(Value::number(
41                self.arena,
42                (self.start + index as isize) as f64,
43            ))
44        } else {
45            None
46        }
47    }
48}
49
50impl<'a> Index<usize> for Range<'a> {
51    type Output = Value<'a>;
52
53    fn index(&self, index: usize) -> &Self::Output {
54        self.nth(index).unwrap_or_else(Value::undefined)
55    }
56}
57
58impl<'a> PartialEq<Range<'_>> for Range<'a> {
59    fn eq(&self, other: &Range<'_>) -> bool {
60        self.start == other.start && self.end == other.end
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use bumpalo::Bump;
68
69    #[test]
70    fn len() {
71        let arena = Bump::new();
72        let range = Range::new(&arena, 1, 5);
73        assert_eq!(range.start(), 1);
74        assert_eq!(range.end(), 5);
75        assert_eq!(range.len(), 5);
76        assert!(!range.is_empty());
77    }
78
79    #[test]
80    fn nth() {
81        let arena = Bump::new();
82        let range = Range::new(&arena, 1, 5);
83        assert_eq!(*range.nth(0).unwrap(), 1_isize);
84        assert_eq!(*range.nth(1).unwrap(), 2_isize);
85        assert_eq!(*range.nth(2).unwrap(), 3_isize);
86        assert_eq!(*range.nth(3).unwrap(), 4_isize);
87        assert_eq!(*range.nth(4).unwrap(), 5_isize);
88        assert!(range.nth(5).is_none());
89    }
90
91    #[test]
92    fn eq() {
93        let arena = Bump::new();
94        let range1 = Range::new(&arena, 1, 5);
95        let range2 = Range::new(&arena, 1, 5);
96        assert_eq!(range1, range2);
97    }
98
99    #[test]
100    fn ne() {
101        let arena = Bump::new();
102        let range1 = Range::new(&arena, 2, 5);
103        let range2 = Range::new(&arena, 1, 5);
104        assert_ne!(range1, range2);
105    }
106
107    #[test]
108    fn index() {
109        let arena = Bump::new();
110        let range = Range::new(&arena, 1, 5);
111        assert_eq!(range[0], 1_isize);
112        assert_eq!(range[1], 2_isize);
113        assert_eq!(range[2], 3_isize);
114        assert_eq!(range[3], 4_isize);
115        assert_eq!(range[4], 5_isize);
116        assert!(range[5].is_undefined());
117    }
118
119    #[test]
120    fn negative() {
121        let arena = Bump::new();
122        let range = Range::new(&arena, -10, -5);
123        assert_eq!(range[0], -10_isize);
124        assert_eq!(range[1], -9_isize);
125        assert_eq!(range[2], -8_isize);
126        assert_eq!(range[3], -7_isize);
127        assert_eq!(range[4], -6_isize);
128        assert_eq!(range[5], -5_isize);
129        assert!(range[6].is_undefined());
130    }
131}