qubit_metadata/
metadata_filter.rs1use serde::{
32 Deserialize,
33 Serialize,
34};
35
36use crate::{
37 Condition,
38 Metadata,
39};
40
41#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub enum MetadataFilter {
62 Condition(Condition),
64 And(Vec<MetadataFilter>),
66 Or(Vec<MetadataFilter>),
68 Not(Box<MetadataFilter>),
70}
71
72impl MetadataFilter {
73 #[inline]
77 pub fn equal<T: Serialize>(key: impl Into<String>, value: T) -> Self {
78 Self::Condition(Condition::Equal {
79 key: key.into(),
80 value: serde_json::to_value(value)
81 .expect("MetadataFilter::equal: value must be serializable"),
82 })
83 }
84
85 #[inline]
87 pub fn not_equal<T: Serialize>(key: impl Into<String>, value: T) -> Self {
88 Self::Condition(Condition::NotEqual {
89 key: key.into(),
90 value: serde_json::to_value(value)
91 .expect("MetadataFilter::not_equal: value must be serializable"),
92 })
93 }
94
95 #[inline]
97 pub fn greater<T: Serialize>(key: impl Into<String>, value: T) -> Self {
98 Self::Condition(Condition::Greater {
99 key: key.into(),
100 value: serde_json::to_value(value)
101 .expect("MetadataFilter::greater: value must be serializable"),
102 })
103 }
104
105 #[inline]
107 pub fn greater_equal<T: Serialize>(key: impl Into<String>, value: T) -> Self {
108 Self::Condition(Condition::GreaterEqual {
109 key: key.into(),
110 value: serde_json::to_value(value)
111 .expect("MetadataFilter::greater_equal: value must be serializable"),
112 })
113 }
114
115 #[inline]
117 pub fn less<T: Serialize>(key: impl Into<String>, value: T) -> Self {
118 Self::Condition(Condition::Less {
119 key: key.into(),
120 value: serde_json::to_value(value)
121 .expect("MetadataFilter::less: value must be serializable"),
122 })
123 }
124
125 #[inline]
127 pub fn less_equal<T: Serialize>(key: impl Into<String>, value: T) -> Self {
128 Self::Condition(Condition::LessEqual {
129 key: key.into(),
130 value: serde_json::to_value(value)
131 .expect("MetadataFilter::less_equal: value must be serializable"),
132 })
133 }
134
135 #[inline]
137 pub fn exists(key: impl Into<String>) -> Self {
138 Self::Condition(Condition::Exists { key: key.into() })
139 }
140
141 #[inline]
143 pub fn not_exists(key: impl Into<String>) -> Self {
144 Self::Condition(Condition::NotExists { key: key.into() })
145 }
146
147 #[inline]
149 pub fn in_values<T, I>(key: impl Into<String>, values: I) -> Self
150 where
151 T: Serialize,
152 I: IntoIterator<Item = T>,
153 {
154 let values = values
155 .into_iter()
156 .map(|v| {
157 serde_json::to_value(v)
158 .expect("MetadataFilter::in_values: each value must be serializable")
159 })
160 .collect();
161 Self::Condition(Condition::In {
162 key: key.into(),
163 values,
164 })
165 }
166
167 #[inline]
169 pub fn not_in_values<T, I>(key: impl Into<String>, values: I) -> Self
170 where
171 T: Serialize,
172 I: IntoIterator<Item = T>,
173 {
174 let values = values
175 .into_iter()
176 .map(|v| {
177 serde_json::to_value(v)
178 .expect("MetadataFilter::not_in_values: each value must be serializable")
179 })
180 .collect();
181 Self::Condition(Condition::NotIn {
182 key: key.into(),
183 values,
184 })
185 }
186
187 #[inline]
194 #[must_use]
195 pub fn and(self, other: MetadataFilter) -> Self {
196 match self {
197 MetadataFilter::And(mut children) => {
198 children.push(other);
199 MetadataFilter::And(children)
200 }
201 _ => MetadataFilter::And(vec![self, other]),
202 }
203 }
204
205 #[inline]
210 #[must_use]
211 pub fn or(self, other: MetadataFilter) -> Self {
212 match self {
213 MetadataFilter::Or(mut children) => {
214 children.push(other);
215 MetadataFilter::Or(children)
216 }
217 _ => MetadataFilter::Or(vec![self, other]),
218 }
219 }
220
221 #[allow(clippy::should_implement_trait)]
223 #[inline]
224 #[must_use]
225 pub fn not(self) -> Self {
226 !self
227 }
228
229 #[inline]
233 pub fn matches(&self, meta: &Metadata) -> bool {
234 match self {
235 MetadataFilter::Condition(cond) => cond.matches(meta),
236 MetadataFilter::And(children) => children.iter().all(|f| f.matches(meta)),
237 MetadataFilter::Or(children) => children.iter().any(|f| f.matches(meta)),
238 MetadataFilter::Not(inner) => !inner.matches(meta),
239 }
240 }
241}
242
243impl std::ops::Not for MetadataFilter {
244 type Output = MetadataFilter;
245
246 #[inline]
247 fn not(self) -> Self::Output {
248 MetadataFilter::Not(Box::new(self))
249 }
250}