ya_agreement_utils/
constraints.rs

1use std::fmt::{self, Formatter};
2
3#[derive(Clone)]
4pub struct Constraints {
5    pub constraints: Vec<ConstraintExpr>,
6    pub operator: ClauseOperator,
7}
8
9impl Constraints {
10    pub fn new_clause<T: Into<ConstraintExpr>>(op: ClauseOperator, v: Vec<T>) -> Constraints {
11        Constraints {
12            constraints: v.into_iter().map(|x| x.into()).collect(),
13            operator: op,
14        }
15    }
16    pub fn new_single<T: Into<ConstraintExpr>>(el: T) -> Constraints {
17        Constraints {
18            constraints: vec![el.into()],
19            operator: ClauseOperator::And,
20        }
21    }
22    pub fn or(self, c: Constraints) -> Constraints {
23        self.joined_with(c, ClauseOperator::Or)
24    }
25    pub fn and(self, c: Constraints) -> Constraints {
26        self.joined_with(c, ClauseOperator::And)
27    }
28    fn joined_with(self, c: Constraints, operator: ClauseOperator) -> Constraints {
29        if c.operator == operator && self.operator == operator {
30            Constraints {
31                constraints: [&self.constraints[..], &c.constraints[..]].concat(),
32                operator: self.operator,
33            }
34        } else {
35            Constraints::new_clause(operator, vec![self, c])
36        }
37    }
38    pub fn without<T: Into<ConstraintKey>>(self, removed_key: T) -> Constraints {
39        let op = self.operator;
40        let del_key = removed_key.into();
41        Constraints {
42            constraints: self
43                .into_iter()
44                .filter(|c| match c {
45                    ConstraintExpr::KeyValue { key, .. } => *key != del_key,
46                    _ => true,
47                })
48                .collect(),
49            operator: op,
50        }
51    }
52    pub fn filter_by_key<T: Into<ConstraintKey>>(&self, get_key: T) -> Option<Constraints> {
53        let k = get_key.into();
54        let v: Vec<_> = self
55            .constraints
56            .iter()
57            .cloned()
58            .filter(|e| match e {
59                ConstraintExpr::KeyValue { key, .. } => *key == k,
60                ConstraintExpr::Constraints(_) => false,
61            })
62            .collect();
63        match v.len() {
64            0 => None,
65            1 => Some(Self::new_single(v[0].clone())),
66            _ => Some(Self::new_clause(self.operator, v)),
67        }
68    }
69}
70
71impl fmt::Display for Constraints {
72    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
73        match self.constraints.len() {
74            0 => Ok(()),
75            1 => write!(f, "{}", self.constraints[0]),
76            _ => {
77                writeln!(f, "({}", self.operator)?;
78                for el in &self.constraints {
79                    writeln!(f, "  {}", el.to_string().replace('\n', "\n  "))?;
80                }
81                write!(f, ")")
82            }
83        }
84    }
85}
86
87impl std::iter::IntoIterator for Constraints {
88    type Item = ConstraintExpr;
89    type IntoIter = std::vec::IntoIter<Self::Item>;
90
91    fn into_iter(self) -> Self::IntoIter {
92        self.constraints.into_iter()
93    }
94}
95
96#[derive(Copy, Clone, PartialEq, Eq)]
97pub enum ClauseOperator {
98    And,
99    Or,
100}
101
102impl fmt::Display for ClauseOperator {
103    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
104        write!(
105            f,
106            "{}",
107            match self {
108                ClauseOperator::And => "&",
109                ClauseOperator::Or => "|",
110            }
111        )
112    }
113}
114
115#[derive(Copy, Clone)]
116pub enum ConstraintOperator {
117    Equal,
118    NotEqual,
119    LessThan,
120    GreaterThan,
121}
122
123impl fmt::Display for ConstraintOperator {
124    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
125        write!(
126            f,
127            "{}",
128            match self {
129                ConstraintOperator::Equal => "=",
130                ConstraintOperator::NotEqual => "<>",
131                ConstraintOperator::LessThan => "<",
132                ConstraintOperator::GreaterThan => ">",
133            }
134        )
135    }
136}
137
138#[derive(Clone, PartialEq, Eq)]
139pub struct ConstraintKey(serde_json::Value);
140
141impl ConstraintKey {
142    pub fn new<T: Into<serde_json::Value>>(v: T) -> Self {
143        ConstraintKey(v.into())
144    }
145}
146
147impl<T: AsRef<str>> From<T> for ConstraintKey {
148    fn from(key: T) -> Self {
149        ConstraintKey::new(serde_json::Value::String(key.as_ref().to_string()))
150    }
151}
152
153pub type ConstraintValue = ConstraintKey;
154
155/* expression, e.g. key > value */
156#[derive(Clone)]
157pub enum ConstraintExpr {
158    KeyValue {
159        /* ops_values length is 0 or 1 now, but it's ready for expressions like k: > v1, < v2 */
160        key: ConstraintKey,
161        ops_values: Vec<(ConstraintOperator, ConstraintValue)>,
162    },
163    Constraints(Constraints),
164}
165
166impl From<ConstraintKey> for ConstraintExpr {
167    fn from(key: ConstraintKey) -> Self {
168        ConstraintExpr::KeyValue {
169            key,
170            ops_values: vec![],
171        }
172    }
173}
174
175impl From<Constraints> for ConstraintExpr {
176    fn from(key: Constraints) -> Self {
177        ConstraintExpr::Constraints(key)
178    }
179}
180
181impl fmt::Display for ConstraintExpr {
182    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
183        match self {
184            ConstraintExpr::KeyValue { key, ops_values } => {
185                if ops_values.is_empty() {
186                    write!(f, "({})", key.0.as_str().unwrap_or(&key.0.to_string()))
187                } else {
188                    for (op, val) in ops_values {
189                        write!(f, "({}", key.0.as_str().unwrap_or(&key.0.to_string()))?;
190                        write!(f, "{}", op)?;
191                        write!(f, "{}", val.0.as_str().unwrap_or(&val.0.to_string()))?;
192                        write!(f, ")")?
193                    }
194                    Ok(())
195                }
196            }
197            ConstraintExpr::Constraints(c) => write!(f, "{}", c),
198        }
199    }
200}
201
202impl ConstraintKey {
203    fn with_operator_value(
204        self,
205        operator: ConstraintOperator,
206        value: ConstraintValue,
207    ) -> ConstraintExpr {
208        ConstraintExpr::KeyValue {
209            key: self,
210            ops_values: vec![(operator, value)],
211        }
212    }
213    pub fn greater_than(self, value: ConstraintValue) -> ConstraintExpr {
214        self.with_operator_value(ConstraintOperator::GreaterThan, value)
215    }
216    pub fn less_than(self, value: ConstraintValue) -> ConstraintExpr {
217        self.with_operator_value(ConstraintOperator::LessThan, value)
218    }
219    pub fn equal_to(self, value: ConstraintValue) -> ConstraintExpr {
220        self.with_operator_value(ConstraintOperator::Equal, value)
221    }
222    pub fn not_equal_to(self, value: ConstraintValue) -> ConstraintExpr {
223        self.with_operator_value(ConstraintOperator::NotEqual, value)
224    }
225}
226
227#[macro_export]
228macro_rules! constraints [
229    () => {};
230    ($key:tt == $value:expr $(,)*) => {{ Constraints::new_single(ConstraintKey::new($key).equal_to(ConstraintKey::new($value))) }};
231    ($key:tt == $value:expr , $($r:tt)*) => {{ Constraints::new_single(ConstraintKey::new($key).equal_to(ConstraintKey::new($value))).and(constraints!( $($r)* )) }};
232    ($key:tt != $value:expr $(,)*) => {{ Constraints::new_single(ConstraintKey::new($key).not_equal_to(ConstraintKey::new($value))) }};
233    ($key:tt != $value:expr , $($r:tt)*) => {{ Constraints::new_single(ConstraintKey::new($key).not_equal_to(ConstraintKey::new($value))).and(constraints!( $($r)* )) }};
234    ($key:tt < $value:expr $(,)*) => {{ Constraints::new_single(ConstraintKey::new($key).less_than(ConstraintKey::new($value))) }};
235    ($key:tt < $value:expr , $($r:tt)*) => {{ Constraints::new_single(ConstraintKey::new($key).less_than(ConstraintKey::new($value))).and(constraints!( $($r)* )) }};
236    ($key:tt > $value:expr $(,)*) => {{ Constraints::new_single(ConstraintKey::new($key).greater_than(ConstraintKey::new($value))) }};
237    ($key:tt > $value:expr , $($r:tt)*) => {{ Constraints::new_single(ConstraintKey::new($key).greater_than(ConstraintKey::new($value))).and(constraints!( $($r)* )) }};
238    ($key:tt $(,)*) => {{ Constraints::new_single(ConstraintKey::new($key)) }};
239    ($key:tt , $($r:tt)*) => {{ Constraints::new_single(ConstraintKey::new($key)).and(constraints!( $($r)* )) }};
240    ($t:expr $(,)*) => { $t };
241    ($t:expr , $($r:tt)*) => {
242        $t.and(constraints!( $($r)* ))
243    };
244];