qubit_metadata/filter/
metadata_filter.rs1use std::cell::RefCell;
11#[cfg(feature = "json")]
12use std::io::Write;
13use std::rc::Rc;
14
15#[cfg(feature = "json")]
16use qubit_budget::json::JsonDecodeSession;
17#[cfg(feature = "json")]
18use qubit_budget::json::JsonEncodeLimits;
19#[cfg(feature = "json")]
20use qubit_budget::json::JsonEncodeSession;
21#[cfg(feature = "json")]
22use qubit_json::decode::JsonDecoder;
23#[cfg(feature = "json")]
24use qubit_json::encode::JsonEncoder;
25use qubit_utils::Transient;
26#[cfg(feature = "json")]
27use qubit_value::ValueWireEncodePreflight;
28use serde::Deserialize;
29use serde::Deserializer;
30use serde::Serialize;
31use serde::Serializer;
32use serde::de;
33use serde::de::DeserializeSeed;
34use serde::ser::Error as SerError;
35
36use super::metadata_filter_builder::MetadataFilterBuilder;
37#[cfg(feature = "json")]
38use super::wire::METADATA_FILTER_WIRE_VERSION_V1;
39use super::wire::MetadataFilterWireV1Ref;
40use super::wire::MetadataFilterWireV1Seed;
41#[cfg(feature = "schema")]
42use crate::Condition;
43use crate::FilterExpression;
44#[cfg(feature = "json")]
45use crate::FilterExpressionView;
46use crate::FilterLimits;
47use crate::FilterMatchOptions;
48use crate::Metadata;
49#[cfg(feature = "schema")]
50use crate::MetadataResult;
51#[cfg(feature = "json")]
52use crate::metadata_limits::MetadataLimits;
53
54#[derive(Debug, Clone, PartialEq)]
77pub struct MetadataFilter {
78 expression: FilterExpression,
80 options: FilterMatchOptions,
82 limits: Transient<FilterLimits>,
84}
85
86impl MetadataFilter {
87 #[inline]
94 #[must_use = "the constructed all-matching filter should be used"]
95 pub fn all() -> Self {
96 Self::new(
97 FilterExpression::match_all(),
98 FilterMatchOptions::default(),
99 FilterLimits::MAX,
100 )
101 }
102
103 #[inline]
110 #[must_use = "the constructed no-match filter should be used"]
111 pub fn none() -> Self {
112 Self::new(
113 FilterExpression::match_none(),
114 FilterMatchOptions::default(),
115 FilterLimits::MAX,
116 )
117 }
118
119 #[inline]
121 #[must_use]
122 pub const fn builder() -> MetadataFilterBuilder {
123 MetadataFilterBuilder::new()
124 }
125
126 pub fn deserialize_with_filter_limits<'de, D>(
145 deserializer: D,
146 receiver_limits: FilterLimits,
147 ) -> Result<Self, D::Error>
148 where
149 D: Deserializer<'de>,
150 {
151 let error_slot = Rc::new(RefCell::new(None));
152 let wire = MetadataFilterWireV1Seed::new(receiver_limits, Rc::clone(&error_slot))
153 .deserialize(deserializer)
154 .map_err(|error| {
155 error_slot
156 .borrow_mut()
157 .take()
158 .map_or_else(|| de::Error::custom(error), de::Error::custom)
159 })?;
160 wire.into_filter(receiver_limits).map_err(de::Error::custom)
161 }
162
163 #[cfg(feature = "json")]
181 #[inline]
182 pub fn decode_json_slice(input: &[u8]) -> Result<Self, crate::MetadataWireDecodeError> {
183 Self::decode_json_slice_with_limits(input, MetadataLimits::default(), FilterLimits::MAX)
184 }
185
186 #[cfg(feature = "json")]
210 pub fn decode_json_slice_with_limits(
211 input: &[u8],
212 limits: MetadataLimits,
213 receiver_filter_limits: FilterLimits,
214 ) -> Result<Self, crate::MetadataWireDecodeError> {
215 limits
216 .validate()
217 .map_err(crate::MetadataWireDecodeError::InvalidLimits)?;
218 let mut decoder = JsonDecoder::new(JsonDecodeSession::from_limits(limits.json_decode()));
219 let error_slot = Rc::new(RefCell::new(None));
220 let wire = decoder
221 .decode_seed_utf8(
222 MetadataFilterWireV1Seed::new(receiver_filter_limits, Rc::clone(&error_slot)),
223 input,
224 )
225 .map_err(|error| {
226 error_slot.borrow_mut().take().map_or_else(
227 || Into::<crate::MetadataWireDecodeError>::into(error),
228 crate::MetadataWireDecodeError::Filter,
229 )
230 })?;
231 if wire.version() != METADATA_FILTER_WIRE_VERSION_V1 {
232 return Err(crate::MetadataWireDecodeError::UnsupportedVersion {
233 expected: METADATA_FILTER_WIRE_VERSION_V1,
234 actual: wire.version(),
235 });
236 }
237 wire.into_filter(receiver_filter_limits)
238 .map_err(crate::MetadataWireDecodeError::Filter)
239 }
240
241 #[cfg(feature = "json")]
243 pub fn to_json_vec(&self) -> Result<Vec<u8>, crate::MetadataWireEncodeError> {
244 self.to_json_vec_with_limits(crate::metadata_limits::default_json_encode_limits())
245 }
246
247 #[cfg(feature = "json")]
258 pub fn to_json_vec_with_limits(&self, limits: JsonEncodeLimits) -> Result<Vec<u8>, crate::MetadataWireEncodeError> {
259 self.preflight_wire_values(limits)?;
260 let session = JsonEncodeSession::from_limits(limits);
261 JsonEncoder::new(session).to_vec(self).map_err(Into::into)
262 }
263
264 #[cfg(feature = "json")]
266 pub fn to_json_writer<W>(&self, writer: W) -> Result<(), crate::MetadataWireEncodeError>
267 where
268 W: Write,
269 {
270 self.to_json_writer_with_limits(writer, crate::metadata_limits::default_json_encode_limits())
271 }
272
273 #[cfg(feature = "json")]
286 pub fn to_json_writer_with_limits<W>(
287 &self,
288 writer: W,
289 limits: JsonEncodeLimits,
290 ) -> Result<(), crate::MetadataWireEncodeError>
291 where
292 W: Write,
293 {
294 self.preflight_wire_values(limits)?;
295 let session = JsonEncodeSession::from_limits(limits);
296 JsonEncoder::new(session)
297 .write_buffered(writer, self)
298 .map_err(Into::into)
299 }
300
301 #[inline]
303 pub(crate) const fn new(expression: FilterExpression, options: FilterMatchOptions, limits: FilterLimits) -> Self {
304 Self {
305 expression,
306 options,
307 limits: Transient::new(limits),
308 }
309 }
310
311 #[inline]
313 #[must_use = "the filter expression should be inspected"]
314 pub const fn expression(&self) -> &FilterExpression {
315 &self.expression
316 }
317
318 #[inline]
320 #[must_use]
321 pub const fn options(&self) -> FilterMatchOptions {
322 self.options
323 }
324
325 #[inline]
327 #[must_use = "the filter limits should be inspected"]
328 pub const fn limits(&self) -> FilterLimits {
329 *self.limits.get()
330 }
331
332 #[cfg(feature = "json")]
334 fn preflight_wire_values(&self, limits: JsonEncodeLimits) -> Result<(), crate::MetadataWireEncodeError> {
335 fn visit(
336 expression: &FilterExpression,
337 checker: &mut ValueWireEncodePreflight,
338 ) -> Result<(), crate::MetadataWireEncodeError> {
339 match expression.view() {
340 FilterExpressionView::Condition(condition) => condition.visit_operands(&mut |value| {
341 checker.check_value(value).map_err(crate::MetadataWireEncodeError::from)
342 }),
343 FilterExpressionView::And(children) | FilterExpressionView::Or(children) => {
344 for child in children {
345 visit(child, checker)?;
346 }
347 Ok(())
348 }
349 FilterExpressionView::Not(inner) => visit(inner, checker),
350 FilterExpressionView::True | FilterExpressionView::False => Ok(()),
351 }
352 }
353 let mut checker = ValueWireEncodePreflight::new(limits);
354 visit(&self.expression, &mut checker)
355 }
356
357 #[inline]
359 #[must_use]
360 pub fn matches(&self, metadata: &Metadata) -> bool {
361 self.expression.evaluate(metadata, self.options).is_match()
362 }
363
364 #[cfg(feature = "schema")]
370 #[inline]
371 pub(crate) fn visit_conditions<F>(&self, mut visitor: F) -> MetadataResult<()>
372 where
373 F: FnMut(&Condition) -> MetadataResult<()>,
374 {
375 self.expression.visit_conditions(&mut visitor)
376 }
377}
378
379impl Serialize for MetadataFilter {
380 #[inline]
382 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
383 where
384 S: Serializer,
385 {
386 MetadataFilterWireV1Ref::try_from(self)
387 .map_err(<S::Error as SerError>::custom)?
388 .serialize(serializer)
389 }
390}
391
392impl<'de> Deserialize<'de> for MetadataFilter {
393 #[inline]
395 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
396 where
397 D: Deserializer<'de>,
398 {
399 Self::deserialize_with_filter_limits(deserializer, FilterLimits::MAX)
400 }
401}