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}