Skip to main content

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    #[must_use]
104    /// Gets references to the content of a `Lens` without cloning.
105    pub fn get_ref(&self) -> (&[Token<'a>], Option<&LensValue<'a>>) {
106        (&self.0, self.1.as_ref())
107    }
108}
109
110impl fmt::Display for Lens<'_> {
111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112        write!(
113            f,
114            "{}{}",
115            self.0.stringify(),
116            match &self.1 {
117                Some(lens_value) => {
118                    lens_value.to_string()
119                }
120                None => String::new(),
121            }
122        )
123    }
124}
125
126/// Lens value type.
127#[derive(Debug, Clone, PartialEq, Eq)]
128pub enum LensValue<'a> {
129    /// Variant for a JSON boolean.
130    Bool(bool),
131    /// Variant for JSON null.
132    Null,
133    /// Variant for a JSON number.
134    Number(usize),
135    /// Variant for a JSON string.
136    String(&'a str),
137}
138
139impl fmt::Display for LensValue<'_> {
140    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141        match self {
142            LensValue::Bool(boolean) => {
143                write!(f, "{boolean}")
144            }
145            LensValue::Null => {
146                write!(f, "null")
147            }
148            LensValue::Number(number) => {
149                write!(f, "{number}")
150            }
151            LensValue::String(string) => write!(f, "{string}"),
152        }
153    }
154}
155
156/// Parser tokens type.
157#[derive(Debug, Clone, PartialEq, Eq)]
158pub enum Token<'a> {
159    /// Array index selector.
160    ArrayIndexSelector(Vec<Index>),
161    /// Array range selector.
162    ArrayRangeSelector(Range),
163    /// Flatten operator.
164    FlattenOperator,
165    /// Key operator.
166    KeyOperator,
167    /// Group separator.
168    GroupSeparator,
169    /// Key selector.
170    KeySelector(&'a str),
171    /// Lens selector.
172    LensSelector(Vec<Lens<'a>>),
173    /// Multi key selector.
174    MultiKeySelector(Vec<&'a str>),
175    /// Object index selector.
176    ObjectIndexSelector(Vec<Index>),
177    /// Object range selector.
178    ObjectRangeSelector(Range),
179    /// Pipe in operator.
180    PipeInOperator,
181    /// Pipe out operator.
182    PipeOutOperator,
183    /// Truncate operator.
184    TruncateOperator,
185}
186
187impl<'a> Token<'a> {
188    fn get_name(&self) -> &'a str {
189        match self {
190            Token::ArrayIndexSelector(_) => "Array Index Selector",
191            Token::ArrayRangeSelector(_) => "Array Range Selector",
192            Token::FlattenOperator => "Flatten Operator",
193            Token::KeyOperator => "Key Operator",
194            Token::GroupSeparator => "Group Separator",
195            Token::KeySelector(_) => "Key Selector",
196            Token::LensSelector(_) => "Lens Selector",
197            Token::MultiKeySelector(_) => "Multi Key Selector",
198            Token::ObjectIndexSelector(_) => "Object Index Selector",
199            Token::ObjectRangeSelector(_) => "Object Range Selector",
200            Token::PipeInOperator => "Pipe In Operator",
201            Token::PipeOutOperator => "Pipe Out Operator",
202            Token::TruncateOperator => "Truncate Operator",
203        }
204    }
205}
206
207impl fmt::Display for Token<'_> {
208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209        match self {
210            Token::ArrayIndexSelector(indexes) | Token::ObjectIndexSelector(indexes) => {
211                let formatted_indexes = indexes
212                    .iter()
213                    .map(ToString::to_string)
214                    .collect::<Vec<String>>()
215                    .join(", ");
216
217                write!(f, "{} [{formatted_indexes}]", self.get_name())
218            }
219            Token::ArrayRangeSelector(range) | Token::ObjectRangeSelector(range) => {
220                write!(f, "{} {}", self.get_name(), range)
221            }
222            Token::KeySelector(key) => {
223                write!(f, r#"{} "{key}""#, self.get_name())
224            }
225            Token::LensSelector(lenses) => {
226                let formatted_indexes = lenses
227                    .iter()
228                    .map(ToString::to_string)
229                    .collect::<Vec<String>>()
230                    .join(", ");
231
232                write!(f, "{} [{formatted_indexes}]", self.get_name())
233            }
234            Token::MultiKeySelector(multi_key) => {
235                let formatted_keys = multi_key.join(", ");
236
237                write!(f, "{} {formatted_keys}", self.get_name())
238            }
239            Token::FlattenOperator
240            | Token::KeyOperator
241            | Token::GroupSeparator
242            | Token::PipeInOperator
243            | Token::PipeOutOperator
244            | Token::TruncateOperator => {
245                write!(f, "{}", self.get_name())
246            }
247        }
248    }
249}
250
251/// Trait used to expose custom display methods.
252pub trait View {
253    /// Returns a stringified version of `self`.
254    fn stringify(&self) -> String;
255}
256
257impl<'a, T: AsRef<[Token<'a>]>> View for T {
258    fn stringify(&self) -> String {
259        self.as_ref()
260            .iter()
261            .map(ToString::to_string)
262            .collect::<Vec<String>>()
263            .join(", ")
264    }
265}