dynamodb_expression/condition/
parenthetical.rs

1use core::fmt::{self, Write};
2
3use super::Condition;
4
5/// Wraps a condition in parentheses.
6///
7/// See also: [`Condition::parenthesize`]
8///
9/// ```
10/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
11/// use dynamodb_expression::Path;
12/// # use pretty_assertions::assert_eq;
13///
14/// let a = "a".parse::<Path>()?;
15/// let b = "b".parse::<Path>()?;
16/// let c = "c".parse::<Path>()?;
17/// let d = "d".parse::<Path>()?;
18///
19/// let condition = a.greater_than(b).parenthesize().and(c.less_than(d).parenthesize());
20/// assert_eq!("(a > b) AND (c < d)", condition.to_string());
21/// #
22/// # Ok(())
23/// # }
24/// ```
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct Parenthetical {
27    pub(crate) condition: Box<Condition>,
28}
29
30impl Parenthetical {
31    // /// Unwrap nested parentheses. E.g., `(((a and (((b < c))))))` becomes `(a and (b < c))`
32    // pub fn normalize(self) -> Condition {
33    //     Self(
34    //         self.flatten()
35    //             .0
36    //             // Normalize down the chain.
37    //             .normalize()
38    //             .into(),
39    //     )
40    //     .into()
41    // }
42
43    // /// Removes this level of nested parentheses without any deeper flattening or normalization.
44    // /// E.g., `(((a and (((b < c))))))` becomes `(a and (((b < c))))`
45    // pub fn flatten(self) -> Self {
46    //     let mut inner = self.0;
47    //     while let Expression::Parenthetical(Self(paren_inner)) = *inner {
48    //         inner = paren_inner;
49    //     }
50
51    //     Self(inner)
52    // }
53}
54
55impl<T> From<T> for Parenthetical
56where
57    T: Into<Box<Condition>>,
58{
59    fn from(condition: T) -> Self {
60        Self {
61            condition: condition.into(),
62        }
63    }
64}
65
66impl fmt::Display for Parenthetical {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        f.write_char('(')?;
69        self.condition.fmt(f)?;
70        f.write_char(')')
71    }
72}
73
74#[cfg(test)]
75mod test {
76    use std::io::{self, Write};
77
78    use pretty_assertions::assert_str_eq;
79
80    use crate::condition::test::cmp_a_gt_b;
81
82    #[test]
83    fn parentheses() {
84        let expr = cmp_a_gt_b();
85
86        for i in 0..3 {
87            let mut wrapped = expr.clone().parenthesize();
88            for _ in 0..i {
89                wrapped = wrapped.parenthesize();
90            }
91
92            println!("{i}: {wrapped}");
93            io::stdout().lock().flush().unwrap();
94
95            assert_str_eq!(
96                match i {
97                    0 => format!("({expr})"),
98                    1 => format!("(({expr}))"),
99                    2 => format!("((({expr})))"),
100                    _ => unreachable!(),
101                },
102                wrapped.to_string(),
103                "The `Display` output wasn't what was expected."
104            );
105
106            // let normalized = wrapped.normalize();
107            // println!(" → {normalized}");
108            // assert_str_eq!(
109            //     "(a > b)",
110            //     normalized.to_string(),
111            //     "Should always normalize to a single set of parentheses."
112            // );
113        }
114    }
115}