logical_expressions/lib.rs
1#![deny(missing_docs)]
2
3//! This crate provides a library for working with logical expressions.
4//!
5//! It defines the `LogicalExpression` enum, which represents a logical expression with conditions
6//! combined using AND and OR operators. The library also provides functions for parsing logical
7//! expressions from strings and expanding them into a list of lists, where the inner lists represent
8//! the AND conditions and the outer lists represent the OR conditions.
9
10/// Represents a logical expression with conditions combined using AND and OR operators.
11#[derive(Clone, PartialEq, Eq, Debug)]
12pub enum LogicalExpression<Condition> {
13 /// Represents a logical AND operation on a list of logical expressions.
14 And(Vec<LogicalExpression<Condition>>),
15 /// Represents a logical OR operation on a list of logical expressions.
16 Or(Vec<LogicalExpression<Condition>>),
17 /// Represents a single condition in the logical expression.
18 Condition(Condition),
19}
20
21impl<Condition> LogicalExpression<Condition> {
22 /// Creates a new logical expression representing the logical AND of the given list of expressions.
23 ///
24 /// If the list contains only one expression, it is returned as is.
25 pub fn and(mut list: Vec<Self>) -> Self {
26 if list.len() == 1 {
27 return unsafe { list.pop().unwrap_unchecked() };
28 }
29
30 Self::And(list)
31 }
32
33 /// Creates a new logical expression representing the logical OR of the given list of expressions.
34 ///
35 /// If the list contains only one expression, it is returned as is.
36 pub fn or(mut list: Vec<Self>) -> Self {
37 if list.len() == 1 {
38 return unsafe { list.pop().unwrap_unchecked() };
39 }
40
41 Self::Or(list)
42 }
43}
44
45impl<Condition: Clone> LogicalExpression<Condition> {
46 /// Expands the logical expression into a list of lists, where the inner lists represent the AND conditions
47 /// and the outer lists represent the OR conditions.
48 pub fn expand(self) -> Vec<Vec<Condition>> {
49 use LogicalExpression::*;
50 match self {
51 And(groups) => {
52 let mut expanded_groups = Vec::new();
53 for group in groups {
54 let expanded = group.expand();
55 expanded_groups.push(expanded);
56 }
57 Self::cartesian_product(expanded_groups)
58 }
59 Or(groups) => {
60 let mut expanded = Vec::new();
61 for group in groups {
62 let mut group_expanded = group.expand();
63 expanded.append(&mut group_expanded);
64 }
65 expanded
66 }
67 Condition(condition) => vec![vec![condition]],
68 }
69 }
70
71 fn cartesian_product(groups: Vec<Vec<Vec<Condition>>>) -> Vec<Vec<Condition>> {
72 let mut result = vec![Vec::new()];
73
74 for group in groups {
75 let mut new_result = vec![];
76 for r in &result {
77 for g in &group {
78 let mut new_r = r.clone();
79 new_r.extend(g.clone());
80 new_result.push(new_r);
81 }
82 }
83 result = new_result;
84 }
85
86 result
87 }
88}
89
90mod parser;
91
92pub use parser::ParseError;