jql_parser/
tokens.rs

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