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}