@@ -58,6 +58,40 @@ impl Matcher for Child {
58
58
}
59
59
}
60
60
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
+
61
95
/// Applies a sequence of selectors on the same node and returns
62
96
/// a concatenation of the results.
63
97
pub struct Union {
@@ -96,4 +130,44 @@ mod tests {
96
130
let r: Vec < & Value > = s. select ( & j) . collect ( ) ;
97
131
assert_eq ! ( format!( "{:?}" , r) , "[Number(1), Number(2)]" ) ;
98
132
}
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
+ }
99
173
}
0 commit comments