Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Commit 1397caf

Browse files
author
Marko Mikulicic
committed
Array indexing
1 parent eafdf74 commit 1397caf

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

src/matchers.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,40 @@ impl Matcher for Child {
5858
}
5959
}
6060

61+
/// Selects an array item by index.
62+
///
63+
/// If the index is negative, it references element len-abs(index).
64+
pub struct ArrayIndex {
65+
index: i64,
66+
}
67+
68+
impl ArrayIndex {
69+
pub fn new(index: i64) -> Self {
70+
ArrayIndex { index }
71+
}
72+
}
73+
74+
impl Matcher for ArrayIndex {
75+
fn select<'a>(&self, node: &'a Value) -> Iter<'a> {
76+
let len = if let Value::Array(a) = node {
77+
a.len()
78+
} else {
79+
0
80+
};
81+
let idx = if self.index >= 0 {
82+
self.index as usize
83+
} else {
84+
let abs = (-self.index) as usize;
85+
if abs < len {
86+
len - abs
87+
} else {
88+
return Box::new(iter::empty());
89+
}
90+
};
91+
Box::new(node.get(idx).into_iter())
92+
}
93+
}
94+
6195
/// Applies a sequence of selectors on the same node and returns
6296
/// a concatenation of the results.
6397
pub struct Union {
@@ -96,4 +130,44 @@ mod tests {
96130
let r: Vec<&Value> = s.select(&j).collect();
97131
assert_eq!(format!("{:?}", r), "[Number(1), Number(2)]");
98132
}
133+
134+
#[test]
135+
fn array_index() {
136+
let s = ArrayIndex::new(1);
137+
let j = json!([1, 2]);
138+
let r: Vec<&Value> = s.select(&j).collect();
139+
assert_eq!(format!("{:?}", r), "[Number(2)]");
140+
}
141+
142+
#[test]
143+
fn array_index_zero() {
144+
let s = ArrayIndex::new(0);
145+
let j = json!([1, 2]);
146+
let r: Vec<&Value> = s.select(&j).collect();
147+
assert_eq!(format!("{:?}", r), "[Number(1)]");
148+
}
149+
150+
#[test]
151+
fn array_index_oob() {
152+
let s = ArrayIndex::new(4);
153+
let j = json!([1, 2]);
154+
let r: Vec<&Value> = s.select(&j).collect();
155+
assert_eq!(r.len(), 0);
156+
}
157+
158+
#[test]
159+
fn array_index_negative() {
160+
let s = ArrayIndex::new(-1);
161+
let j = json!([1, 2]);
162+
let r: Vec<&Value> = s.select(&j).collect();
163+
assert_eq!(format!("{:?}", r), "[Number(2)]");
164+
}
165+
166+
#[test]
167+
fn array_index_negative_oob() {
168+
let s = ArrayIndex::new(-10);
169+
let j = json!([1, 2]);
170+
let r: Vec<&Value> = s.select(&j).collect();
171+
assert_eq!(r.len(), 0);
172+
}
99173
}

0 commit comments

Comments
 (0)