11//! Utility for building a [`JsonPathQuery`](`crate::JsonPathQuery`)
22//! programmatically.
3- use crate :: { num:: JsonInt , str:: JsonString , Index , JsonPathQuery , Segment , Selector , Selectors } ;
3+ use crate :: { num:: JsonInt , str:: JsonString , Index , JsonPathQuery , Segment , Selector , Selectors , SliceBuilder } ;
44
55/// Builder for [`JsonPathQuery`] instances.
66///
@@ -13,12 +13,13 @@ use crate::{num::JsonInt, str::JsonString, Index, JsonPathQuery, Segment, Select
1313/// .descendant_name("b")
1414/// .child_wildcard()
1515/// .child_name("c")
16- /// .descendant_wildcard();
16+ /// .descendant_wildcard()
17+ /// .child_slice(|x| x.with_start(3).with_end(-7).with_step(2));
1718///
1819/// // Can also use `builder.build()` as a non-consuming version.
1920/// let query: JsonPathQuery = builder.into();
2021///
21- /// assert_eq!(query.to_string(), "$['a']..['b'][*]['c']..[*]");
22+ /// assert_eq!(query.to_string(), "$['a']..['b'][*]['c']..[*][3:-7:2] ");
2223/// ```
2324pub struct JsonPathQueryBuilder {
2425 segments : Vec < Segment > ,
@@ -133,6 +134,17 @@ impl JsonPathQueryBuilder {
133134 self . child ( |x| x. index ( idx) )
134135 }
135136
137+ /// Add a child segment with a single slice selector.
138+ ///
139+ /// This is a shorthand for `.child(|x| x.slice(slice_builder))`.
140+ #[ inline( always) ]
141+ pub fn child_slice < F > ( & mut self , slice_builder : F ) -> & mut Self
142+ where
143+ F : FnOnce ( & mut SliceBuilder ) -> & mut SliceBuilder ,
144+ {
145+ self . child ( |x| x. slice ( slice_builder) )
146+ }
147+
136148 /// Add a descendant segment with a single name selector.
137149 ///
138150 /// This is a shorthand for `.descendant(|x| x.name(name))`.
@@ -157,6 +169,17 @@ impl JsonPathQueryBuilder {
157169 self . descendant ( |x| x. index ( idx) )
158170 }
159171
172+ /// Add a descendant segment with a single slice selector.
173+ ///
174+ /// This is a shorthand for `.descendant(|x| x.slice(slice_builder))`.
175+ #[ inline( always) ]
176+ pub fn descendant_slice < F > ( & mut self , slice_builder : F ) -> & mut Self
177+ where
178+ F : FnOnce ( & mut SliceBuilder ) -> & mut SliceBuilder ,
179+ {
180+ self . descendant ( |x| x. slice ( slice_builder) )
181+ }
182+
160183 /// Produce a [`JsonPathQuery`] from the builder.
161184 ///
162185 /// This clones all data in the builder to create the query.
@@ -225,6 +248,47 @@ impl JsonPathSelectorsBuilder {
225248 self
226249 }
227250
251+ /// Add a slice selector based on a given start, end, and step integers.
252+ ///
253+ /// The result is a [`Selector::Slice`] with given `start`, `end`, and `step`.
254+ ///
255+ /// ## Examples
256+ ///
257+ /// ```rust
258+ /// # use rsonpath_syntax::{Selector, SliceBuilder, Index, Step, num::{JsonNonZeroUInt, JsonUInt}, builder::JsonPathQueryBuilder};
259+ /// let mut builder = JsonPathQueryBuilder::new();
260+ /// builder.child(|x| x
261+ /// .slice(|s| s.with_start(10).with_end(-20).with_step(5))
262+ /// .slice(|s| s.with_start(-20).with_step(-30)));
263+ /// let result = builder.into_query();
264+ ///
265+ /// assert_eq!(result.segments().len(), 1);
266+ /// let segment = &result.segments()[0];
267+ /// let selectors = segment.selectors().as_slice();
268+ /// match (&selectors[0], &selectors[1]) {
269+ /// (Selector::Slice(s1), Selector::Slice(s2)) => {
270+ /// assert_eq!(s1.start(), Index::FromStart(10.into()));
271+ /// assert_eq!(s1.end(), Some(Index::FromEnd(JsonNonZeroUInt::try_from(20).unwrap())));
272+ /// assert_eq!(s1.step(), Step::Forward(5.into()));
273+ /// assert_eq!(s2.start(), Index::FromEnd(JsonNonZeroUInt::try_from(20).unwrap()));
274+ /// assert_eq!(s2.end(), None);
275+ /// assert_eq!(s2.step(), Step::Backward(JsonNonZeroUInt::try_from(30).unwrap()));
276+ /// }
277+ /// _ => unreachable!()
278+ /// }
279+ /// ```
280+ #[ inline( always) ]
281+ pub fn slice < F > ( & mut self , slice_builder : F ) -> & mut Self
282+ where
283+ F : FnOnce ( & mut SliceBuilder ) -> & mut SliceBuilder ,
284+ {
285+ let mut slice = SliceBuilder :: new ( ) ;
286+ slice_builder ( & mut slice) ;
287+ let slice = slice. into ( ) ;
288+ self . selectors . push ( Selector :: Slice ( slice) ) ;
289+ self
290+ }
291+
228292 /// Add a wildcard selector.
229293 #[ inline( always) ]
230294 pub fn wildcard ( & mut self ) -> & mut Self {
0 commit comments