Skip to main content

jql_parser/
tokens.rs

1use std::{
2    borrow::Cow,
3    fmt,
4    num::{
5        NonZeroUsize,
6        ParseIntError,
7    },
8    str::FromStr,
9    string::ToString,
10};
11
12/// `Index` used for arrays and objects.
13/// Internally mapped to a `usize` with the newtype pattern.
14#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
15pub struct Index(pub(crate) usize);
16
17impl Index {
18    #[must_use]
19    /// Creates a new `Index`.
20    pub fn new(index: usize) -> Index {
21        Index(index)
22    }
23}
24
25impl From<Index> for usize {
26    fn from(index: Index) -> usize {
27        index.0
28    }
29}
30
31impl fmt::Display for Index {
32    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33        write!(f, "Index ({})", self.0)
34    }
35}
36
37impl FromStr for Index {
38    type Err = ParseIntError;
39
40    fn from_str(s: &str) -> Result<Self, Self::Err> {
41        Ok(Index(s.parse::<usize>()?))
42    }
43}
44
45/// `Range` used for arrays and objects.
46/// Internally mapped to a tuple of `Option` of `Index`.
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct Range(pub(crate) Option<Index>, pub(crate) Option<Index>);
49
50impl Range {
51    #[must_use]
52    /// Creates a new `Range`.
53    pub fn new(start: Option<Index>, end: Option<Index>) -> Range {
54        Range(start, end)
55    }
56
57    #[must_use]
58    /// Maps a `Range` to a tuple of boundaries as `usize`.
59    /// `start` defaults to 0 if `None`.
60    /// `end` is injected based on `len` if `None`.
61    pub fn to_boundaries(&self, len: NonZeroUsize) -> (usize, usize) {
62        let start = self.0.unwrap_or(Index(0));
63        let end = self.1.unwrap_or(Index(len.get() - 1));
64
65        (start.0, end.0)
66    }
67}
68
69impl fmt::Display for Range {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        let format_bound = |bound: &Option<Index>| match bound {
72            Some(index) => index.to_string(),
73            None => String::new(),
74        };
75
76        write!(
77            f,
78            "Range [{}:{}]",
79            format_bound(&self.0),
80            format_bound(&self.1)
81        )
82    }
83}
84
85/// `Lens` used for `LensSelector`.
86/// Internally mapped to a tuple of a slice of `Token` and `Option` of
87/// `LensValue`.
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub struct Lens<'a>(pub(crate) Vec<Token<'a>>, pub(crate) Option<LensValue<'a>>);
90
91impl<'a> Lens<'a> {
92    #[must_use]
93    /// Creates a new `Lens`.
94    pub fn new(tokens: &[Token<'a>], value: Option<LensValue<'a>>) -> Lens<'a> {
95        Lens(tokens.to_vec(), value)
96    }
97
98    #[must_use]
99    /// Gets the content of a `Lens`.
100    pub fn get(&self) -> (Vec<Token<'a>>, Option<LensValue<'a>>) {
101        (self.0.clone(), self.1.clone())
102    }
103
104    #[must_use]
105    /// Gets references to the content of a `Lens` without cloning.
106    pub fn get_ref(&self) -> (&[Token<'a>], Option<&LensValue<'a>>) {
107        (&self.0, self.1.as_ref())
108    }
109}
110
111impl fmt::Display for Lens<'_> {
112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113        write!(
114            f,
115            "{}{}",
116            self.0.stringify(),
117            match &self.1 {
118                Some(lens_value) => {
119                    lens_value.to_string()
120                }
121                None => String::new(),
122            }
123        )
124    }
125}
126
127/// Lens value type.
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub enum LensValue<'a> {
130    /// Variant for a JSON boolean.
131    Bool(bool),
132    /// Variant for JSON null.
133    Null,
134    /// Variant for a JSON number.
135    Number(usize),
136    /// Variant for a JSON string.
137    String(Cow<'a, str>),
138}
139
140impl fmt::Display for LensValue<'_> {
141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142        match self {
143            LensValue::Bool(boolean) => {
144                write!(f, "{boolean}")
145            }
146            LensValue::Null => {
147                write!(f, "null")
148            }
149            LensValue::Number(number) => {
150                write!(f, "{number}")
151            }
152            LensValue::String(string) => write!(f, "{string}"),
153        }
154    }
155}
156
157/// Parser tokens type.
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum Token<'a> {
160    /// Array index selector.
161    ArrayIndexSelector(Vec<Index>),
162    /// Array range selector.
163    ArrayRangeSelector(Range),
164    /// Flatten operator.
165    FlattenOperator,
166    /// Key operator.
167    KeyOperator,
168    /// Group separator.
169    GroupSeparator,
170    /// Key selector.
171    KeySelector(Cow<'a, str>),
172    /// Lens selector.
173    LensSelector(Vec<Lens<'a>>),
174    /// Multi key selector.
175    MultiKeySelector(Vec<Cow<'a, str>>),
176    /// Object index selector.
177    ObjectIndexSelector(Vec<Index>),
178    /// Object range selector.
179    ObjectRangeSelector(Range),
180    /// Pipe in operator.
181    PipeInOperator,
182    /// Pipe out operator.
183    PipeOutOperator,
184    /// Truncate operator.
185    TruncateOperator,
186}
187
188impl<'a> Token<'a> {
189    fn get_name(&self) -> &'a str {
190        match self {
191            Token::ArrayIndexSelector(_) => "Array Index Selector",
192            Token::ArrayRangeSelector(_) => "Array Range Selector",
193            Token::FlattenOperator => "Flatten Operator",
194            Token::KeyOperator => "Key Operator",
195            Token::GroupSeparator => "Group Separator",
196            Token::KeySelector(_) => "Key Selector",
197            Token::LensSelector(_) => "Lens Selector",
198            Token::MultiKeySelector(_) => "Multi Key Selector",
199            Token::ObjectIndexSelector(_) => "Object Index Selector",
200            Token::ObjectRangeSelector(_) => "Object Range Selector",
201            Token::PipeInOperator => "Pipe In Operator",
202            Token::PipeOutOperator => "Pipe Out Operator",
203            Token::TruncateOperator => "Truncate Operator",
204        }
205    }
206}
207
208impl fmt::Display for Token<'_> {
209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210        match self {
211            Token::ArrayIndexSelector(indexes) | Token::ObjectIndexSelector(indexes) => {
212                let formatted_indexes = indexes
213                    .iter()
214                    .map(ToString::to_string)
215                    .collect::<Vec<String>>()
216                    .join(", ");
217
218                write!(f, "{} [{formatted_indexes}]", self.get_name())
219            }
220            Token::ArrayRangeSelector(range) | Token::ObjectRangeSelector(range) => {
221                write!(f, "{} {}", self.get_name(), range)
222            }
223            Token::KeySelector(key) => {
224                write!(f, r#"{} "{key}""#, self.get_name())
225            }
226            Token::LensSelector(lenses) => {
227                let formatted_indexes = lenses
228                    .iter()
229                    .map(ToString::to_string)
230                    .collect::<Vec<String>>()
231                    .join(", ");
232
233                write!(f, "{} [{formatted_indexes}]", self.get_name())
234            }
235            Token::MultiKeySelector(multi_key) => {
236                let formatted_keys = multi_key
237                    .iter()
238                    .map(AsRef::as_ref)
239                    .collect::<Vec<&str>>()
240                    .join(", ");
241
242                write!(f, "{} {formatted_keys}", self.get_name())
243            }
244            Token::FlattenOperator
245            | Token::KeyOperator
246            | Token::GroupSeparator
247            | Token::PipeInOperator
248            | Token::PipeOutOperator
249            | Token::TruncateOperator => {
250                write!(f, "{}", self.get_name())
251            }
252        }
253    }
254}
255
256/// Trait used to expose custom display methods.
257pub trait View {
258    /// Returns a stringified version of `self`.
259    fn stringify(&self) -> String;
260}
261
262impl<'a, T: AsRef<[Token<'a>]>> View for T {
263    fn stringify(&self) -> String {
264        self.as_ref()
265            .iter()
266            .map(ToString::to_string)
267            .collect::<Vec<String>>()
268            .join(", ")
269    }
270}