Skip to main content

promql_parser/parser/
ast.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::label::{Labels, Matchers, METRIC_NAME};
16use crate::parser::token::{
17    self, token_display, T_BOTTOMK, T_COUNT_VALUES, T_END, T_QUANTILE, T_START, T_TOPK,
18};
19use crate::parser::token::{Token, TokenId, TokenType};
20use crate::parser::value::ValueType;
21use crate::parser::{indent, Function, FunctionArgs, Prettier, MAX_CHARACTERS_PER_LINE};
22use crate::util::display_duration;
23use chrono::{DateTime, Utc};
24use std::fmt::{self, Write};
25use std::ops::Neg;
26use std::sync::Arc;
27use std::time::{Duration, SystemTime};
28
29/// LabelModifier acts as
30///
31/// # Aggregation Modifier
32///
33/// - Exclude means `ignoring`
34/// - Include means `on`
35///
36/// # Vector Match Modifier
37///
38/// - Exclude means `without` removes the listed labels from the result vector,
39///   while all other labels are preserved in the output.
40///
41/// - Include means `by` does the opposite and drops labels that are not listed in the by clause,
42///   even if their label values are identical between all elements of the vector.
43///
44/// if empty listed labels, meaning no grouping
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum LabelModifier {
47    Include(Labels),
48    Exclude(Labels),
49}
50
51impl LabelModifier {
52    pub fn labels(&self) -> &Labels {
53        match self {
54            LabelModifier::Include(l) => l,
55            LabelModifier::Exclude(l) => l,
56        }
57    }
58
59    pub fn is_include(&self) -> bool {
60        matches!(*self, LabelModifier::Include(_))
61    }
62
63    pub fn include(ls: Vec<&str>) -> Self {
64        Self::Include(Labels::new(ls))
65    }
66
67    pub fn exclude(ls: Vec<&str>) -> Self {
68        Self::Exclude(Labels::new(ls))
69    }
70}
71
72/// The label list provided with the group_left or group_right modifier contains
73/// additional labels from the "one"-side to be included in the result metrics.
74#[derive(Debug, Clone, PartialEq, Eq)]
75#[cfg_attr(feature = "ser", derive(serde::Serialize))]
76#[cfg_attr(feature = "ser", serde(rename_all = "kebab-case"))]
77pub enum VectorMatchCardinality {
78    OneToOne,
79    ManyToOne(Labels),
80    OneToMany(Labels),
81    ManyToMany, // logical/set binary operators
82}
83
84impl VectorMatchCardinality {
85    pub fn labels(&self) -> Option<&Labels> {
86        match self {
87            VectorMatchCardinality::ManyToOne(l) => Some(l),
88            VectorMatchCardinality::OneToMany(l) => Some(l),
89            VectorMatchCardinality::ManyToMany => None,
90            VectorMatchCardinality::OneToOne => None,
91        }
92    }
93
94    pub fn many_to_one(ls: Vec<&str>) -> Self {
95        Self::ManyToOne(Labels::new(ls))
96    }
97
98    pub fn one_to_many(ls: Vec<&str>) -> Self {
99        Self::OneToMany(Labels::new(ls))
100    }
101}
102
103/// VectorMatchFillValues contains the fill values to use for Vector matching
104/// when one side does not find a match on the other side.
105/// When a fill value is nil, no fill is applied for that side, and there
106/// is no output for the match group if there is no match.
107#[derive(Debug, Clone, PartialEq, Default)]
108#[cfg_attr(feature = "ser", derive(serde::Serialize))]
109pub struct VectorMatchFillValues {
110    pub rhs: Option<f64>,
111    pub lhs: Option<f64>,
112}
113
114impl VectorMatchFillValues {
115    pub fn new(lhs: f64, rhs: f64) -> Self {
116        Self {
117            rhs: Some(rhs),
118            lhs: Some(lhs),
119        }
120    }
121
122    pub fn with_rhs(mut self, rhs: f64) -> Self {
123        self.rhs = Some(rhs);
124        self
125    }
126
127    pub fn with_lhs(mut self, lhs: f64) -> Self {
128        self.lhs = Some(lhs);
129        self
130    }
131}
132
133/// Binary Expr Modifier
134#[derive(Debug, Clone, PartialEq)]
135pub struct BinModifier {
136    /// The matching behavior for the operation if both operands are Vectors.
137    /// If they are not this field is None.
138    pub card: VectorMatchCardinality,
139
140    /// on/ignoring on labels.
141    /// like a + b, no match modifier is needed.
142    pub matching: Option<LabelModifier>,
143    /// If a comparison operator, return 0/1 rather than filtering.
144    pub return_bool: bool,
145    /// Fill-in values to use when a series from one side does not find a match
146    /// on the other side.
147    pub fill_values: VectorMatchFillValues,
148}
149
150impl fmt::Display for BinModifier {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        let mut s = String::from(self.bool_str());
153
154        if let Some(matching) = &self.matching {
155            match matching {
156                LabelModifier::Include(ls) => write!(s, "on ({ls}) ")?,
157                LabelModifier::Exclude(ls) if !ls.is_empty() => write!(s, "ignoring ({ls}) ")?,
158                _ => (),
159            }
160        }
161
162        match &self.card {
163            VectorMatchCardinality::ManyToOne(ls) => write!(s, "group_left ({ls}) ")?,
164            VectorMatchCardinality::OneToMany(ls) => write!(s, "group_right ({ls}) ")?,
165            _ => (),
166        }
167
168        if self.fill_values.rhs.is_some() || self.fill_values.lhs.is_some() {
169            if self.fill_values.rhs == self.fill_values.lhs {
170                let fill_value = self.fill_values.rhs.unwrap();
171                write!(s, "fill ({fill_value}) ")?;
172            } else {
173                if let Some(fill_value) = self.fill_values.lhs {
174                    write!(s, "fill_left ({fill_value}) ")?;
175                }
176
177                if let Some(fill_value) = self.fill_values.rhs {
178                    write!(s, "fill_right ({fill_value}) ")?;
179                }
180            }
181        }
182
183        if s.trim().is_empty() {
184            write!(f, "")
185        } else {
186            write!(f, " {}", s.trim_end()) // there is a leading space here
187        }
188    }
189}
190
191impl Default for BinModifier {
192    fn default() -> Self {
193        Self {
194            card: VectorMatchCardinality::OneToOne,
195            matching: None,
196            return_bool: false,
197            fill_values: VectorMatchFillValues::default(),
198        }
199    }
200}
201
202impl BinModifier {
203    pub fn with_card(mut self, card: VectorMatchCardinality) -> Self {
204        self.card = card;
205        self
206    }
207
208    pub fn with_matching(mut self, matching: Option<LabelModifier>) -> Self {
209        self.matching = matching;
210        self
211    }
212
213    pub fn with_return_bool(mut self, return_bool: bool) -> Self {
214        self.return_bool = return_bool;
215        self
216    }
217
218    pub fn with_fill_values(mut self, fill_values: VectorMatchFillValues) -> Self {
219        self.fill_values = fill_values;
220        self
221    }
222
223    pub fn is_labels_joint(&self) -> bool {
224        matches!(
225            (self.card.labels(), &self.matching),
226            (Some(labels), Some(matching)) if labels.is_joint(matching.labels())
227        )
228    }
229
230    pub fn intersect_labels(&self) -> Option<Vec<String>> {
231        if let Some(labels) = self.card.labels() {
232            if let Some(matching) = &self.matching {
233                return Some(labels.intersect(matching.labels()).labels);
234            }
235        };
236        None
237    }
238
239    pub fn is_matching_on(&self) -> bool {
240        matches!(&self.matching, Some(matching) if matching.is_include())
241    }
242
243    pub fn is_matching_labels_not_empty(&self) -> bool {
244        matches!(&self.matching, Some(matching) if !matching.labels().is_empty())
245    }
246
247    pub fn bool_str(&self) -> &str {
248        if self.return_bool {
249            "bool "
250        } else {
251            ""
252        }
253    }
254}
255
256#[cfg(feature = "ser")]
257pub(crate) fn serialize_grouping<S>(
258    this: &Option<LabelModifier>,
259    serializer: S,
260) -> Result<S::Ok, S::Error>
261where
262    S: serde::Serializer,
263{
264    use serde::ser::SerializeMap;
265    let mut map = serializer.serialize_map(Some(2))?;
266    match this {
267        Some(LabelModifier::Include(l)) => {
268            map.serialize_entry("grouping", l)?;
269            map.serialize_entry("without", &false)?;
270        }
271        Some(LabelModifier::Exclude(l)) => {
272            map.serialize_entry("grouping", l)?;
273            map.serialize_entry("without", &true)?;
274        }
275        None => {
276            map.serialize_entry("grouping", &(vec![] as Vec<String>))?;
277            map.serialize_entry("without", &false)?;
278        }
279    }
280
281    map.end()
282}
283
284#[cfg(feature = "ser")]
285pub(crate) fn serialize_bin_modifier<S>(
286    this: &Option<BinModifier>,
287    serializer: S,
288) -> Result<S::Ok, S::Error>
289where
290    S: serde::Serializer,
291{
292    use serde::ser::SerializeMap;
293    use serde_json::json;
294
295    let mut map = serializer.serialize_map(Some(2))?;
296
297    map.serialize_entry(
298        "bool",
299        &this.as_ref().map(|t| t.return_bool).unwrap_or(false),
300    )?;
301    if let Some(t) = this {
302        if let Some(labels) = &t.matching {
303            map.serialize_key("matching")?;
304
305            match labels {
306                LabelModifier::Include(labels) => {
307                    let value = json!({
308                        "card": t.card,
309                        "include": [],
310                        "labels": labels,
311                        "on": true,
312                        "fillValues": t.fill_values,
313                    });
314                    map.serialize_value(&value)?;
315                }
316                LabelModifier::Exclude(labels) => {
317                    let value = json!({
318                        "card": t.card,
319                        "include": [],
320                        "labels": labels,
321                        "on": false,
322                        "fillValues": t.fill_values,
323                    });
324                    map.serialize_value(&value)?;
325                }
326            }
327        } else {
328            let value = json!({
329                "card": t.card,
330                "include": [],
331                "labels": [],
332                "on": false,
333                "fillValues": t.fill_values,
334            });
335            map.serialize_entry("matching", &value)?;
336        }
337    } else {
338        map.serialize_entry("matching", &None::<bool>)?;
339    }
340
341    map.end()
342}
343
344#[cfg(feature = "ser")]
345pub(crate) fn serialize_at_modifier<S>(
346    this: &Option<AtModifier>,
347    serializer: S,
348) -> Result<S::Ok, S::Error>
349where
350    S: serde::Serializer,
351{
352    use serde::ser::SerializeMap;
353    let mut map = serializer.serialize_map(Some(2))?;
354    match this {
355        Some(AtModifier::Start) => {
356            map.serialize_entry("startOrEnd", &Some("start"))?;
357            map.serialize_entry("timestamp", &None::<u128>)?;
358        }
359        Some(AtModifier::End) => {
360            map.serialize_entry("startOrEnd", &Some("end"))?;
361            map.serialize_entry("timestamp", &None::<u128>)?;
362        }
363        Some(AtModifier::At(time)) => {
364            map.serialize_entry("startOrEnd", &None::<&str>)?;
365            map.serialize_entry(
366                "timestamp",
367                &time
368                    .duration_since(SystemTime::UNIX_EPOCH)
369                    .unwrap_or(Duration::ZERO)
370                    .as_millis(),
371            )?;
372        }
373        None => {
374            map.serialize_entry("startOrEnd", &None::<&str>)?;
375            map.serialize_entry("timestamp", &None::<u128>)?;
376        }
377    }
378
379    map.end()
380}
381
382#[derive(Debug, Clone, PartialEq)]
383pub enum Offset {
384    Pos(Duration),
385    Neg(Duration),
386}
387
388impl Offset {
389    #[cfg(feature = "ser")]
390    pub(crate) fn as_millis(&self) -> i128 {
391        match self {
392            Self::Pos(dur) => dur.as_millis() as i128,
393            Self::Neg(dur) => -(dur.as_millis() as i128),
394        }
395    }
396
397    #[cfg(feature = "ser")]
398    pub(crate) fn serialize_offset<S>(
399        offset: &Option<Self>,
400        serializer: S,
401    ) -> Result<S::Ok, S::Error>
402    where
403        S: serde::Serializer,
404    {
405        let value = offset.as_ref().map(|o| o.as_millis()).unwrap_or(0);
406        serializer.serialize_i128(value)
407    }
408}
409
410impl fmt::Display for Offset {
411    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
412        match self {
413            Offset::Pos(dur) => write!(f, "{}", display_duration(dur)),
414            Offset::Neg(dur) => write!(f, "-{}", display_duration(dur)),
415        }
416    }
417}
418
419#[derive(Debug, Clone, PartialEq)]
420pub enum AtModifier {
421    Start,
422    End,
423    /// at can be earlier than UNIX_EPOCH
424    At(SystemTime),
425}
426
427impl fmt::Display for AtModifier {
428    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
429        match self {
430            AtModifier::Start => write!(f, "@ {}()", token_display(T_START)),
431            AtModifier::End => write!(f, "@ {}()", token_display(T_END)),
432            AtModifier::At(time) => {
433                let d = time
434                    .duration_since(SystemTime::UNIX_EPOCH)
435                    .unwrap_or(Duration::ZERO); // This should not happen
436                write!(f, "@ {:.3}", d.as_secs_f64())
437            }
438        }
439    }
440}
441
442impl TryFrom<TokenId> for AtModifier {
443    type Error = String;
444
445    fn try_from(id: TokenId) -> Result<Self, Self::Error> {
446        match id {
447            T_START => Ok(AtModifier::Start),
448            T_END => Ok(AtModifier::End),
449            _ => Err(format!(
450                "invalid @ modifier preprocessor '{}', START or END is valid.",
451                token::token_display(id)
452            )),
453        }
454    }
455}
456
457impl TryFrom<Token> for AtModifier {
458    type Error = String;
459
460    fn try_from(token: Token) -> Result<Self, Self::Error> {
461        AtModifier::try_from(token.id())
462    }
463}
464
465impl TryFrom<NumberLiteral> for AtModifier {
466    type Error = String;
467
468    fn try_from(num: NumberLiteral) -> Result<Self, Self::Error> {
469        AtModifier::try_from(num.val)
470    }
471}
472
473impl TryFrom<Expr> for AtModifier {
474    type Error = String;
475
476    fn try_from(ex: Expr) -> Result<Self, Self::Error> {
477        match ex {
478            Expr::NumberLiteral(nl) => AtModifier::try_from(nl),
479            _ => Err("invalid float value after @ modifier".into()),
480        }
481    }
482}
483
484impl TryFrom<f64> for AtModifier {
485    type Error = String;
486
487    fn try_from(secs: f64) -> Result<Self, Self::Error> {
488        let err_info = format!("timestamp out of bounds for @ modifier: {secs}");
489
490        if secs.is_nan() || secs.is_infinite() || secs >= f64::MAX || secs <= f64::MIN {
491            return Err(err_info);
492        }
493        let milli = (secs * 1000f64).round().abs() as u64;
494
495        let duration = Duration::from_millis(milli);
496        let mut st = Some(SystemTime::UNIX_EPOCH);
497        if secs.is_sign_positive() {
498            st = SystemTime::UNIX_EPOCH.checked_add(duration);
499        }
500        if secs.is_sign_negative() {
501            st = SystemTime::UNIX_EPOCH.checked_sub(duration);
502        }
503
504        st.map(Self::At).ok_or(err_info)
505    }
506}
507
508/// EvalStmt holds an expression and information on the range it should
509/// be evaluated on.
510#[allow(rustdoc::broken_intra_doc_links)]
511#[derive(Debug, Clone)]
512pub struct EvalStmt {
513    /// Expression to be evaluated.
514    pub expr: Expr,
515
516    /// The time boundaries for the evaluation. If start equals end an instant
517    /// is evaluated.
518    pub start: SystemTime,
519    pub end: SystemTime,
520    /// Time between two evaluated instants for the range [start:end].
521    pub interval: Duration,
522    /// Lookback delta to use for this evaluation.
523    pub lookback_delta: Duration,
524}
525
526impl fmt::Display for EvalStmt {
527    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
528        write!(
529            f,
530            "[{}] @ [{}, {}, {}, {}]",
531            self.expr,
532            DateTime::<Utc>::from(self.start).to_rfc3339(),
533            DateTime::<Utc>::from(self.end).to_rfc3339(),
534            display_duration(&self.interval),
535            display_duration(&self.lookback_delta)
536        )
537    }
538}
539
540/// Grammar:
541/// ``` norust
542/// <aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)
543/// <aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
544/// ```
545///
546/// parameter is only required for `count_values`, `quantile`, `topk` and `bottomk`.
547#[derive(Debug, Clone, PartialEq)]
548#[cfg_attr(feature = "ser", derive(serde::Serialize))]
549pub struct AggregateExpr {
550    /// The used aggregation operation.
551    pub op: TokenType,
552    /// The Vector expression over which is aggregated.
553    pub expr: Box<Expr>,
554    /// Parameter used by some aggregators.
555    pub param: Option<Box<Expr>>,
556    /// modifier is optional for some aggregation operators, like sum.
557    #[cfg_attr(feature = "ser", serde(flatten))]
558    #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_grouping"))]
559    pub modifier: Option<LabelModifier>,
560}
561
562impl AggregateExpr {
563    fn get_op_string(&self) -> String {
564        let mut s = self.op.to_string();
565
566        if let Some(modifier) = &self.modifier {
567            match modifier {
568                LabelModifier::Exclude(ls) => write!(s, " without ({ls}) ").unwrap(),
569                LabelModifier::Include(ls) if !ls.is_empty() => write!(s, " by ({ls}) ").unwrap(),
570                _ => (),
571            }
572        }
573        s
574    }
575}
576
577impl fmt::Display for AggregateExpr {
578    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579        write!(f, "{}", self.get_op_string())?;
580
581        write!(f, "(")?;
582        if let Some(param) = &self.param {
583            write!(f, "{param}, ")?;
584        }
585        write!(f, "{})", self.expr)?;
586
587        Ok(())
588    }
589}
590
591impl Prettier for AggregateExpr {
592    fn format(&self, level: usize, max: usize) -> String {
593        let mut s = format!("{}{}(\n", indent(level), self.get_op_string());
594        if let Some(param) = &self.param {
595            writeln!(s, "{},", param.pretty(level + 1, max)).unwrap();
596        }
597        writeln!(s, "{}", self.expr.pretty(level + 1, max)).unwrap();
598        write!(s, "{})", indent(level)).unwrap();
599        s
600    }
601}
602
603/// UnaryExpr will negate the expr
604#[derive(Debug, Clone, PartialEq)]
605pub struct UnaryExpr {
606    pub expr: Box<Expr>,
607}
608
609impl fmt::Display for UnaryExpr {
610    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
611        write!(f, "-{}", self.expr)
612    }
613}
614
615impl Prettier for UnaryExpr {
616    fn pretty(&self, level: usize, max: usize) -> String {
617        format!(
618            "{}-{}",
619            indent(level),
620            self.expr.pretty(level, max).trim_start()
621        )
622    }
623}
624
625#[cfg(feature = "ser")]
626impl serde::Serialize for UnaryExpr {
627    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
628    where
629        S: serde::Serializer,
630    {
631        use serde::ser::SerializeMap;
632        let mut map = serializer.serialize_map(Some(2))?;
633        map.serialize_entry("op", "-")?;
634        map.serialize_entry("expr", &self.expr)?;
635
636        map.end()
637    }
638}
639
640/// Grammar:
641/// ``` norust
642/// <vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
643/// <vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
644/// <vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
645/// <vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
646/// ```
647#[derive(Debug, Clone, PartialEq)]
648#[cfg_attr(feature = "ser", derive(serde::Serialize))]
649pub struct BinaryExpr {
650    /// The operation of the expression.
651    pub op: TokenType,
652    /// The operands on the left sides of the operator.
653    pub lhs: Box<Expr>,
654    /// The operands on the right sides of the operator.
655    pub rhs: Box<Expr>,
656    #[cfg_attr(feature = "ser", serde(flatten))]
657    #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_bin_modifier"))]
658    pub modifier: Option<BinModifier>,
659}
660
661impl BinaryExpr {
662    pub fn is_matching_on(&self) -> bool {
663        matches!(&self.modifier, Some(modifier) if modifier.is_matching_on())
664    }
665
666    pub fn is_matching_labels_not_empty(&self) -> bool {
667        matches!(&self.modifier, Some(modifier) if modifier.is_matching_labels_not_empty())
668    }
669
670    pub fn return_bool(&self) -> bool {
671        matches!(&self.modifier, Some(modifier) if modifier.return_bool)
672    }
673
674    /// check if labels of card and matching are joint
675    pub fn is_labels_joint(&self) -> bool {
676        matches!(&self.modifier, Some(modifier) if modifier.is_labels_joint())
677    }
678
679    /// intersect labels of card and matching
680    pub fn intersect_labels(&self) -> Option<Vec<String>> {
681        self.modifier
682            .as_ref()
683            .and_then(|modifier| modifier.intersect_labels())
684    }
685
686    fn get_op_matching_string(&self) -> String {
687        match &self.modifier {
688            Some(modifier) => format!("{}{modifier}", self.op),
689            None => self.op.to_string(),
690        }
691    }
692}
693
694impl fmt::Display for BinaryExpr {
695    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
696        write!(
697            f,
698            "{} {} {}",
699            self.lhs,
700            self.get_op_matching_string(),
701            self.rhs
702        )
703    }
704}
705
706impl Prettier for BinaryExpr {
707    fn format(&self, level: usize, max: usize) -> String {
708        format!(
709            "{}\n{}{}\n{}",
710            self.lhs.pretty(level + 1, max),
711            indent(level),
712            self.get_op_matching_string(),
713            self.rhs.pretty(level + 1, max)
714        )
715    }
716}
717
718#[derive(Debug, Clone, PartialEq)]
719#[cfg_attr(feature = "ser", derive(serde::Serialize))]
720pub struct ParenExpr {
721    pub expr: Box<Expr>,
722}
723
724impl fmt::Display for ParenExpr {
725    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
726        write!(f, "({})", self.expr)
727    }
728}
729
730impl Prettier for ParenExpr {
731    fn format(&self, level: usize, max: usize) -> String {
732        format!(
733            "{}(\n{}\n{})",
734            indent(level),
735            self.expr.pretty(level + 1, max),
736            indent(level)
737        )
738    }
739}
740
741/// Grammar:
742/// ```norust
743/// <instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]
744/// ```
745#[derive(Debug, Clone, PartialEq)]
746#[cfg_attr(feature = "ser", derive(serde::Serialize))]
747pub struct SubqueryExpr {
748    pub expr: Box<Expr>,
749    #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
750    pub offset: Option<Offset>,
751    #[cfg_attr(feature = "ser", serde(flatten))]
752    #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
753    pub at: Option<AtModifier>,
754    #[cfg_attr(
755        feature = "ser",
756        serde(serialize_with = "crate::util::duration::serialize_duration")
757    )]
758    pub range: Duration,
759    /// Default is the global evaluation interval.
760    #[cfg_attr(
761        feature = "ser",
762        serde(serialize_with = "crate::util::duration::serialize_duration_opt")
763    )]
764    pub step: Option<Duration>,
765}
766
767impl SubqueryExpr {
768    fn get_time_suffix_string(&self) -> String {
769        let step = match &self.step {
770            Some(step) => display_duration(step),
771            None => String::from(""),
772        };
773        let range = display_duration(&self.range);
774
775        let mut s = format!("[{range}:{step}]");
776
777        if let Some(at) = &self.at {
778            write!(s, " {at}").unwrap();
779        }
780
781        if let Some(offset) = &self.offset {
782            write!(s, " offset {offset}").unwrap();
783        }
784        s
785    }
786}
787
788impl fmt::Display for SubqueryExpr {
789    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790        write!(f, "{}{}", self.expr, self.get_time_suffix_string())
791    }
792}
793
794impl Prettier for SubqueryExpr {
795    fn pretty(&self, level: usize, max: usize) -> String {
796        format!(
797            "{}{}",
798            self.expr.pretty(level, max),
799            self.get_time_suffix_string()
800        )
801    }
802}
803
804#[derive(Debug, Clone)]
805pub struct NumberLiteral {
806    pub val: f64,
807}
808
809impl NumberLiteral {
810    pub fn new(val: f64) -> Self {
811        Self { val }
812    }
813}
814
815impl PartialEq for NumberLiteral {
816    fn eq(&self, other: &Self) -> bool {
817        self.val == other.val || self.val.is_nan() && other.val.is_nan()
818    }
819}
820
821impl Eq for NumberLiteral {}
822
823impl Neg for NumberLiteral {
824    type Output = Self;
825
826    fn neg(self) -> Self::Output {
827        NumberLiteral { val: -self.val }
828    }
829}
830
831impl fmt::Display for NumberLiteral {
832    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
833        if self.val == f64::INFINITY {
834            write!(f, "Inf")
835        } else if self.val == f64::NEG_INFINITY {
836            write!(f, "-Inf")
837        } else if f64::is_nan(self.val) {
838            write!(f, "NaN")
839        } else {
840            write!(f, "{}", self.val)
841        }
842    }
843}
844
845#[cfg(feature = "ser")]
846impl serde::Serialize for NumberLiteral {
847    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
848    where
849        S: serde::Serializer,
850    {
851        use serde::ser::SerializeMap;
852        let mut map = serializer.serialize_map(Some(1))?;
853        map.serialize_entry("val", &self.to_string())?;
854
855        map.end()
856    }
857}
858
859impl Prettier for NumberLiteral {
860    fn needs_split(&self, _max: usize) -> bool {
861        false
862    }
863}
864
865#[derive(Debug, Clone, PartialEq)]
866#[cfg_attr(feature = "ser", derive(serde::Serialize))]
867pub struct StringLiteral {
868    pub val: String,
869}
870
871impl fmt::Display for StringLiteral {
872    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
873        write!(f, "\"{}\"", self.val)
874    }
875}
876
877impl Prettier for StringLiteral {
878    fn needs_split(&self, _max: usize) -> bool {
879        false
880    }
881}
882
883#[derive(Debug, Clone, PartialEq)]
884#[cfg_attr(feature = "ser", derive(serde::Serialize))]
885pub struct VectorSelector {
886    pub name: Option<String>,
887    #[cfg_attr(feature = "ser", serde(flatten))]
888    pub matchers: Matchers,
889    #[cfg_attr(feature = "ser", serde(serialize_with = "Offset::serialize_offset"))]
890    pub offset: Option<Offset>,
891    #[cfg_attr(feature = "ser", serde(flatten))]
892    #[cfg_attr(feature = "ser", serde(serialize_with = "serialize_at_modifier"))]
893    pub at: Option<AtModifier>,
894}
895
896impl VectorSelector {
897    pub fn new(name: Option<String>, matchers: Matchers) -> Self {
898        VectorSelector {
899            name,
900            matchers,
901            offset: None,
902            at: None,
903        }
904    }
905}
906
907impl Default for VectorSelector {
908    fn default() -> Self {
909        Self {
910            name: None,
911            matchers: Matchers::empty(),
912            offset: None,
913            at: None,
914        }
915    }
916}
917
918impl From<String> for VectorSelector {
919    fn from(name: String) -> Self {
920        VectorSelector {
921            name: Some(name),
922            offset: None,
923            at: None,
924            matchers: Matchers::empty(),
925        }
926    }
927}
928
929/// directly create an instant vector with only METRIC_NAME matcher.
930///
931/// # Examples
932///
933/// Basic usage:
934///
935/// ``` rust
936/// use promql_parser::label::Matchers;
937/// use promql_parser::parser::VectorSelector;
938///
939/// let vs = VectorSelector {
940///     name: Some(String::from("foo")),
941///     offset: None,
942///     at: None,
943///     matchers: Matchers::empty(),
944/// };
945///
946/// assert_eq!(VectorSelector::from("foo"), vs);
947/// ```
948impl From<&str> for VectorSelector {
949    fn from(name: &str) -> Self {
950        VectorSelector::from(name.to_string())
951    }
952}
953
954impl Neg for VectorSelector {
955    type Output = UnaryExpr;
956
957    fn neg(self) -> Self::Output {
958        let ex = Expr::VectorSelector(self);
959        UnaryExpr { expr: Box::new(ex) }
960    }
961}
962
963impl fmt::Display for VectorSelector {
964    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
965        if let Some(name) = &self.name {
966            write!(f, "{name}")?;
967        }
968        let matchers = &self.matchers.to_string();
969        if !matchers.is_empty() {
970            write!(f, "{{{matchers}}}")?;
971        }
972        if let Some(at) = &self.at {
973            write!(f, " {at}")?;
974        }
975        if let Some(offset) = &self.offset {
976            write!(f, " offset {offset}")?;
977        }
978        Ok(())
979    }
980}
981
982impl Prettier for VectorSelector {
983    fn needs_split(&self, _max: usize) -> bool {
984        false
985    }
986}
987
988#[derive(Debug, Clone, PartialEq)]
989#[cfg_attr(feature = "ser", derive(serde::Serialize))]
990pub struct MatrixSelector {
991    #[cfg_attr(feature = "ser", serde(flatten))]
992    pub vs: VectorSelector,
993    #[cfg_attr(
994        feature = "ser",
995        serde(serialize_with = "crate::util::duration::serialize_duration")
996    )]
997    pub range: Duration,
998}
999
1000impl fmt::Display for MatrixSelector {
1001    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1002        if let Some(name) = &self.vs.name {
1003            write!(f, "{name}")?;
1004        }
1005
1006        let matchers = &self.vs.matchers.to_string();
1007        if !matchers.is_empty() {
1008            write!(f, "{{{matchers}}}")?;
1009        }
1010
1011        write!(f, "[{}]", display_duration(&self.range))?;
1012
1013        if let Some(at) = &self.vs.at {
1014            write!(f, " {at}")?;
1015        }
1016
1017        if let Some(offset) = &self.vs.offset {
1018            write!(f, " offset {offset}")?;
1019        }
1020
1021        Ok(())
1022    }
1023}
1024
1025impl Prettier for MatrixSelector {
1026    fn needs_split(&self, _max: usize) -> bool {
1027        false
1028    }
1029}
1030
1031/// Call represents Prometheus Function.
1032/// Some functions have special cases:
1033///
1034/// ## exp
1035///
1036/// exp(v instant-vector) calculates the exponential function for all elements in v.
1037/// Special cases are:
1038///
1039/// ```promql
1040/// Exp(+Inf) = +Inf
1041/// Exp(NaN) = NaN
1042/// ```
1043///
1044/// ## ln
1045///
1046/// ln(v instant-vector) calculates the natural logarithm for all elements in v.
1047/// Special cases are:
1048///
1049/// ```promql
1050/// ln(+Inf) = +Inf
1051/// ln(0) = -Inf
1052/// ln(x < 0) = NaN
1053/// ln(NaN) = NaN
1054/// ```
1055///
1056/// TODO: support more special cases of function call
1057///
1058///  - acos()
1059///  - acosh()
1060///  - asin()
1061///  - asinh()
1062///  - atan()
1063///  - atanh()
1064///  - cos()
1065///  - cosh()
1066///  - sin()
1067///  - sinh()
1068///  - tan()
1069///  - tanh()
1070#[derive(Debug, Clone, PartialEq)]
1071#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1072pub struct Call {
1073    pub func: Function,
1074    #[cfg_attr(feature = "ser", serde(flatten))]
1075    pub args: FunctionArgs,
1076}
1077
1078impl fmt::Display for Call {
1079    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1080        write!(f, "{}({})", self.func.name, self.args)
1081    }
1082}
1083
1084impl Prettier for Call {
1085    fn format(&self, level: usize, max: usize) -> String {
1086        format!(
1087            "{}{}(\n{}\n{})",
1088            indent(level),
1089            self.func.name,
1090            self.args.pretty(level + 1, max),
1091            indent(level)
1092        )
1093    }
1094}
1095
1096/// Node for extending the AST. [Extension] won't be generate by this parser itself.
1097#[derive(Debug, Clone)]
1098pub struct Extension {
1099    pub expr: Arc<dyn ExtensionExpr>,
1100}
1101
1102/// The interface for extending the AST with custom expression node.
1103pub trait ExtensionExpr: std::fmt::Debug + Send + Sync {
1104    fn as_any(&self) -> &dyn std::any::Any;
1105
1106    fn name(&self) -> &str;
1107
1108    fn value_type(&self) -> ValueType;
1109
1110    fn children(&self) -> &[Expr];
1111
1112    fn with_new_children(&self, children: Vec<Expr>) -> Arc<dyn ExtensionExpr>;
1113}
1114
1115impl PartialEq for Extension {
1116    fn eq(&self, other: &Self) -> bool {
1117        format!("{self:?}") == format!("{other:?}")
1118    }
1119}
1120
1121impl Eq for Extension {}
1122
1123#[derive(Debug, Clone, PartialEq)]
1124#[cfg_attr(feature = "ser", derive(serde::Serialize))]
1125#[cfg_attr(feature = "ser", serde(tag = "type", rename_all = "camelCase"))]
1126pub enum Expr {
1127    /// Aggregate represents an aggregation operation on a Vector.
1128    #[cfg_attr(feature = "ser", serde(rename = "aggregation"))]
1129    Aggregate(AggregateExpr),
1130
1131    /// Unary represents a unary operation on another expression.
1132    /// Currently unary operations are only supported for Scalars.
1133    #[cfg_attr(feature = "ser", serde(rename = "unaryExpr"))]
1134    Unary(UnaryExpr),
1135
1136    /// Binary represents a binary expression between two child expressions.
1137    #[cfg_attr(feature = "ser", serde(rename = "binaryExpr"))]
1138    Binary(BinaryExpr),
1139
1140    /// Paren wraps an expression so it cannot be disassembled as a consequence
1141    /// of operator precedence.
1142    #[cfg_attr(feature = "ser", serde(rename = "parenExpr"))]
1143    Paren(ParenExpr),
1144
1145    /// SubqueryExpr represents a subquery.
1146    Subquery(SubqueryExpr),
1147
1148    /// NumberLiteral represents a number.
1149    NumberLiteral(NumberLiteral),
1150
1151    /// StringLiteral represents a string.
1152    StringLiteral(StringLiteral),
1153
1154    /// VectorSelector represents a Vector selection.
1155    VectorSelector(VectorSelector),
1156
1157    /// MatrixSelector represents a Matrix selection.
1158    MatrixSelector(MatrixSelector),
1159
1160    /// Call represents a function call.
1161    Call(Call),
1162
1163    /// Extension represents an extension expression. It is for user to attach additional
1164    /// information to the AST. This parser won't generate Extension node.
1165    #[cfg_attr(feature = "ser", serde(skip))]
1166    Extension(Extension),
1167}
1168
1169impl Expr {
1170    pub(crate) fn new_vector_selector(
1171        name: Option<String>,
1172        matchers: Matchers,
1173    ) -> Result<Self, String> {
1174        let vs = VectorSelector::new(name, matchers);
1175        Ok(Self::VectorSelector(vs))
1176    }
1177
1178    pub(crate) fn new_unary_expr(expr: Expr) -> Result<Self, String> {
1179        match expr {
1180            Expr::StringLiteral(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: string".into()),
1181            Expr::MatrixSelector(_) => Err("unary expression only allowed on expressions of type scalar or vector, got: matrix".into()),
1182            _ => Ok(-expr),
1183        }
1184    }
1185
1186    pub(crate) fn new_subquery_expr(
1187        expr: Expr,
1188        range: Duration,
1189        step: Option<Duration>,
1190    ) -> Result<Self, String> {
1191        let se = Expr::Subquery(SubqueryExpr {
1192            expr: Box::new(expr),
1193            offset: None,
1194            at: None,
1195            range,
1196            step,
1197        });
1198        Ok(se)
1199    }
1200
1201    pub(crate) fn new_paren_expr(expr: Expr) -> Result<Self, String> {
1202        let ex = Expr::Paren(ParenExpr {
1203            expr: Box::new(expr),
1204        });
1205        Ok(ex)
1206    }
1207
1208    /// NOTE: @ and offset is not set here.
1209    pub(crate) fn new_matrix_selector(expr: Expr, range: Duration) -> Result<Self, String> {
1210        match expr {
1211            Expr::VectorSelector(VectorSelector {
1212                offset: Some(_), ..
1213            }) => Err("no offset modifiers allowed before range".into()),
1214            Expr::VectorSelector(VectorSelector { at: Some(_), .. }) => {
1215                Err("no @ modifiers allowed before range".into())
1216            }
1217            Expr::VectorSelector(vs) => {
1218                let ms = Expr::MatrixSelector(MatrixSelector { vs, range });
1219                Ok(ms)
1220            }
1221            _ => Err("ranges only allowed for vector selectors".into()),
1222        }
1223    }
1224
1225    pub(crate) fn at_expr(self, at: AtModifier) -> Result<Self, String> {
1226        let already_set_err = Err("@ <timestamp> may not be set multiple times".into());
1227        match self {
1228            Expr::VectorSelector(mut vs) => match vs.at {
1229                None => {
1230                    vs.at = Some(at);
1231                    Ok(Expr::VectorSelector(vs))
1232                }
1233                Some(_) => already_set_err,
1234            },
1235            Expr::MatrixSelector(mut ms) => match ms.vs.at {
1236                None => {
1237                    ms.vs.at = Some(at);
1238                    Ok(Expr::MatrixSelector(ms))
1239                }
1240                Some(_) => already_set_err,
1241            },
1242            Expr::Subquery(mut s) => match s.at {
1243                None => {
1244                    s.at = Some(at);
1245                    Ok(Expr::Subquery(s))
1246                }
1247                Some(_) => already_set_err,
1248            },
1249            _ => {
1250                Err("@ modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1251            }
1252        }
1253    }
1254
1255    /// set offset field for specified Expr, but CAN ONLY be set once.
1256    pub(crate) fn offset_expr(self, offset: Offset) -> Result<Self, String> {
1257        let already_set_err = Err("offset may not be set multiple times".into());
1258        match self {
1259            Expr::VectorSelector(mut vs) => match vs.offset {
1260                None => {
1261                    vs.offset = Some(offset);
1262                    Ok(Expr::VectorSelector(vs))
1263                }
1264                Some(_) => already_set_err,
1265            },
1266            Expr::MatrixSelector(mut ms) => match ms.vs.offset {
1267                None => {
1268                    ms.vs.offset = Some(offset);
1269                    Ok(Expr::MatrixSelector(ms))
1270                }
1271                Some(_) => already_set_err,
1272            },
1273            Expr::Subquery(mut s) => match s.offset {
1274                None => {
1275                    s.offset = Some(offset);
1276                    Ok(Expr::Subquery(s))
1277                }
1278                Some(_) => already_set_err,
1279            },
1280            _ => {
1281                Err("offset modifier must be preceded by an vector selector or matrix selector or a subquery".into())
1282            }
1283        }
1284    }
1285
1286    pub(crate) fn new_call(func: Function, args: FunctionArgs) -> Result<Expr, String> {
1287        Ok(Expr::Call(Call { func, args }))
1288    }
1289
1290    pub(crate) fn new_binary_expr(
1291        lhs: Expr,
1292        op: TokenId,
1293        modifier: Option<BinModifier>,
1294        rhs: Expr,
1295    ) -> Result<Expr, String> {
1296        let ex = BinaryExpr {
1297            op: TokenType::new(op),
1298            lhs: Box::new(lhs),
1299            rhs: Box::new(rhs),
1300            modifier,
1301        };
1302        Ok(Expr::Binary(ex))
1303    }
1304
1305    pub(crate) fn new_aggregate_expr(
1306        op: TokenId,
1307        modifier: Option<LabelModifier>,
1308        args: FunctionArgs,
1309    ) -> Result<Expr, String> {
1310        let op = TokenType::new(op);
1311        if args.is_empty() {
1312            return Err(format!(
1313                "no arguments for aggregate expression '{op}' provided"
1314            ));
1315        }
1316        let mut desired_args_count = 1;
1317        let mut param = None;
1318        if op.is_aggregator_with_param() {
1319            desired_args_count = 2;
1320            param = args.first();
1321        }
1322        if args.len() != desired_args_count {
1323            return Err(format!(
1324                "wrong number of arguments for aggregate expression provided, expected {}, got {}",
1325                desired_args_count,
1326                args.len()
1327            ));
1328        }
1329
1330        match args.last() {
1331            Some(expr) => Ok(Expr::Aggregate(AggregateExpr {
1332                op,
1333                expr,
1334                param,
1335                modifier,
1336            })),
1337            None => Err(
1338                "aggregate operation needs a single instant vector parameter, but found none"
1339                    .into(),
1340            ),
1341        }
1342    }
1343
1344    pub fn value_type(&self) -> ValueType {
1345        match self {
1346            Expr::Aggregate(_) => ValueType::Vector,
1347            Expr::Unary(ex) => ex.expr.value_type(),
1348            Expr::Binary(ex) => {
1349                if ex.lhs.value_type() == ValueType::Scalar
1350                    && ex.rhs.value_type() == ValueType::Scalar
1351                {
1352                    ValueType::Scalar
1353                } else {
1354                    ValueType::Vector
1355                }
1356            }
1357            Expr::Paren(ex) => ex.expr.value_type(),
1358            Expr::Subquery(_) => ValueType::Matrix,
1359            Expr::NumberLiteral(_) => ValueType::Scalar,
1360            Expr::StringLiteral(_) => ValueType::String,
1361            Expr::VectorSelector(_) => ValueType::Vector,
1362            Expr::MatrixSelector(_) => ValueType::Matrix,
1363            Expr::Call(ex) => ex.func.return_type,
1364            Expr::Extension(ex) => ex.expr.value_type(),
1365        }
1366    }
1367
1368    /// only Some if expr is [Expr::NumberLiteral]
1369    pub(crate) fn scalar_value(&self) -> Option<f64> {
1370        match self {
1371            Expr::NumberLiteral(nl) => Some(nl.val),
1372            _ => None,
1373        }
1374    }
1375
1376    pub fn prettify(&self) -> String {
1377        self.pretty(0, MAX_CHARACTERS_PER_LINE)
1378    }
1379}
1380
1381impl From<String> for Expr {
1382    fn from(val: String) -> Self {
1383        Expr::StringLiteral(StringLiteral { val })
1384    }
1385}
1386
1387impl From<&str> for Expr {
1388    fn from(s: &str) -> Self {
1389        Expr::StringLiteral(StringLiteral { val: s.into() })
1390    }
1391}
1392
1393impl From<f64> for Expr {
1394    fn from(val: f64) -> Self {
1395        Expr::NumberLiteral(NumberLiteral { val })
1396    }
1397}
1398
1399/// directly create an Expr::VectorSelector from instant vector
1400///
1401/// # Examples
1402///
1403/// Basic usage:
1404///
1405/// ``` rust
1406/// use promql_parser::label::Matchers;
1407/// use promql_parser::parser::{Expr, VectorSelector};
1408///
1409/// let name = String::from("foo");
1410/// let vs = VectorSelector::new(Some(name), Matchers::empty());
1411///
1412/// assert_eq!(Expr::VectorSelector(vs), Expr::from(VectorSelector::from("foo")));
1413/// ```
1414impl From<VectorSelector> for Expr {
1415    fn from(vs: VectorSelector) -> Self {
1416        Expr::VectorSelector(vs)
1417    }
1418}
1419
1420impl Neg for Expr {
1421    type Output = Self;
1422
1423    fn neg(self) -> Self::Output {
1424        match self {
1425            Expr::NumberLiteral(nl) => Expr::NumberLiteral(-nl),
1426            _ => Expr::Unary(UnaryExpr {
1427                expr: Box::new(self),
1428            }),
1429        }
1430    }
1431}
1432
1433impl fmt::Display for Expr {
1434    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1435        match self {
1436            Expr::Aggregate(ex) => write!(f, "{ex}"),
1437            Expr::Unary(ex) => write!(f, "{ex}"),
1438            Expr::Binary(ex) => write!(f, "{ex}"),
1439            Expr::Paren(ex) => write!(f, "{ex}"),
1440            Expr::Subquery(ex) => write!(f, "{ex}"),
1441            Expr::NumberLiteral(ex) => write!(f, "{ex}"),
1442            Expr::StringLiteral(ex) => write!(f, "{ex}"),
1443            Expr::VectorSelector(ex) => write!(f, "{ex}"),
1444            Expr::MatrixSelector(ex) => write!(f, "{ex}"),
1445            Expr::Call(ex) => write!(f, "{ex}"),
1446            Expr::Extension(ext) => write!(f, "{ext:?}"),
1447        }
1448    }
1449}
1450
1451impl Prettier for Expr {
1452    fn pretty(&self, level: usize, max: usize) -> String {
1453        match self {
1454            Expr::Aggregate(ex) => ex.pretty(level, max),
1455            Expr::Unary(ex) => ex.pretty(level, max),
1456            Expr::Binary(ex) => ex.pretty(level, max),
1457            Expr::Paren(ex) => ex.pretty(level, max),
1458            Expr::Subquery(ex) => ex.pretty(level, max),
1459            Expr::NumberLiteral(ex) => ex.pretty(level, max),
1460            Expr::StringLiteral(ex) => ex.pretty(level, max),
1461            Expr::VectorSelector(ex) => ex.pretty(level, max),
1462            Expr::MatrixSelector(ex) => ex.pretty(level, max),
1463            Expr::Call(ex) => ex.pretty(level, max),
1464            Expr::Extension(ext) => format!("{ext:?}"),
1465        }
1466    }
1467}
1468
1469/// check_ast checks the validity of the provided AST. This includes type checking.
1470/// Recursively check correct typing for child nodes and raise errors in case of bad typing.
1471pub(crate) fn check_ast(expr: Expr) -> Result<Expr, String> {
1472    match expr {
1473        Expr::Binary(ex) => check_ast_for_binary_expr(ex),
1474        Expr::Aggregate(ex) => check_ast_for_aggregate_expr(ex),
1475        Expr::Call(ex) => check_ast_for_call(ex),
1476        Expr::Unary(ex) => check_ast_for_unary(ex),
1477        Expr::Subquery(ex) => check_ast_for_subquery(ex),
1478        Expr::VectorSelector(ex) => check_ast_for_vector_selector(ex),
1479        Expr::Paren(_) => Ok(expr),
1480        Expr::NumberLiteral(_) => Ok(expr),
1481        Expr::StringLiteral(_) => Ok(expr),
1482        Expr::MatrixSelector(_) => Ok(expr),
1483        Expr::Extension(_) => Ok(expr),
1484    }
1485}
1486
1487fn expect_type(
1488    expected: ValueType,
1489    actual: Option<ValueType>,
1490    context: &str,
1491) -> Result<bool, String> {
1492    match actual {
1493        Some(actual) => {
1494            if actual == expected {
1495                Ok(true)
1496            } else {
1497                Err(format!(
1498                    "expected type {expected} in {context}, got {actual}"
1499                ))
1500            }
1501        }
1502        None => Err(format!("expected type {expected} in {context}, got None")),
1503    }
1504}
1505
1506/// the original logic is redundant in prometheus, and the following coding blocks
1507/// have been optimized for readability, but all logic SHOULD be covered.
1508fn check_ast_for_binary_expr(mut ex: BinaryExpr) -> Result<Expr, String> {
1509    if !ex.op.is_operator() {
1510        return Err(format!(
1511            "binary expression does not support operator '{}'",
1512            ex.op
1513        ));
1514    }
1515
1516    if ex.return_bool() && !ex.op.is_comparison_operator() {
1517        return Err("bool modifier can only be used on comparison operators".into());
1518    }
1519
1520    if ex.op.is_comparison_operator()
1521        && ex.lhs.value_type() == ValueType::Scalar
1522        && ex.rhs.value_type() == ValueType::Scalar
1523        && !ex.return_bool()
1524    {
1525        return Err("comparisons between scalars must use BOOL modifier".into());
1526    }
1527
1528    // For `on` matching, a label can only appear in one of the lists.
1529    // Every time series of the result vector must be uniquely identifiable.
1530    if ex.is_matching_on() && ex.is_labels_joint() {
1531        if let Some(labels) = ex.intersect_labels() {
1532            if let Some(label) = labels.first() {
1533                return Err(format!(
1534                    "label '{label}' must not occur in ON and GROUP clause at once"
1535                ));
1536            }
1537        };
1538    }
1539
1540    if ex.op.is_set_operator() {
1541        if ex.lhs.value_type() == ValueType::Scalar || ex.rhs.value_type() == ValueType::Scalar {
1542            return Err(format!(
1543                "set operator '{}' not allowed in binary scalar expression",
1544                ex.op
1545            ));
1546        }
1547
1548        if ex.lhs.value_type() == ValueType::Vector && ex.rhs.value_type() == ValueType::Vector {
1549            if let Some(ref modifier) = ex.modifier {
1550                if matches!(modifier.card, VectorMatchCardinality::OneToMany(_))
1551                    || matches!(modifier.card, VectorMatchCardinality::ManyToOne(_))
1552                {
1553                    return Err(format!("no grouping allowed for '{}' operation", ex.op));
1554                }
1555            };
1556        }
1557
1558        match &mut ex.modifier {
1559            Some(modifier) => {
1560                if modifier.card == VectorMatchCardinality::OneToOne {
1561                    modifier.card = VectorMatchCardinality::ManyToMany;
1562                }
1563            }
1564            None => {
1565                ex.modifier =
1566                    Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany));
1567            }
1568        }
1569    }
1570
1571    if ex.lhs.value_type() != ValueType::Scalar && ex.lhs.value_type() != ValueType::Vector {
1572        return Err("binary expression must contain only scalar and instant vector types".into());
1573    }
1574    if ex.rhs.value_type() != ValueType::Scalar && ex.rhs.value_type() != ValueType::Vector {
1575        return Err("binary expression must contain only scalar and instant vector types".into());
1576    }
1577
1578    if (ex.lhs.value_type() != ValueType::Vector || ex.rhs.value_type() != ValueType::Vector)
1579        && ex.is_matching_labels_not_empty()
1580    {
1581        return Err("vector matching only allowed between vectors".into());
1582    }
1583
1584    Ok(Expr::Binary(ex))
1585}
1586
1587fn check_ast_for_aggregate_expr(ex: AggregateExpr) -> Result<Expr, String> {
1588    if !ex.op.is_aggregator() {
1589        return Err(format!(
1590            "aggregation operator expected in aggregation expression but got '{}'",
1591            ex.op
1592        ));
1593    }
1594
1595    expect_type(
1596        ValueType::Vector,
1597        Some(ex.expr.value_type()),
1598        "aggregation expression",
1599    )?;
1600
1601    if matches!(ex.op.id(), T_TOPK | T_BOTTOMK | T_QUANTILE) {
1602        expect_type(
1603            ValueType::Scalar,
1604            ex.param.as_ref().map(|ex| ex.value_type()),
1605            "aggregation expression",
1606        )?;
1607    }
1608
1609    if ex.op.id() == T_COUNT_VALUES {
1610        expect_type(
1611            ValueType::String,
1612            ex.param.as_ref().map(|ex| ex.value_type()),
1613            "aggregation expression",
1614        )?;
1615    }
1616
1617    Ok(Expr::Aggregate(ex))
1618}
1619
1620fn check_ast_for_call(ex: Call) -> Result<Expr, String> {
1621    let expected_args_len = ex.func.arg_types.len();
1622    let name = ex.func.name;
1623    let actual_args_len = ex.args.len();
1624
1625    if ex.func.variadic == 0 {
1626        if expected_args_len != actual_args_len {
1627            return Err(format!(
1628                "expected {expected_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1629            ));
1630        }
1631    } else {
1632        let expected_args_len_without_default = expected_args_len.saturating_sub(1);
1633        if expected_args_len_without_default > actual_args_len {
1634            return Err(format!(
1635                "expected at least {expected_args_len_without_default} argument(s) in call to '{name}', got {actual_args_len}"
1636            ));
1637        }
1638
1639        if ex.func.variadic > 0 {
1640            let expected_max_args_len =
1641                expected_args_len_without_default + ex.func.variadic as usize;
1642            if expected_max_args_len < actual_args_len {
1643                return Err(format!(
1644                    "expected at most {expected_max_args_len} argument(s) in call to '{name}', got {actual_args_len}"
1645                ));
1646            }
1647        }
1648    }
1649
1650    // special cases from https://prometheus.io/docs/prometheus/latest/querying/functions
1651    if name.eq("exp") {
1652        if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1653            if val.is_nan() || val.is_infinite() {
1654                return Ok(Expr::Call(ex));
1655            }
1656        }
1657    } else if name.eq("ln") || name.eq("log2") || name.eq("log10") {
1658        if let Some(val) = ex.args.first().and_then(|ex| ex.scalar_value()) {
1659            if val.is_nan() || val.is_infinite() || val <= 0.0 {
1660                return Ok(Expr::Call(ex));
1661            }
1662        }
1663    }
1664
1665    for (mut idx, actual_arg) in ex.args.args.iter().enumerate() {
1666        // this only happens when function args are variadic
1667        if idx >= ex.func.arg_types.len() {
1668            idx = ex.func.arg_types.len() - 1;
1669        }
1670
1671        expect_type(
1672            ex.func.arg_types[idx],
1673            Some(actual_arg.value_type()),
1674            &format!("call to function '{name}'"),
1675        )?;
1676    }
1677
1678    Ok(Expr::Call(ex))
1679}
1680
1681fn check_ast_for_unary(ex: UnaryExpr) -> Result<Expr, String> {
1682    let value_type = ex.expr.value_type();
1683    if value_type != ValueType::Scalar && value_type != ValueType::Vector {
1684        return Err(format!(
1685            "unary expression only allowed on expressions of type scalar or vector, got {value_type}"
1686        ));
1687    }
1688
1689    Ok(Expr::Unary(ex))
1690}
1691
1692fn check_ast_for_subquery(ex: SubqueryExpr) -> Result<Expr, String> {
1693    let value_type = ex.expr.value_type();
1694    if value_type != ValueType::Vector {
1695        return Err(format!(
1696            "subquery is only allowed on vector, got {value_type} instead"
1697        ));
1698    }
1699
1700    Ok(Expr::Subquery(ex))
1701}
1702
1703fn check_ast_for_vector_selector(ex: VectorSelector) -> Result<Expr, String> {
1704    match ex.name {
1705        Some(ref name) => match ex.matchers.find_matcher_value(METRIC_NAME) {
1706            Some(val) => Err(format!(
1707                "metric name must not be set twice: '{name}' or '{val}'"
1708            )),
1709            None => Ok(Expr::VectorSelector(ex)),
1710        },
1711        None if ex.matchers.is_empty_matchers() => {
1712            // When name is None, a vector selector must contain at least one non-empty matcher
1713            // to prevent implicit selection of all metrics (e.g. by a typo).
1714            Err("vector selector must contain at least one non-empty matcher".into())
1715        }
1716        _ => Ok(Expr::VectorSelector(ex)),
1717    }
1718}
1719
1720#[cfg(test)]
1721mod tests {
1722    use super::*;
1723    use crate::label::{MatchOp, Matcher};
1724
1725    #[test]
1726    fn test_valid_at_modifier() {
1727        let cases = vec![
1728            // tuple: (seconds, elapsed milliseconds before or after UNIX_EPOCH)
1729            (0.0, 0),
1730            (1000.3, 1000300),    // after UNIX_EPOCH
1731            (1000.9, 1000900),    // after UNIX_EPOCH
1732            (1000.9991, 1000999), // after UNIX_EPOCH
1733            (1000.9999, 1001000), // after UNIX_EPOCH
1734            (-1000.3, 1000300),   // before UNIX_EPOCH
1735            (-1000.9, 1000900),   // before UNIX_EPOCH
1736        ];
1737
1738        for (secs, elapsed) in cases {
1739            match AtModifier::try_from(secs).unwrap() {
1740                AtModifier::At(st) => {
1741                    if secs.is_sign_positive() || secs == 0.0 {
1742                        assert_eq!(
1743                            elapsed,
1744                            st.duration_since(SystemTime::UNIX_EPOCH)
1745                                .unwrap()
1746                                .as_millis()
1747                        )
1748                    } else if secs.is_sign_negative() {
1749                        assert_eq!(
1750                            elapsed,
1751                            SystemTime::UNIX_EPOCH
1752                                .duration_since(st)
1753                                .unwrap()
1754                                .as_millis()
1755                        )
1756                    }
1757                }
1758                _ => panic!(),
1759            }
1760        }
1761
1762        assert_eq!(
1763            AtModifier::try_from(Expr::from(1.0)),
1764            AtModifier::try_from(1.0),
1765        );
1766    }
1767
1768    #[test]
1769    fn test_invalid_at_modifier() {
1770        let cases = vec![
1771            f64::MAX,
1772            f64::MIN,
1773            f64::NAN,
1774            f64::INFINITY,
1775            f64::NEG_INFINITY,
1776        ];
1777
1778        for secs in cases {
1779            assert!(AtModifier::try_from(secs).is_err())
1780        }
1781
1782        assert_eq!(
1783            AtModifier::try_from(token::T_ADD),
1784            Err("invalid @ modifier preprocessor '+', START or END is valid.".into())
1785        );
1786
1787        assert_eq!(
1788            AtModifier::try_from(Expr::from("string literal")),
1789            Err("invalid float value after @ modifier".into())
1790        );
1791    }
1792
1793    #[test]
1794    fn test_binary_labels() {
1795        assert_eq!(
1796            &Labels::new(vec!["foo", "bar"]),
1797            LabelModifier::Include(Labels::new(vec!["foo", "bar"])).labels()
1798        );
1799
1800        assert_eq!(
1801            &Labels::new(vec!["foo", "bar"]),
1802            LabelModifier::Exclude(Labels::new(vec!["foo", "bar"])).labels()
1803        );
1804
1805        assert_eq!(
1806            &Labels::new(vec!["foo", "bar"]),
1807            VectorMatchCardinality::OneToMany(Labels::new(vec!["foo", "bar"]))
1808                .labels()
1809                .unwrap()
1810        );
1811
1812        assert_eq!(
1813            &Labels::new(vec!["foo", "bar"]),
1814            VectorMatchCardinality::ManyToOne(Labels::new(vec!["foo", "bar"]))
1815                .labels()
1816                .unwrap()
1817        );
1818
1819        assert_eq!(VectorMatchCardinality::OneToOne.labels(), None);
1820        assert_eq!(VectorMatchCardinality::ManyToMany.labels(), None);
1821    }
1822
1823    #[test]
1824    fn test_neg() {
1825        assert_eq!(
1826            -VectorSelector::from("foo"),
1827            UnaryExpr {
1828                expr: Box::new(Expr::from(VectorSelector::from("foo")))
1829            }
1830        )
1831    }
1832
1833    #[test]
1834    fn test_scalar_value() {
1835        assert_eq!(Some(1.0), Expr::from(1.0).scalar_value());
1836        assert_eq!(None, Expr::from("1.0").scalar_value());
1837    }
1838
1839    #[test]
1840    fn test_at_expr() {
1841        assert_eq!(
1842            "@ <timestamp> may not be set multiple times",
1843            Expr::from(VectorSelector::from("foo"))
1844                .at_expr(AtModifier::try_from(1.0).unwrap())
1845                .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1846                .unwrap_err()
1847        );
1848
1849        assert_eq!(
1850            "@ <timestamp> may not be set multiple times",
1851            Expr::new_matrix_selector(
1852                Expr::from(VectorSelector::from("foo")),
1853                Duration::from_secs(1),
1854            )
1855            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1856            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1857            .unwrap_err()
1858        );
1859
1860        assert_eq!(
1861            "@ <timestamp> may not be set multiple times",
1862            Expr::new_subquery_expr(
1863                Expr::from(VectorSelector::from("foo")),
1864                Duration::from_secs(1),
1865                None,
1866            )
1867            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1868            .and_then(|ex| ex.at_expr(AtModifier::try_from(1.0).unwrap()))
1869            .unwrap_err()
1870        )
1871    }
1872
1873    #[test]
1874    fn test_offset_expr() {
1875        assert_eq!(
1876            "offset may not be set multiple times",
1877            Expr::from(VectorSelector::from("foo"))
1878                .offset_expr(Offset::Pos(Duration::from_secs(1000)))
1879                .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1880                .unwrap_err()
1881        );
1882
1883        assert_eq!(
1884            "offset may not be set multiple times",
1885            Expr::new_matrix_selector(
1886                Expr::from(VectorSelector::from("foo")),
1887                Duration::from_secs(1),
1888            )
1889            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1890            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1891            .unwrap_err()
1892        );
1893
1894        assert_eq!(
1895            "offset may not be set multiple times",
1896            Expr::new_subquery_expr(
1897                Expr::from(VectorSelector::from("foo")),
1898                Duration::from_secs(1),
1899                None,
1900            )
1901            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1902            .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1000))))
1903            .unwrap_err()
1904        );
1905    }
1906
1907    #[test]
1908    fn test_expr_to_string() {
1909        let mut cases = vec![
1910            ("1", "1"),
1911            ("- 1", "-1"),
1912            ("+ 1", "1"),
1913            ("Inf", "Inf"),
1914            ("inf", "Inf"),
1915            ("+Inf", "Inf"),
1916            ("- Inf", "-Inf"),
1917            (".5", "0.5"),
1918            ("5.", "5"),
1919            ("123.4567", "123.4567"),
1920            ("5e-3", "0.005"),
1921            ("5e3", "5000"),
1922            ("0xc", "12"),
1923            ("0755", "493"),
1924            ("08", "8"),
1925            ("+5.5e-3", "0.0055"),
1926            ("-0755", "-493"),
1927            ("NaN", "NaN"),
1928            ("NAN", "NaN"),
1929            ("- 1^2", "-1 ^ 2"),
1930            ("+1 + -2 * 1", "1 + -2 * 1"),
1931            ("1 + 2/(3*1)", "1 + 2 / (3 * 1)"),
1932            ("foo*sum", "foo * sum"),
1933            ("foo * on(test,blub) bar", "foo * on (test, blub) bar"),
1934            (
1935                r#"up{job="hi", instance="in"} offset 5m @ 100"#,
1936                r#"up{instance="in",job="hi"} @ 100.000 offset 5m"#,
1937            ),
1938            (
1939                r#"up{job="hi", instance="in"}"#,
1940                r#"up{instance="in",job="hi"}"#,
1941            ),
1942            ("sum (up) by (job,instance)", "sum by (job, instance) (up)"),
1943            (
1944                "foo / on(test,blub) group_left(bar) bar",
1945                "foo / on (test, blub) group_left (bar) bar",
1946            ),
1947            (
1948                "foo / on(test,blub) group_right(bar) bar",
1949                "foo / on (test, blub) group_right (bar) bar",
1950            ),
1951            (
1952                r#"foo{a="b",foo!="bar",test=~"test",bar!~"baz"}"#,
1953                r#"foo{a="b",bar!~"baz",foo!="bar",test=~"test"}"#,
1954            ),
1955            (
1956                r#"{__name__=~"foo.+",__name__=~".*bar"}"#,
1957                r#"{__name__=~".*bar",__name__=~"foo.+"}"#,
1958            ),
1959            (
1960                r#"test{a="b"}[5y] OFFSET 3d"#,
1961                r#"test{a="b"}[5y] offset 3d"#,
1962            ),
1963            (
1964                r#"{a="b"}[5y] OFFSET 3d"#,
1965                r#"{a="b"}[5y] offset 3d"#,
1966            ),
1967            (
1968                "sum(some_metric) without(and, by, avg, count, alert, annotations)",
1969                "sum without (and, by, avg, count, alert, annotations) (some_metric)",
1970            ),
1971            (
1972                r#"floor(some_metric{foo!="bar"})"#,
1973                r#"floor(some_metric{foo!="bar"})"#,
1974            ),
1975            (
1976                "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1977                "sum(rate(http_request_duration_seconds[10m])) / count(rate(http_request_duration_seconds[10m]))",
1978            ),
1979            ("rate(some_metric[5m])", "rate(some_metric[5m])"),
1980            ("round(some_metric,5)", "round(some_metric, 5)"),
1981            (
1982                r#"absent(sum(nonexistent{job="myjob"}))"#,
1983                r#"absent(sum(nonexistent{job="myjob"}))"#,
1984            ),
1985            (
1986                "histogram_quantile(0.9,rate(http_request_duration_seconds_bucket[10m]))",
1987                "histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))",
1988            ),
1989            (
1990                "histogram_quantile(0.9,sum(rate(http_request_duration_seconds_bucket[10m])) by(job,le))",
1991                "histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))",
1992            ),
1993            (
1994                r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1995                r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1996            ),
1997            (
1998                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100"#,
1999                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s] @ 100.000"#,
2000            ),
2001            (
2002                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2003                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#,
2004            ),
2005            (
2006                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2007                r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
2008            ),
2009            ("some_metric OFFSET 1m [10m:5s]", "some_metric offset 1m[10m:5s]"),
2010            ("some_metric @123 [10m:5s]", "some_metric @ 123.000[10m:5s]"),
2011            ("some_metric <= 1ms", "some_metric <= 0.001"),
2012        ];
2013
2014        // the following cases are from https://github.com/prometheus/prometheus/blob/main/promql/parser/printer_test.go
2015        let mut cases1 = vec![
2016            (
2017                r#"sum by() (task:errors:rate10s{job="s"})"#,
2018                r#"sum(task:errors:rate10s{job="s"})"#,
2019            ),
2020            (
2021                r#"sum by(code) (task:errors:rate10s{job="s"})"#,
2022                r#"sum by (code) (task:errors:rate10s{job="s"})"#,
2023            ),
2024            (
2025                r#"sum without() (task:errors:rate10s{job="s"})"#,
2026                r#"sum without () (task:errors:rate10s{job="s"})"#,
2027            ),
2028            (
2029                r#"sum without(instance) (task:errors:rate10s{job="s"})"#,
2030                r#"sum without (instance) (task:errors:rate10s{job="s"})"#,
2031            ),
2032            (
2033                r#"topk(5, task:errors:rate10s{job="s"})"#,
2034                r#"topk(5, task:errors:rate10s{job="s"})"#,
2035            ),
2036            (
2037                r#"count_values("value", task:errors:rate10s{job="s"})"#,
2038                r#"count_values("value", task:errors:rate10s{job="s"})"#,
2039            ),
2040            ("a - on() c", "a - on () c"),
2041            ("a - on(b) c", "a - on (b) c"),
2042            ("a - on(b) group_left(x) c", "a - on (b) group_left (x) c"),
2043            (
2044                "a - on(b) group_left(x, y) c",
2045                "a - on (b) group_left (x, y) c",
2046            ),
2047            ("a - on(b) group_left c", "a - on (b) group_left () c"),
2048            ("a - ignoring(b) c", "a - ignoring (b) c"),
2049            ("a - ignoring() c", "a - c"),
2050            ("a + fill(-23) b", "a + fill (-23) b"),
2051            ("a + fill_left(-23) b", "a + fill_left (-23) b"),
2052            ("a + fill_right(42) b", "a + fill_right (42) b"),
2053            (
2054                "a + fill_left(-23) fill_right(42) b",
2055                "a + fill_left (-23) fill_right (42) b",
2056            ),
2057            (
2058                "a + on(b) group_left fill(-23) c",
2059                "a + on (b) group_left () fill (-23) c",
2060            ),
2061            ("up > bool 0", "up > bool 0"),
2062            ("a offset 1m", "a offset 1m"),
2063            ("a offset -7m", "a offset -7m"),
2064            (r#"a{c="d"}[5m] offset 1m"#, r#"a{c="d"}[5m] offset 1m"#),
2065            ("a[5m] offset 1m", "a[5m] offset 1m"),
2066            ("a[12m] offset -3m", "a[12m] offset -3m"),
2067            ("a[1h:5m] offset 1m", "a[1h:5m] offset 1m"),
2068            (r#"{__name__="a"}"#, r#"{__name__="a"}"#),
2069            (r#"a{b!="c"}[1m]"#, r#"a{b!="c"}[1m]"#),
2070            (r#"a{b=~"c"}[1m]"#, r#"a{b=~"c"}[1m]"#),
2071            (r#"a{b!~"c"}[1m]"#, r#"a{b!~"c"}[1m]"#),
2072            ("a @ 10", "a @ 10.000"),
2073            ("a[1m] @ 10", "a[1m] @ 10.000"),
2074            ("a @ start()", "a @ start()"),
2075            ("a @ end()", "a @ end()"),
2076            ("a[1m] @ start()", "a[1m] @ start()"),
2077            ("a[1m] @ end()", "a[1m] @ end()"),
2078        ];
2079
2080        // the following cases copy the tests from the following: https://github.com/prometheus/prometheus/pull/9138
2081        let mut cases2 = vec![
2082            (
2083                r#"test{a="b"}[5y] OFFSET 3d"#,
2084                r#"test{a="b"}[5y] offset 3d"#,
2085            ),
2086            (
2087                r#"test{a="b"}[5m] OFFSET 3600"#,
2088                r#"test{a="b"}[5m] offset 1h"#,
2089            ),
2090            ("foo[3ms] @ 2.345", "foo[3ms] @ 2.345"),
2091            ("foo[4s180ms] @ 2.345", "foo[4s180ms] @ 2.345"),
2092            ("foo[4.18] @ 2.345", "foo[4s180ms] @ 2.345"),
2093            ("foo[4s18ms] @ 2.345", "foo[4s18ms] @ 2.345"),
2094            ("foo[4.018] @ 2.345", "foo[4s18ms] @ 2.345"),
2095            ("test[5]", "test[5s]"),
2096            ("some_metric[5m] @ 1m", "some_metric[5m] @ 60.000"),
2097            ("metric @ 100s", "metric @ 100.000"),
2098            ("metric @ 1m40s", "metric @ 100.000"),
2099            ("metric @ 100 offset 50", "metric @ 100.000 offset 50s"),
2100            ("metric offset 50 @ 100", "metric @ 100.000 offset 50s"),
2101            ("metric @ 0 offset -50", "metric @ 0.000 offset -50s"),
2102            ("metric offset -50 @ 0", "metric @ 0.000 offset -50s"),
2103            (
2104                r#"sum_over_time(metric{job="1"}[100] @ 100 offset 50)"#,
2105                r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2106            ),
2107            (
2108                r#"sum_over_time(metric{job="1"}[100] offset 50s @ 100)"#,
2109                r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000 offset 50s)"#,
2110            ),
2111            (
2112                r#"sum_over_time(metric{job="1"}[100] @ 100) + label_replace(sum_over_time(metric{job="2"}[100] @ 100), "job", "1", "", "")"#,
2113                r#"sum_over_time(metric{job="1"}[1m40s] @ 100.000) + label_replace(sum_over_time(metric{job="2"}[1m40s] @ 100.000), "job", "1", "", "")"#,
2114            ),
2115            (
2116                r#"sum_over_time(metric{job="1"}[100:1] offset 20 @ 100)"#,
2117                r#"sum_over_time(metric{job="1"}[1m40s:1s] @ 100.000 offset 20s)"#,
2118            ),
2119        ];
2120
2121        cases.append(&mut cases1);
2122        cases.append(&mut cases2);
2123        for (input, expected) in cases {
2124            let expr = crate::parser::parse(input).unwrap();
2125            assert_eq!(expected, expr.to_string())
2126        }
2127    }
2128
2129    #[test]
2130    fn test_vector_selector_to_string() {
2131        let cases = vec![
2132            (VectorSelector::default(), ""),
2133            (VectorSelector::from("foobar"), "foobar"),
2134            (
2135                {
2136                    let name = Some(String::from("foobar"));
2137                    let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "x"));
2138                    VectorSelector::new(name, matchers)
2139                },
2140                r#"foobar{a="x"}"#,
2141            ),
2142            (
2143                {
2144                    let matchers = Matchers::new(vec![
2145                        Matcher::new(MatchOp::Equal, "a", "x"),
2146                        Matcher::new(MatchOp::Equal, "b", "y"),
2147                    ]);
2148                    VectorSelector::new(None, matchers)
2149                },
2150                r#"{a="x",b="y"}"#,
2151            ),
2152            (
2153                {
2154                    let matchers =
2155                        Matchers::one(Matcher::new(MatchOp::Equal, METRIC_NAME, "foobar"));
2156                    VectorSelector::new(None, matchers)
2157                },
2158                r#"{__name__="foobar"}"#,
2159            ),
2160        ];
2161
2162        for (vs, expect) in cases {
2163            assert_eq!(expect, vs.to_string())
2164        }
2165    }
2166
2167    #[test]
2168    fn test_aggregate_expr_pretty() {
2169        let cases = vec![
2170            ("sum(foo)", "sum(foo)"),
2171            (
2172                r#"sum by() (task:errors:rate10s{job="s"})"#,
2173                r#"sum(
2174  task:errors:rate10s{job="s"}
2175)"#,
2176            ),
2177            (
2178                r#"sum without(job,foo) (task:errors:rate10s{job="s"})"#,
2179                r#"sum without (job, foo) (
2180  task:errors:rate10s{job="s"}
2181)"#,
2182            ),
2183            (
2184                r#"sum(task:errors:rate10s{job="s"}) without(job,foo)"#,
2185                r#"sum without (job, foo) (
2186  task:errors:rate10s{job="s"}
2187)"#,
2188            ),
2189            (
2190                r#"sum by(job,foo) (task:errors:rate10s{job="s"})"#,
2191                r#"sum by (job, foo) (
2192  task:errors:rate10s{job="s"}
2193)"#,
2194            ),
2195            (
2196                r#"sum (task:errors:rate10s{job="s"}) by(job,foo)"#,
2197                r#"sum by (job, foo) (
2198  task:errors:rate10s{job="s"}
2199)"#,
2200            ),
2201            (
2202                r#"topk(10, ask:errors:rate10s{job="s"})"#,
2203                r#"topk(
2204  10,
2205  ask:errors:rate10s{job="s"}
2206)"#,
2207            ),
2208            (
2209                r#"sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2210                r#"sum by (job, foo) (
2211  sum by (job, foo) (
2212    task:errors:rate10s{job="s"}
2213  )
2214)"#,
2215            ),
2216            (
2217                r#"sum by(job,foo) (sum by(job,foo) (sum by(job,foo) (task:errors:rate10s{job="s"})))"#,
2218                r#"sum by (job, foo) (
2219  sum by (job, foo) (
2220    sum by (job, foo) (
2221      task:errors:rate10s{job="s"}
2222    )
2223  )
2224)"#,
2225            ),
2226            (
2227                r#"sum by(job,foo)
2228(sum by(job,foo) (task:errors:rate10s{job="s"}))"#,
2229                r#"sum by (job, foo) (
2230  sum by (job, foo) (
2231    task:errors:rate10s{job="s"}
2232  )
2233)"#,
2234            ),
2235            (
2236                r#"sum by(job,foo)
2237(sum(task:errors:rate10s{job="s"}) without(job,foo))"#,
2238                r#"sum by (job, foo) (
2239  sum without (job, foo) (
2240    task:errors:rate10s{job="s"}
2241  )
2242)"#,
2243            ),
2244            (
2245                r#"sum by(job,foo) # Comment 1.
2246(sum by(job,foo) ( # Comment 2.
2247task:errors:rate10s{job="s"}))"#,
2248                r#"sum by (job, foo) (
2249  sum by (job, foo) (
2250    task:errors:rate10s{job="s"}
2251  )
2252)"#,
2253            ),
2254        ];
2255
2256        for (input, expect) in cases {
2257            let expr = crate::parser::parse(input);
2258            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2259        }
2260    }
2261
2262    #[test]
2263    fn test_binary_expr_pretty() {
2264        let cases = vec![
2265            ("a+b", "a + b"),
2266            (
2267                "a == bool 1",
2268                "  a
2269== bool
2270  1",
2271            ),
2272            (
2273                "a == 1024000",
2274                "  a
2275==
2276  1024000",
2277            ),
2278            (
2279                "a + ignoring(job) b",
2280                "  a
2281+ ignoring (job)
2282  b",
2283            ),
2284            (
2285                "foo_1 + foo_2",
2286                "  foo_1
2287+
2288  foo_2",
2289            ),
2290            (
2291                "foo_1 + foo_2 + foo_3",
2292                "    foo_1
2293  +
2294    foo_2
2295+
2296  foo_3",
2297            ),
2298            (
2299                "foo + baar + foo_3",
2300                "  foo + baar
2301+
2302  foo_3",
2303            ),
2304            (
2305                "foo_1 + foo_2 + foo_3 + foo_4",
2306                "      foo_1
2307    +
2308      foo_2
2309  +
2310    foo_3
2311+
2312  foo_4",
2313            ),
2314            (
2315                "foo_1 + ignoring(foo) foo_2 + ignoring(job) group_left foo_3 + on(instance) group_right foo_4",
2316
2317                 "      foo_1
2318    + ignoring (foo)
2319      foo_2
2320  + ignoring (job) group_left ()
2321    foo_3
2322+ on (instance) group_right ()
2323  foo_4",
2324            ),
2325        ];
2326
2327        for (input, expect) in cases {
2328            let expr = crate::parser::parse(input);
2329            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2330        }
2331    }
2332
2333    #[test]
2334    fn test_call_expr_pretty() {
2335        let cases = vec![
2336            (
2337                "rate(foo[1m])",
2338                "rate(
2339  foo[1m]
2340)",
2341            ),
2342            (
2343                "sum_over_time(foo[1m])",
2344                "sum_over_time(
2345  foo[1m]
2346)",
2347            ),
2348            (
2349                "rate(long_vector_selector[10m:1m] @ start() offset 1m)",
2350                "rate(
2351  long_vector_selector[10m:1m] @ start() offset 1m
2352)",
2353            ),
2354            (
2355                "histogram_quantile(0.9, rate(foo[1m]))",
2356                "histogram_quantile(
2357  0.9,
2358  rate(
2359    foo[1m]
2360  )
2361)",
2362            ),
2363            (
2364                "histogram_quantile(0.9, rate(foo[1m] @ start()))",
2365                "histogram_quantile(
2366  0.9,
2367  rate(
2368    foo[1m] @ start()
2369  )
2370)",
2371            ),
2372            (
2373                "max_over_time(rate(demo_api_request_duration_seconds_count[1m])[1m:] @ start() offset 1m)",
2374                "max_over_time(
2375  rate(
2376    demo_api_request_duration_seconds_count[1m]
2377  )[1m:] @ start() offset 1m
2378)",
2379            ),
2380            (
2381                r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
2382                r#"label_replace(
2383  up{job="api-server",service="a:c"},
2384  "foo",
2385  "$1",
2386  "service",
2387  "(.*):.*"
2388)"#,
2389            ),
2390            (
2391                r#"label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*")"#,
2392                r#"label_replace(
2393  label_replace(
2394    up{job="api-server",service="a:c"},
2395    "foo",
2396    "$1",
2397    "service",
2398    "(.*):.*"
2399  ),
2400  "foo",
2401  "$1",
2402  "service",
2403  "(.*):.*"
2404)"#,
2405            ),
2406        ];
2407
2408        for (input, expect) in cases {
2409            let expr = crate::parser::parse(input);
2410            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2411        }
2412    }
2413
2414    #[test]
2415    fn test_paren_expr_pretty() {
2416        let cases = vec![
2417            ("(foo)", "(foo)"),
2418            (
2419                "(_foo_long_)",
2420                "(
2421  _foo_long_
2422)",
2423            ),
2424            (
2425                "((foo_long))",
2426                "(
2427  (foo_long)
2428)",
2429            ),
2430            (
2431                "((_foo_long_))",
2432                "(
2433  (
2434    _foo_long_
2435  )
2436)",
2437            ),
2438            (
2439                "(((foo_long)))",
2440                "(
2441  (
2442    (foo_long)
2443  )
2444)",
2445            ),
2446            ("(1 + 2)", "(1 + 2)"),
2447            (
2448                "(foo + bar)",
2449                "(
2450  foo + bar
2451)",
2452            ),
2453            (
2454                "(foo_long + bar_long)",
2455                "(
2456    foo_long
2457  +
2458    bar_long
2459)",
2460            ),
2461            (
2462                "(foo_long + bar_long + bar_2_long)",
2463                "(
2464      foo_long
2465    +
2466      bar_long
2467  +
2468    bar_2_long
2469)",
2470            ),
2471            (
2472                "((foo_long + bar_long) + bar_2_long)",
2473                "(
2474    (
2475        foo_long
2476      +
2477        bar_long
2478    )
2479  +
2480    bar_2_long
2481)",
2482            ),
2483            (
2484                "(1111 + 2222)",
2485                "(
2486    1111
2487  +
2488    2222
2489)",
2490            ),
2491            (
2492                "(sum_over_time(foo[1m]))",
2493                "(
2494  sum_over_time(
2495    foo[1m]
2496  )
2497)",
2498            ),
2499            (
2500                r#"(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"))"#,
2501                r#"(
2502  label_replace(
2503    up{job="api-server",service="a:c"},
2504    "foo",
2505    "$1",
2506    "service",
2507    "(.*):.*"
2508  )
2509)"#,
2510            ),
2511            (
2512                r#"(label_replace(label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2513                r#"(
2514  label_replace(
2515    label_replace(
2516      up{job="api-server",service="a:c"},
2517      "foo",
2518      "$1",
2519      "service",
2520      "(.*):.*"
2521    ),
2522    "foo",
2523    "$1",
2524    "service",
2525    "(.*):.*"
2526  )
2527)"#,
2528            ),
2529            (
2530                r#"(label_replace(label_replace((up{job="api-server",service="a:c"}), "foo", "$1", "service", "(.*):.*"), "foo", "$1", "service", "(.*):.*"))"#,
2531                r#"(
2532  label_replace(
2533    label_replace(
2534      (
2535        up{job="api-server",service="a:c"}
2536      ),
2537      "foo",
2538      "$1",
2539      "service",
2540      "(.*):.*"
2541    ),
2542    "foo",
2543    "$1",
2544    "service",
2545    "(.*):.*"
2546  )
2547)"#,
2548            ),
2549        ];
2550
2551        for (input, expect) in cases {
2552            let expr = crate::parser::parse(input);
2553            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2554        }
2555    }
2556
2557    #[test]
2558    fn test_unary_expr_pretty() {
2559        let cases = vec![
2560            ("-1", "-1"),
2561            ("-vector_selector", "-vector_selector"),
2562            (
2563                "(-vector_selector)",
2564                "(
2565  -vector_selector
2566)",
2567            ),
2568            (
2569                "-histogram_quantile(0.9,rate(foo[1m]))",
2570                "-histogram_quantile(
2571  0.9,
2572  rate(
2573    foo[1m]
2574  )
2575)",
2576            ),
2577            (
2578                "-histogram_quantile(0.99, sum by (le) (rate(foo[1m])))",
2579                "-histogram_quantile(
2580  0.99,
2581  sum by (le) (
2582    rate(
2583      foo[1m]
2584    )
2585  )
2586)",
2587            ),
2588            (
2589                "-histogram_quantile(0.9, -rate(foo[1m] @ start()))",
2590                "-histogram_quantile(
2591  0.9,
2592  -rate(
2593    foo[1m] @ start()
2594  )
2595)",
2596            ),
2597            (
2598                "(-histogram_quantile(0.9, -rate(foo[1m] @ start())))",
2599                "(
2600  -histogram_quantile(
2601    0.9,
2602    -rate(
2603      foo[1m] @ start()
2604    )
2605  )
2606)",
2607            ),
2608        ];
2609
2610        for (input, expect) in cases {
2611            let expr = crate::parser::parse(input);
2612            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2613        }
2614    }
2615
2616    #[test]
2617    fn test_expr_pretty() {
2618        // Following queries have been taken from https://monitoring.mixins.dev/
2619        let cases = vec![
2620            (
2621                r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 40 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 24*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2622                r#"(
2623            node_filesystem_avail_bytes{fstype!="",job="node"}
2624          /
2625            node_filesystem_size_bytes{fstype!="",job="node"}
2626        *
2627          100
2628      <
2629        40
2630    and
2631        predict_linear(
2632          node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2633            24 * 60
2634          *
2635            60
2636        )
2637      <
2638        0
2639  and
2640      node_filesystem_readonly{fstype!="",job="node"}
2641    ==
2642      0
2643)"#,
2644            ),
2645            (
2646                r#"(node_filesystem_avail_bytes{job="node",fstype!=""} / node_filesystem_size_bytes{job="node",fstype!=""} * 100 < 20 and predict_linear(node_filesystem_avail_bytes{job="node",fstype!=""}[6h], 4*60*60) < 0 and node_filesystem_readonly{job="node",fstype!=""} == 0)"#,
2647                r#"(
2648            node_filesystem_avail_bytes{fstype!="",job="node"}
2649          /
2650            node_filesystem_size_bytes{fstype!="",job="node"}
2651        *
2652          100
2653      <
2654        20
2655    and
2656        predict_linear(
2657          node_filesystem_avail_bytes{fstype!="",job="node"}[6h],
2658            4 * 60
2659          *
2660            60
2661        )
2662      <
2663        0
2664  and
2665      node_filesystem_readonly{fstype!="",job="node"}
2666    ==
2667      0
2668)"#,
2669            ),
2670            (
2671                r#"(node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0)"#,
2672                r#"  (
2673        node_timex_offset_seconds
2674      >
2675        0.05
2676    and
2677        deriv(
2678          node_timex_offset_seconds[5m]
2679        )
2680      >=
2681        0
2682  )
2683or
2684  (
2685        node_timex_offset_seconds
2686      <
2687        -0.05
2688    and
2689        deriv(
2690          node_timex_offset_seconds[5m]
2691        )
2692      <=
2693        0
2694  )"#,
2695            ),
2696            (
2697                r#"1 - ((node_memory_MemAvailable_bytes{job="node"} or (node_memory_Buffers_bytes{job="node"} + node_memory_Cached_bytes{job="node"} + node_memory_MemFree_bytes{job="node"} + node_memory_Slab_bytes{job="node"}) ) / node_memory_MemTotal_bytes{job="node"})"#,
2698                r#"  1
2699-
2700  (
2701      (
2702          node_memory_MemAvailable_bytes{job="node"}
2703        or
2704          (
2705                  node_memory_Buffers_bytes{job="node"}
2706                +
2707                  node_memory_Cached_bytes{job="node"}
2708              +
2709                node_memory_MemFree_bytes{job="node"}
2710            +
2711              node_memory_Slab_bytes{job="node"}
2712          )
2713      )
2714    /
2715      node_memory_MemTotal_bytes{job="node"}
2716  )"#,
2717            ),
2718            (
2719                r#"min by (job, integration) (rate(alertmanager_notifications_failed_total{job="alertmanager", integration=~".*"}[5m]) / rate(alertmanager_notifications_total{job="alertmanager", integration="~.*"}[5m])) > 0.01"#,
2720                r#"  min by (job, integration) (
2721      rate(
2722        alertmanager_notifications_failed_total{integration=~".*",job="alertmanager"}[5m]
2723      )
2724    /
2725      rate(
2726        alertmanager_notifications_total{integration="~.*",job="alertmanager"}[5m]
2727      )
2728  )
2729>
2730  0.01"#,
2731            ),
2732            (
2733                r#"(count by (job) (changes(process_start_time_seconds{job="alertmanager"}[10m]) > 4) / count by (job) (up{job="alertmanager"})) >= 0.5"#,
2734                r#"  (
2735      count by (job) (
2736          changes(
2737            process_start_time_seconds{job="alertmanager"}[10m]
2738          )
2739        >
2740          4
2741      )
2742    /
2743      count by (job) (
2744        up{job="alertmanager"}
2745      )
2746  )
2747>=
2748  0.5"#,
2749            ),
2750        ];
2751
2752        for (input, expect) in cases {
2753            let expr = crate::parser::parse(input);
2754            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2755        }
2756    }
2757
2758    #[test]
2759    fn test_step_invariant_pretty() {
2760        let cases = vec![
2761            ("a @ 1", "a @ 1.000"),
2762            ("a @ start()", "a @ start()"),
2763            ("vector_selector @ start()", "vector_selector @ start()"),
2764        ];
2765
2766        for (input, expect) in cases {
2767            let expr = crate::parser::parse(input);
2768            assert_eq!(expect, expr.unwrap().pretty(0, 10));
2769        }
2770    }
2771
2772    #[test]
2773    fn test_prettify() {
2774        let cases = vec![
2775            ("vector_selector", "vector_selector"),
2776            (
2777                r#"vector_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}"#,
2778                r#"vector_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}"#,
2779            ),
2780            (
2781                r#"matrix_selector{fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",process_name="alertmanager"}[1y2w3d]"#,
2782                r#"matrix_selector{barrrrrrrrrrrrrrrrrrr="fooooooooooooooooo",fooooooooooooooooo="barrrrrrrrrrrrrrrrrrr",process_name="alertmanager"}[382d]"#,
2783            ),
2784        ];
2785
2786        for (input, expect) in cases {
2787            assert_eq!(expect, crate::parser::parse(input).unwrap().prettify());
2788        }
2789    }
2790
2791    #[test]
2792    fn test_eval_stmt_to_string() {
2793        let query = r#"http_requests_total{job="apiserver", handler="/api/comments"}[5m]"#;
2794        let start = "2024-10-08T07:15:00.022978+00:00";
2795        let end = "2024-10-08T07:15:30.012978+00:00";
2796        let expect = r#"[http_requests_total{handler="/api/comments",job="apiserver"}[5m]] @ [2024-10-08T07:15:00.022978+00:00, 2024-10-08T07:15:30.012978+00:00, 1m, 5m]"#;
2797
2798        let stmt = EvalStmt {
2799            expr: crate::parser::parse(query).unwrap(),
2800            start: DateTime::parse_from_rfc3339(start)
2801                .unwrap()
2802                .with_timezone(&Utc)
2803                .into(),
2804            end: DateTime::parse_from_rfc3339(end)
2805                .unwrap()
2806                .with_timezone(&Utc)
2807                .into(),
2808            interval: Duration::from_secs(60),
2809            lookback_delta: Duration::from_secs(300),
2810        };
2811
2812        assert_eq!(expect, stmt.to_string());
2813    }
2814
2815    #[test]
2816    fn test_prettify_with_utf8_labels() {
2817        // Test that labels with special characters are properly quoted in display
2818        let cases = vec![
2819            // (input, expected_display)
2820            (r#"{"some.metric"}"#, r#"{__name__="some.metric"}"#),
2821            (
2822                r#"foo{"label.with.dots"="value"}"#,
2823                r#"foo{"label.with.dots"="value"}"#,
2824            ),
2825            (
2826                r#"bar{"label-with-dashes"="test"}"#,
2827                r#"bar{"label-with-dashes"="test"}"#,
2828            ),
2829            (
2830                r#"baz{"label:with:colons"="data"}"#,
2831                r#"baz{"label:with:colons"="data"}"#,
2832            ),
2833            (
2834                r#"sum by ("service.version", foo) ({"some.metric"})"#,
2835                r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2836            ),
2837            (
2838                r#"sum by (`service.version`, foo) ({"some.metric"})"#,
2839                r#"sum by ("service.version", foo) ({__name__="some.metric"})"#,
2840            ),
2841            // Regular labels should not be quoted
2842            (r#"foo{job="web"}"#, r#"foo{job="web"}"#),
2843            (
2844                r#"bar{instance_id="server1"}"#,
2845                r#"bar{instance_id="server1"}"#,
2846            ),
2847        ];
2848
2849        for (input, expected) in cases {
2850            let parsed = crate::parser::parse(input).unwrap();
2851            let prettified = parsed.prettify();
2852            assert_eq!(prettified, expected);
2853        }
2854    }
2855}