solti_model/domain/selector/operator.rs
1//! # Selector operator
2//!
3//! [`SelectorOperator`] defines set-based label comparisons.
4
5use std::fmt;
6
7use serde::{Deserialize, Serialize};
8
9/// Set-based operator for [`super::SelectorRequirement`].
10///
11/// | Operator | Values | Match |
12/// |----------------|-----------|---------------------------------------------------|
13/// | `In` | non-empty | key exists and value is in `values` |
14/// | `NotIn` | non-empty | key is absent or value is not in `values` |
15/// | `Exists` | empty | key exists |
16/// | `DoesNotExist` | empty | key is absent |
17///
18/// ## Example
19///
20/// ```
21/// use solti_model::SelectorOperator;
22///
23/// assert_eq!(SelectorOperator::DoesNotExist.to_string(), "DoesNotExist");
24/// ```
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
26#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
27#[non_exhaustive]
28pub enum SelectorOperator {
29 /// Label value must be one of `values`.
30 In,
31 /// Label is absent or its value is not in `values`.
32 NotIn,
33 /// Label key must exist.
34 Exists,
35 /// Label key must not exist.
36 DoesNotExist,
37}
38
39impl fmt::Display for SelectorOperator {
40 #[inline]
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::In => f.write_str("In"),
44 Self::NotIn => f.write_str("NotIn"),
45 Self::Exists => f.write_str("Exists"),
46 Self::DoesNotExist => f.write_str("DoesNotExist"),
47 }
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn display_and_serde_use_operator_names() {
57 for (operator, name) in [
58 (SelectorOperator::In, "In"),
59 (SelectorOperator::NotIn, "NotIn"),
60 (SelectorOperator::Exists, "Exists"),
61 (SelectorOperator::DoesNotExist, "DoesNotExist"),
62 ] {
63 assert_eq!(operator.to_string(), name);
64 let json = serde_json::to_string(&operator).unwrap();
65 let back: SelectorOperator = serde_json::from_str(&json).unwrap();
66 assert_eq!(back, operator);
67 }
68 }
69}