dynamodb_expression/condition/
mod.rs1mod and;
6mod attribute_exists;
7mod attribute_not_exists;
8pub mod attribute_type;
9mod begins_with;
10mod between;
11mod comparison;
12mod contains;
13mod in_;
14mod not;
15mod or;
16mod parenthetical;
17
18pub use and::And;
19pub use attribute_exists::AttributeExists;
20pub use attribute_not_exists::AttributeNotExists;
21pub use attribute_type::AttributeType;
22pub use begins_with::BeginsWith;
23pub use between::Between;
24pub use comparison::{
25 equal, greater_than, greater_than_or_equal, less_than, less_than_or_equal, not_equal,
26 Comparator, Comparison,
27};
28pub use contains::Contains;
29pub use in_::In;
30pub use not::Not;
31pub use or::Or;
32pub use parenthetical::Parenthetical;
33
34use core::{fmt, ops};
35
36#[must_use = "Use in a DynamoDB expression with \
43 `Expression::builder().with_condition(condition)` or \
44 `Expression::builder().with_filter(condition)`"]
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum Condition {
47 AttributeExists(AttributeExists),
48 AttributeNotExists(AttributeNotExists),
49 AttributeType(AttributeType),
50 BeginsWith(BeginsWith),
51 Between(Between),
52 Contains(Contains),
53 In(In),
54 Not(Not),
55 And(And),
56 Or(Or),
57 Comparison(Comparison),
58 Parenthetical(Parenthetical),
59}
60
61impl Condition {
62 pub fn and<R>(self, right: R) -> Self
85 where
86 R: Into<Condition>,
87 {
88 Self::And(And {
89 left: self.into(),
90 right: right.into().into(),
91 })
92 }
93
94 pub fn or<R>(self, right: R) -> Self
117 where
118 R: Into<Condition>,
119 {
120 Self::Or(Or {
121 left: self.into(),
122 right: right.into().into(),
123 })
124 }
125
126 #[rustversion::attr(before(1.81), allow(clippy::should_implement_trait))]
147 #[rustversion::attr(
148 since(1.81),
149 expect(
150 clippy::should_implement_trait,
151 reason = "This is for the DynamoDB `NOT` operator, not the Rust `!` operator."
152 )
153 )]
154 pub fn not(self) -> Self {
155 Self::Not(Not::from(self))
156 }
157
158 pub fn parenthesize(self) -> Self {
181 Self::Parenthetical(Parenthetical::from(self))
182 }
183}
184
185impl ops::Not for Condition {
186 type Output = Condition;
187
188 fn not(self) -> Self::Output {
209 Condition::not(self)
210 }
211}
212
213impl fmt::Display for Condition {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 match self {
216 Condition::AttributeExists(condition) => condition.fmt(f),
217 Condition::AttributeNotExists(condition) => condition.fmt(f),
218 Condition::AttributeType(condition) => condition.fmt(f),
219 Condition::BeginsWith(condition) => condition.fmt(f),
220 Condition::Between(condition) => condition.fmt(f),
221 Condition::Contains(condition) => condition.fmt(f),
222 Condition::In(condition) => condition.fmt(f),
223 Condition::Not(condition) => condition.fmt(f),
224 Condition::And(condition) => condition.fmt(f),
225 Condition::Or(condition) => condition.fmt(f),
226 Condition::Comparison(condition) => condition.fmt(f),
227 Condition::Parenthetical(condition) => condition.fmt(f),
228 }
229 }
230}
231
232impl From<AttributeExists> for Condition {
233 fn from(condition: AttributeExists) -> Self {
234 Self::AttributeExists(condition)
235 }
236}
237
238impl From<AttributeNotExists> for Condition {
239 fn from(condition: AttributeNotExists) -> Self {
240 Self::AttributeNotExists(condition)
241 }
242}
243
244impl From<AttributeType> for Condition {
245 fn from(condition: AttributeType) -> Self {
246 Self::AttributeType(condition)
247 }
248}
249
250impl From<BeginsWith> for Condition {
251 fn from(condition: BeginsWith) -> Self {
252 Self::BeginsWith(condition)
253 }
254}
255
256impl From<Between> for Condition {
257 fn from(condition: Between) -> Self {
258 Self::Between(condition)
259 }
260}
261
262impl From<Contains> for Condition {
263 fn from(condition: Contains) -> Self {
264 Self::Contains(condition)
265 }
266}
267
268impl From<In> for Condition {
269 fn from(condition: In) -> Self {
270 Self::In(condition)
271 }
272}
273
274impl From<Not> for Condition {
275 fn from(condition: Not) -> Self {
276 Self::Not(condition)
277 }
278}
279
280impl From<And> for Condition {
281 fn from(condition: And) -> Self {
282 Self::And(condition)
283 }
284}
285
286impl From<Or> for Condition {
287 fn from(condition: Or) -> Self {
288 Self::Or(condition)
289 }
290}
291
292impl From<Comparison> for Condition {
293 fn from(condition: Comparison) -> Self {
294 Self::Comparison(condition)
295 }
296}
297
298impl From<Parenthetical> for Condition {
299 fn from(condition: Parenthetical) -> Self {
300 Self::Parenthetical(condition)
301 }
302}
303
304impl From<Condition> for String {
308 fn from(condition: Condition) -> Self {
309 condition.to_string()
311 }
312}
313
314#[cfg(test)]
315pub(crate) mod test {
316 use pretty_assertions::assert_eq;
317
318 use crate::path::Path;
319
320 use super::{
321 comparison::{greater_than, less_than},
322 Condition,
323 };
324
325 pub fn cmp_a_gt_b() -> Condition {
327 Condition::Comparison(greater_than(
328 "a".parse::<Path>().unwrap(),
329 "b".parse::<Path>().unwrap(),
330 ))
331 }
332
333 pub fn cmp_c_lt_d() -> Condition {
335 Condition::Comparison(less_than(
336 "c".parse::<Path>().unwrap(),
337 "d".parse::<Path>().unwrap(),
338 ))
339 }
340
341 #[test]
342 fn display() {
343 assert_eq!("a > b", cmp_a_gt_b().to_string());
344 assert_eq!("c < d", cmp_c_lt_d().to_string());
345 }
346
347 #[test]
348 fn and() {
349 use crate::Path;
350 use pretty_assertions::assert_eq;
351
352 let a = "a".parse::<Path>().unwrap();
353 let b = "b".parse::<Path>().unwrap();
354 let c = "c".parse::<Path>().unwrap();
355 let d = "d".parse::<Path>().unwrap();
356
357 let condition = a.greater_than(b).and(c.less_than(d));
358 assert_eq!("a > b AND c < d", condition.to_string());
359 }
360
361 #[test]
362 fn or() {
363 use crate::Path;
364 use pretty_assertions::assert_eq;
365
366 let a = "a".parse::<Path>().unwrap();
367 let b = "b".parse::<Path>().unwrap();
368 let c = "c".parse::<Path>().unwrap();
369 let d = "d".parse::<Path>().unwrap();
370
371 let condition = a.greater_than(b).or(c.less_than(d));
372 assert_eq!("a > b OR c < d", condition.to_string());
373 }
374
375 #[test]
376 fn not() {
377 use crate::Path;
378 use pretty_assertions::assert_eq;
379
380 let a = "a".parse::<Path>().unwrap();
381 let b = "b".parse::<Path>().unwrap();
382
383 let condition = a.greater_than(b).not();
384 assert_eq!("NOT a > b", condition.to_string());
385 }
386
387 #[test]
388 fn not_operator() {
389 use crate::Path;
390 use pretty_assertions::assert_eq;
391
392 let a = "a".parse::<Path>().unwrap();
393 let b = "b".parse::<Path>().unwrap();
394
395 let condition = !a.greater_than(b);
396 assert_eq!("NOT a > b", condition.to_string());
397 }
398}