1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
use {
    crate::serutil::StringList,
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        fmt::{Debug, Display, Formatter, Result as FmtResult},
    },
};

#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum ConditionOp {
    ArnEquals,
    ArnEqualsIfExists,
    ArnLike,
    ArnLikeIfExists,
    ArnNotEquals,
    ArnNotEqualsIfExists,
    ArnNotLike,
    ArnNotLikeIfExists,
    BinaryEquals,
    BinaryEqualsIfExists,
    Bool,
    BoolIfExists,
    DateEquals,
    DateEqualsIfExists,
    DateGreaterThan,
    DateGreaterThanEquals,
    DateGreaterThanEqualsIfExists,
    DateGreaterThanIfExists,
    DateLessThan,
    DateLessThanEquals,
    DateLessThanEqualsIfExists,
    DateLessThanIfExists,
    DateNotEquals,
    DateNotEqualsIfExists,
    IpAddress,
    IpAddressIfExists,
    NotIpAddress,
    NotIpAddressIfExists,
    Null,
    NumericEquals,
    NumericEqualsIfExists,
    NumericGreaterThan,
    NumericGreaterThanEquals,
    NumericGreaterThanEqualsIfExists,
    NumericGreaterThanIfExists,
    NumericLessThan,
    NumericLessThanEquals,
    NumericLessThanEqualsIfExists,
    NumericLessThanIfExists,
    NumericNotEquals,
    NumericNotEqualsIfExists,
    StringEquals,
    StringEqualsIfExists,
    StringEqualsIgnoreCase,
    StringEqualsIgnoreCaseIfExists,
    StringLike,
    StringLikeIfExists,
    StringNotEquals,
    StringNotEqualsIfExists,
    StringNotEqualsIgnoreCase,
    StringNotEqualsIgnoreCaseIfExists,
    StringNotLike,
    StringNotLikeIfExists,
}

impl Display for ConditionOp {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        Debug::fmt(self, f)
    }
}

pub type ConditionMap = BTreeMap<String, StringList>;
pub type Condition = BTreeMap<ConditionOp, ConditionMap>;

#[cfg(test)]
mod tests {
    use {
        crate::ConditionOp::*,
        std::{cmp::Ordering, collections::HashMap},
    };

    #[test_log::test]
    #[allow(clippy::comparison_chain)]
    fn test_ordering() {
        let sorted_order = vec![
            ArnEquals,
            ArnEqualsIfExists,
            ArnLike,
            ArnLikeIfExists,
            ArnNotEquals,
            ArnNotEqualsIfExists,
            ArnNotLike,
            ArnNotLikeIfExists,
            BinaryEquals,
            BinaryEqualsIfExists,
            Bool,
            BoolIfExists,
            DateEquals,
            DateEqualsIfExists,
            DateGreaterThan,
            DateGreaterThanEquals,
            DateGreaterThanEqualsIfExists,
            DateGreaterThanIfExists,
            DateLessThan,
            DateLessThanEquals,
            DateLessThanEqualsIfExists,
            DateLessThanIfExists,
            DateNotEquals,
            DateNotEqualsIfExists,
            IpAddress,
            IpAddressIfExists,
            NotIpAddress,
            NotIpAddressIfExists,
            Null,
            NumericEquals,
            NumericEqualsIfExists,
            NumericGreaterThan,
            NumericGreaterThanEquals,
            NumericGreaterThanEqualsIfExists,
            NumericGreaterThanIfExists,
            NumericLessThan,
            NumericLessThanEquals,
            NumericLessThanEqualsIfExists,
            NumericLessThanIfExists,
            NumericNotEquals,
            NumericNotEqualsIfExists,
            StringEquals,
            StringEqualsIfExists,
            StringEqualsIgnoreCase,
            StringEqualsIgnoreCaseIfExists,
            StringLike,
            StringLikeIfExists,
            StringNotEquals,
            StringNotEqualsIfExists,
            StringNotEqualsIgnoreCase,
            StringNotEqualsIgnoreCaseIfExists,
            StringNotLike,
            StringNotLikeIfExists,
        ];

        let mut map = HashMap::new();
        for (i, el) in sorted_order.iter().enumerate() {
            map.insert(el, i);
        }

        for (el, i) in map.iter() {
            assert_eq!(**el, sorted_order[*i]);
            let _ = format!("{:?}", el);
        }

        for i in 0..sorted_order.len() {
            for j in 0..sorted_order.len() {
                let ordering = sorted_order[i].partial_cmp(&sorted_order[j]).unwrap();

                if i == j {
                    assert_eq!(ordering, Ordering::Equal);
                    assert!(sorted_order[i].eq(&sorted_order[j]));
                    assert!(sorted_order[i].le(&sorted_order[j]));
                    assert!(sorted_order[i].ge(&sorted_order[j]));
                } else if i < j {
                    assert_eq!(ordering, Ordering::Less);
                    assert!(sorted_order[i].ne(&sorted_order[j]));
                    assert!(sorted_order[i].lt(&sorted_order[j]));
                    assert!(sorted_order[i].le(&sorted_order[j]));
                } else {
                    assert_eq!(ordering, Ordering::Greater);
                    assert!(sorted_order[i].ne(&sorted_order[j]));
                    assert!(sorted_order[i].gt(&sorted_order[j]));
                    assert!(sorted_order[i].ge(&sorted_order[j]));
                }
            }
        }
    }

    #[test_log::test]
    fn test_display() {
        let items = vec![
            (ArnEquals, "ArnEquals"),
            (ArnEqualsIfExists, "ArnEqualsIfExists"),
            (ArnLike, "ArnLike"),
            (ArnLikeIfExists, "ArnLikeIfExists"),
            (ArnNotEquals, "ArnNotEquals"),
            (ArnNotEqualsIfExists, "ArnNotEqualsIfExists"),
            (ArnNotLike, "ArnNotLike"),
            (ArnNotLikeIfExists, "ArnNotLikeIfExists"),
            (BinaryEquals, "BinaryEquals"),
            (BinaryEqualsIfExists, "BinaryEqualsIfExists"),
            (Bool, "Bool"),
            (BoolIfExists, "BoolIfExists"),
            (DateEquals, "DateEquals"),
            (DateEqualsIfExists, "DateEqualsIfExists"),
            (DateGreaterThan, "DateGreaterThan"),
            (DateGreaterThanEquals, "DateGreaterThanEquals"),
            (DateGreaterThanEqualsIfExists, "DateGreaterThanEqualsIfExists"),
            (DateGreaterThanIfExists, "DateGreaterThanIfExists"),
            (DateLessThan, "DateLessThan"),
            (DateLessThanEquals, "DateLessThanEquals"),
            (DateLessThanEqualsIfExists, "DateLessThanEqualsIfExists"),
            (DateLessThanIfExists, "DateLessThanIfExists"),
            (DateNotEquals, "DateNotEquals"),
            (DateNotEqualsIfExists, "DateNotEqualsIfExists"),
            (IpAddress, "IpAddress"),
            (IpAddressIfExists, "IpAddressIfExists"),
            (NotIpAddress, "NotIpAddress"),
            (NotIpAddressIfExists, "NotIpAddressIfExists"),
            (Null, "Null"),
            (NumericEquals, "NumericEquals"),
            (NumericEqualsIfExists, "NumericEqualsIfExists"),
            (NumericGreaterThan, "NumericGreaterThan"),
            (NumericGreaterThanEquals, "NumericGreaterThanEquals"),
            (NumericGreaterThanEqualsIfExists, "NumericGreaterThanEqualsIfExists"),
            (NumericGreaterThanIfExists, "NumericGreaterThanIfExists"),
            (NumericLessThan, "NumericLessThan"),
            (NumericLessThanEquals, "NumericLessThanEquals"),
            (NumericLessThanEqualsIfExists, "NumericLessThanEqualsIfExists"),
            (NumericLessThanIfExists, "NumericLessThanIfExists"),
            (NumericNotEquals, "NumericNotEquals"),
            (NumericNotEqualsIfExists, "NumericNotEqualsIfExists"),
            (StringEquals, "StringEquals"),
            (StringEqualsIfExists, "StringEqualsIfExists"),
            (StringEqualsIgnoreCase, "StringEqualsIgnoreCase"),
            (StringEqualsIgnoreCaseIfExists, "StringEqualsIgnoreCaseIfExists"),
            (StringLike, "StringLike"),
            (StringLikeIfExists, "StringLikeIfExists"),
            (StringNotEquals, "StringNotEquals"),
            (StringNotEqualsIfExists, "StringNotEqualsIfExists"),
            (StringNotEqualsIgnoreCase, "StringNotEqualsIgnoreCase"),
            (StringNotEqualsIgnoreCaseIfExists, "StringNotEqualsIgnoreCaseIfExists"),
            (StringNotLike, "StringNotLike"),
            (StringNotLikeIfExists, "StringNotLikeIfExists"),
        ];

        for (item, expected) in items {
            assert_eq!(format!("{}", item), expected);
        }
    }
}