django_query/filtering/
mod.rs

1//! # Create filters for Rust objects from query URLs
2//!
3//! Django encodes database queries into URL query strings in a way
4//! that can be frustrating to replicate ad-hoc. The simplest query
5//! parts are things like `foo=3` which means the column `foo` must
6//! have the exact value 3. More precisely, it means: "apply the
7//! default operator for column `foo`, to the contents of that column
8//! for each row, with a right hand side of 3, and only include the
9//! row if the result is `true`. The default operator is usually
10//! `exact`.
11//!
12//! There are three ways Django extends this simple model. Firstly,
13//! it's possible to specify a different operator than the default
14//! for some columns. Standard Django operators include `contains`,
15//! `gt`, `lt`, `in`, `iexact` and `isnull`. These are written in
16//! the query string as, for example, `foo__lt=3`, which filters on
17//! `foo < 3`.
18//!
19//! Secondly, columns can be multivalued. If in the preceding example
20//! column `foo` an array of integers, then `foo=3` would mean that
21//! the array must contain 3. In general, for collection valued
22//! columns, a filter is considered to pass if any individual element
23//! passes.
24//!
25//! Thirdly, there can be relations between tables. For example, if
26//! the column `foo` was actually of some complex type, drawn from a
27//! different table, then it's possible to filter within `foo`. Suppose
28//! the table for the type of member `foo` has a column `bar`, then
29//! our query string could be `foo__bar=3` to mean "select all objects
30//! whose member `foo` has a member `bar` whose value is 3".
31//!
32//! All of the preceding features combine, so it's possible to end up
33//! with query strings like `foo__bar__baz__lt=5` with the meaning
34//! (due to the structure with collections): "include objects within
35//! whose collection for member `foo`, one item has a member `bar`,
36//! and within that object's member `bar` one item has a member `baz`,
37//! and within the collection of integers for that object's member
38//! `baz` one integer is less than 5".
39//!
40//! ## Overview
41//!
42//! The main trait in this module is [`Filterable`] which has an
43//! associated derive macro [`macro@Filterable`]. Deriving
44//! [`Filterable`] means the type can describe the filtering it
45//! supports, and the derive macro allows you to set up the filters
46//! inline in the type definition.  An [`OperatorSet`] can be
47//! constructed for any [`Filterable`] type, which can convert a URL
48//! fragment from a django-style query string into a boxed [`Filter`]
49//! object.
50//!
51//! Example:
52//! ```rust
53//! use django_query::filtering::{Filterable, OperatorSet};
54//!
55//! #[derive(Filterable)]
56//! struct Bar {
57//!   #[django(op(lt))]
58//!   a: i32,
59//! }
60//!
61//! #[derive(Filterable)]
62//! struct Foo {
63//!   #[django(op(lt))]
64//!   a: i32,
65//!   #[django(traverse)]
66//!   b: Bar,
67//! }
68//!
69//! let foo = Foo { a: 5, b: Bar { a: 0 } };
70//! let qr = OperatorSet::<Foo>::new();
71//! let filter = qr.create_filter_from_query("b__a__lt=1").unwrap();
72//! assert!(filter.filter_one(&foo));
73//! let filter = qr.create_filter_from_query("b__a__lt=0").unwrap();
74//! assert!(!filter.filter_one(&foo));
75//! ```
76//!
77//! Because [`Filter`] objects produced by parsing are boxed, there is
78//! virtual function call overhead when using them. This can be
79//! minimised by using the provided [`filter_vec`](Filter::filter_vec)
80//! method to filter an entire [`Vec`] at a time, instead of testing
81//! values individually with [`filter_one`](Filter::filter_one).
82//!
83//! Note that self-including types - types that have members of their
84//! own type at any level of indirection - cannot be handled by this
85//! crate because of its commitment to monomorphism within filters. It
86//! must always be possible to write out all the valid left hand sides
87//! that could occur in a filter, and this will in fact be done
88//! automatically when an [`OperatorSet`] is constructed.
89
90pub mod ops;
91
92use core::ops::Deref;
93
94use std::fmt::Debug;
95use std::sync::Arc;
96
97use thiserror::Error;
98
99/// Errors produced by filtering.
100#[derive(Debug, Error)]
101pub enum FilterError {
102    /// There is no equals sign in the query string.
103    #[error("malformed query has no '='")]
104    MissingEquals,
105    /// An operator was requested that isn't defined for the target type.
106    #[error("no such operator '{0}'")]
107    NoOperator(String),
108    /// The requested field is not present on the target type.
109    #[error("no such field '{0}'")]
110    NoField(String),
111    /// Failed to instantiate a [`Filter`].
112    #[error(transparent)]
113    Instantiation(#[from] anyhow::Error),
114}
115
116/// A type that Django filters can work on.
117///
118/// Django filters are defined in terms of operators on
119/// simple values, like strings and numbers. There
120/// is additional complexity, however, because these simple
121/// specifications can also be applied to collections and nullable
122/// values.
123///
124/// All types that occur naturally in Django queries can be made
125/// [`Operable`], but so can, for example, [`Vec<T>`] and
126/// [`Option<T>`], when the `T` in question is itself
127/// [`Operable`]. It's up to an [`Operable`] implementation to decide
128/// how to take an operator on its base type and apply it to its
129/// contents, for example by iterating over whatever contents it has.
130///
131/// The implementations for [`Vec<T>`] and [`Option<T>`] match the default
132/// behaviour in Django.
133pub trait Operable {
134    /// The underlying type that operators should be applied to.
135    type Base;
136    /// Apply `op` across our contents.
137    fn apply<O: Operator<Self::Base>>(&self, op: &O) -> bool;
138}
139
140impl<T> Operable for Vec<T>
141where
142    T: Operable,
143{
144    type Base = <T as Operable>::Base;
145    fn apply<O: Operator<Self::Base>>(&self, op: &O) -> bool {
146        if self.is_empty() {
147            op.empty_collection()
148        } else {
149            self.iter().any(|x| x.apply(op))
150        }
151    }
152}
153
154impl<T> Operable for Option<T>
155where
156    T: Operable,
157{
158    type Base = <T as Operable>::Base;
159    fn apply<O: Operator<Self::Base>>(&self, op: &O) -> bool {
160        if let Some(x) = self {
161            x.apply(op)
162        } else {
163            op.null_option()
164        }
165    }
166}
167
168/// A wrapper for a field of any type.
169///
170/// A [`Field`] allows us to apply an [`Operator`] to one field of a
171/// structure. You will normally generate implementations of [`Field`]
172/// using the [`Filterable`] derive macro for your type. The key use
173/// of [`Field`] is in traversing nested structures: whereas a
174/// [`Member`] represents applying an operator to an [`Operable`]
175/// value, the value of a [`Field`] can be arbitrary, and is often a
176/// structured type.
177pub trait Field<R>: Clone {
178    /// The type an operator on this field must accept.
179    type Value;
180    /// Apply `op` to a particular field of `data`, and return the
181    /// result.
182    fn apply<O: Operator<Self::Value>>(&self, op: &O, data: &R) -> bool;
183}
184
185/// A wrapper for a field of [`Operable`] type.
186///
187/// A [`Member`] is a filterable field of a structure. You will
188/// normally generate implementations of [`Member`] using the
189/// [`Filterable`] derive macro for your type. Whereas a [`Field`]
190/// provides access for nesting, a [`Member`] is visible to queries,
191/// and will expose a list of supported operators to a
192/// [`MemberVisitor`].
193pub trait Member<'a, R>: Clone + 'a {
194    /// The type of the member's data, which must be [`Operable`] so
195    /// that Django filtering queries can be made against it.
196    type Value: Operable;
197    /// Apply an operator to the given field of `data`, returning the
198    /// result.
199    fn apply<O: Operator<<Self::Value as Operable>::Base>>(&self, op: &O, data: &R) -> bool;
200    /// `visitor` will be called with each of the supported operator
201    /// classes for this member. This is used to build up a list
202    /// of supported queries in an [`OperatorSet`].
203    fn accept_visitor<V: MemberVisitor<'a, Self, R, Self::Value>>(&self, visitor: &mut V);
204}
205
206/// Receive descriptions of the filters a [`Member`] supports.
207///
208/// A [`MemberVisitor`] can be passed to
209/// [`accept_visitor`](Member::accept_visitor) on a [`Member`] to
210/// receive a callback for each [`OperatorClass`] that [`Member`]
211/// supports.
212pub trait MemberVisitor<'a, F, R, T>
213where
214    F: Member<'a, R, Value = T> + Clone,
215{
216    /// This is called by [`Member`] for each [`OperatorClass`] it
217    /// supports. Here:
218    /// - `name` is the name of the operator in queries (e.g. "in")
219    /// - `f` is the [`Member`] itself.
220    /// - `op` is an [`OperatorClass`] with a target type matching the
221    ///   `Member` type.
222    fn visit_operator<O>(&mut self, name: &str, f: &F, op: O)
223    where
224        O: OperatorClass<<T as Operable>::Base>,
225        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
226        T: Operable;
227}
228
229/// A wrapper for a type that can be filtered.
230///
231/// A [`Meta`] holds a representation of a filterable type, similar to
232/// [`Member`] for fields, but now for an entire structured type. When
233/// a type is [`Filterable`] it can produce a [`Meta`] for itself, to
234/// enable discovery of its members and their supported operators.
235pub trait Meta<'a, R> {
236    /// `visitor` will be called with each exposed member of the type.
237    fn accept_visitor<V: MetaVisitor<'a, R>>(&self, visitor: &mut V)
238    where
239        Self: Sized;
240}
241
242/// Receive descriptions of the [`Member`]s a type contains from its [`Meta`].
243///
244/// A [`MetaVisitor`] can be passed to
245/// [`accept_visitor`](Meta::accept_visitor) on [`Meta`] to receive a
246/// callback for each of the filterable members of a type.
247pub trait MetaVisitor<'a, R> {
248    /// This will be called by a [`Meta`] instance for each filterable structure
249    /// member which is [`Operable`]. Here:
250    /// - `name` is the name of the membner, as exposed.
251    /// - `member` is a [`Member`] wrapping that field.
252    /// - `defop` is the default [`OperatorClass`] for that member, which
253    ///    should be applied when no operator is specified (i.e. in
254    ///    the `"record__field"` case as opposed to the
255    ///    `"record__field__op"` case)
256    fn visit_member<F, O, T>(&mut self, name: &str, member: &F, defop: O)
257    where
258        F: Member<'a, R, Value = T> + Clone,
259        O: OperatorClass<<T as Operable>::Base>,
260        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
261        T: Operable;
262
263    /// This will be called by  a [`Meta`] instance for each filterable structure field
264    /// that can be traversed. This is true when the field's type is itself
265    /// a structured type, and is not directly filterable. Here:
266    /// - `name` is the name of the field, as exposed.
267    /// - `field` is a [`Field`] wrapping that field (note that
268    ///    there are no exposed operators for a [`Field`], and operators
269    ///    are applied to the record type, since there could not be a single
270    ///    [`Operable::Base`] type.
271    /// - `inner_record` is the [`Meta`] for the field.
272    fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
273    where
274        F: Field<R, Value = U> + Clone + 'a,
275        T: Meta<'a, U>;
276}
277
278struct FieldNestingOperator<'a, O, S, F> {
279    op: &'a O,
280    inner: F,
281    _marker: core::marker::PhantomData<S>,
282}
283
284impl<'a, T, O, F, S> Operator<S> for FieldNestingOperator<'a, O, S, F>
285where
286    O: Operator<T>,
287    F: Field<S, Value = T>,
288{
289    fn apply(&self, value: &S) -> bool {
290        self.inner.apply(self.op, value)
291    }
292}
293
294struct MemberNestingOperator<'a, O, S, F> {
295    op: &'a O,
296    inner: F,
297    _marker: core::marker::PhantomData<S>,
298}
299
300impl<'a, 'b, O, F, S> Operator<S> for MemberNestingOperator<'a, O, S, F>
301where
302    F: Member<'b, S>,
303    O: Operator<<<F as Member<'b, S>>::Value as Operable>::Base>,
304    <F as Member<'b, S>>::Value: Operable,
305{
306    fn apply(&self, value: &S) -> bool {
307        self.inner.apply(self.op, value)
308    }
309}
310
311struct NestedField<F, G> {
312    outer_field: F,
313    inner_field: G,
314}
315
316impl<F, G> Clone for NestedField<F, G>
317where
318    F: Clone,
319    G: Clone,
320{
321    fn clone(&self) -> Self {
322        Self {
323            outer_field: self.outer_field.clone(),
324            inner_field: self.inner_field.clone(),
325        }
326    }
327}
328
329impl<F, G, R, S, T> Field<R> for NestedField<F, G>
330where
331    F: Field<R, Value = S>,
332    G: Field<S, Value = T>,
333{
334    type Value = T;
335    fn apply<O: Operator<Self::Value>>(&'_ self, op: &O, data: &R) -> bool {
336        self.outer_field.apply(
337            &FieldNestingOperator {
338                op,
339                inner: self.inner_field.clone(),
340                _marker: Default::default(),
341            },
342            data,
343        )
344    }
345}
346
347impl<'a, F, G, R, S, T> Member<'a, R> for NestedField<F, G>
348where
349    F: Field<R, Value = S> + 'a,
350    G: Member<'a, S, Value = T>,
351    T: Operable,
352{
353    type Value = T;
354    fn apply<O: Operator<<Self::Value as Operable>::Base>>(&self, op: &O, data: &R) -> bool {
355        self.outer_field.apply(
356            &MemberNestingOperator {
357                op,
358                inner: self.inner_field.clone(),
359                _marker: Default::default(),
360            },
361            data,
362        )
363    }
364
365    fn accept_visitor<V: MemberVisitor<'a, Self, R, <Self as Member<'a, R>>::Value>>(
366        &self,
367        visitor: &mut V,
368    ) {
369        let mut n = NestedMemberVisitor {
370            parent: visitor,
371            field: self,
372            _marker: Default::default(),
373        };
374        self.inner_field.accept_visitor(&mut n);
375    }
376}
377
378trait Nester<'a, R, U, F>
379where
380    F: Field<U, Value = R> + 'a,
381{
382    fn nest_member<G, T>(&self, nested_field: G) -> NestedField<F, G>
383    where
384        G: Member<'a, R, Value = T>,
385        T: Operable;
386
387    fn nest_field<G, T>(&self, inner_field: G) -> NestedField<F, G>
388    where
389        G: Field<R, Value = T> + 'a;
390}
391
392struct NesterImpl<F> {
393    outer_field: F,
394}
395
396impl<'a, R, U, F> Nester<'a, R, U, F> for NesterImpl<F>
397where
398    F: Field<U, Value = R> + Clone + 'a,
399{
400    fn nest_member<G, T>(&self, inner_field: G) -> NestedField<F, G>
401    where
402        G: Member<'a, R, Value = T>,
403        T: Operable,
404    {
405        NestedField {
406            outer_field: self.outer_field.clone(),
407            inner_field,
408        }
409    }
410
411    fn nest_field<G, T>(&self, inner_field: G) -> NestedField<F, G>
412    where
413        G: Field<R, Value = T> + 'a,
414    {
415        NestedField {
416            outer_field: self.outer_field.clone(),
417            inner_field,
418        }
419    }
420}
421
422/// Take a single value and produce a true/false result.
423///
424/// Operators are generally applied by [`Operable`] types, so the
425/// operators themselves can be naive with respect to things like
426/// [`Option<T>`] and collections. For operators that need to know about
427/// special cases, there are the inelegant get-out functions
428/// [`empty_collection`](Operator::empty_collection) and
429/// [`null_option`](Operator::null_option) which can be
430/// implemented. Both return `false` by default.
431///
432/// The standard Django operators are in the
433/// [`ops`] module. Examples are
434/// [`exact`](ops::ExactImpl),
435/// [`in`](ops::InImpl),
436/// [`contains`](ops::ContainsImpl) and so forth.
437pub trait Operator<T> {
438    /// Apply this operator a single value, producing a true/false
439    /// result.
440    fn apply(&self, value: &T) -> bool;
441    /// Return a value for this operator when applied to an empty
442    /// collection.  Implicitly, operators are distributed over
443    /// collections with `any` semantics, so that any `true` result
444    /// means the collection evaluates to `true`. The default
445    /// behaviour for this method is to return `false`, which is
446    /// consistent with those semantics.
447    fn empty_collection(&self) -> bool {
448        false
449    }
450    /// Return a value for this operator when applied to a `None`
451    /// value wrapping its target type (e.g. for an operator on T, we
452    /// are determining the behaviour on Option<T>). This is required
453    /// because we automatically implement all operators on Option<T>,
454    /// but in rare cases the operator's behaviour isn't well captured
455    /// by returning `false` for `None` (e.g for. `isnull`).
456    fn null_option(&self) -> bool {
457        false
458    }
459}
460
461/// Something that can make an operator instance from a right-hand side.
462///
463/// An [`OperatorClass`] can make a particular type of [`Operator`],
464/// performing any needed parsing on the right-hand side of the filter
465/// expression. The main part of parsing a query is in identifying the
466/// [`OperatorClass`] that can handle the requested left hand side; once
467/// that has been done, that [`OperatorClass`] will take over via
468/// [`instantiate`](OperatorClass::instantiate) and construct the
469/// particular [`Operator`] instance to use for that query.
470pub trait OperatorClass<T> {
471    /// The type of [`Operator`] this object can make.
472    type Instance: Operator<T>;
473    /// Create a new [`Operator`], parsing the supplied argument string
474    /// to initialise whatever representation this operator uses to
475    /// match against objects. Since this is a parsing operation, it
476    /// can fail.
477    fn instantiate(&self, rhs: &str) -> Result<Self::Instance, FilterError>;
478}
479
480/// Test whether an objects to see whether it is included in a given
481/// result set.
482///
483/// Each stanza of a query-string results in one [`Filter`] being
484/// constructed. A unique codepath is generated for every combination
485/// of field and operator, which ends up resulting in an efficient
486/// [`Filter`] for each one.
487pub trait Filter<R> {
488    /// Produce a true/false response indicating an in/out result for the object.
489    fn filter_one(&self, data: &R) -> bool;
490    /// Helper method to filter an entire vector by this filter. Note
491    /// that there is no virtual function call overhead here.
492    fn filter_vec(&self, data: &mut Vec<R>) {
493        data.retain(|r| self.filter_one(r))
494    }
495    /// Helper method to filter an entire vector by this filter. Note
496    /// that there is no virtual function call overhead here.
497    fn filter_ref_vec(&self, data: &mut Vec<&R>) {
498        data.retain(|r| self.filter_one(r))
499    }
500}
501
502/// An object that can make a [`Filter`].
503///
504/// An [`OperatorSet`] stores all the possible ways to filter a given type,
505/// but each one can be parameterised by a RHS supplied by the user.
506/// [`FilterClass`] is an object safe trait that allows us to store
507/// these possibilities, and instantiate them into real [`Filter`] objects
508/// when an appropriate RHS is provided.
509pub trait FilterClass<'a, R> {
510    /// Create a new [`Filter`], parsing the `rhs`, which is the argument to
511    /// whatever [`Operator`] this [`Filter`] encompassses.
512    fn instantiate(&self, rhs: &str) -> Result<Box<dyn Filter<R> + 'a>, FilterError>;
513}
514
515struct FilterImpl<F, O> {
516    field: F,
517    operator: O,
518}
519
520impl<F, O> FilterImpl<F, O> {
521    pub fn new(field: F, operator: O) -> Self {
522        Self { field, operator }
523    }
524}
525
526impl<'a, F, O, R> Filter<R> for FilterImpl<F, O>
527where
528    F: Member<'a, R>,
529    <F as Member<'a, R>>::Value: Operable,
530    O: Operator<<<F as Member<'a, R>>::Value as Operable>::Base>,
531{
532    fn filter_one(&self, data: &R) -> bool {
533        self.field.apply(&self.operator, data)
534    }
535}
536
537struct FilterClassImpl<F, O> {
538    field: F,
539    opclass: O,
540}
541
542impl<F, O> FilterClassImpl<F, O> {
543    pub fn new(field: F, opclass: O) -> Self {
544        Self { field, opclass }
545    }
546}
547
548impl<'a, F, O, R, T> FilterClass<'a, R> for FilterClassImpl<F, O>
549where
550    F: Member<'a, R, Value = T> + Clone,
551    O: OperatorClass<<T as Operable>::Base>,
552    <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
553    T: Operable,
554{
555    fn instantiate(&self, rhs: &str) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
556        Ok(Box::new(FilterImpl::new(
557            self.field.clone(),
558            self.opclass.instantiate(rhs)?,
559        )))
560    }
561}
562
563/// Something which can produce a description of how to filter it.
564///
565/// This is the main derivable trait from this file. A type
566/// implementing [`Filterable`] can provide an object, [`Meta`], which
567/// describes its supported fields and their operators.
568pub trait Filterable<'a>: Sized {
569    /// The type which can describe our fields and their operators.
570    type Meta: Meta<'a, Self>;
571    /// Produce an instance of our [`Meta`] type.
572    fn get_meta() -> Self::Meta;
573}
574
575#[doc(hidden)]
576pub struct QueryProcessor<'a, 'q, R> {
577    pub target: &'q str,
578    pub rhs: &'q str,
579    pub result: Option<Result<Box<dyn Filter<R> + 'a>, FilterError>>,
580}
581
582impl<'a, 'q, R> MetaVisitor<'a, R> for QueryProcessor<'a, 'q, R> {
583    fn visit_member<F, O, T>(&mut self, name: &str, field: &F, defop: O)
584    where
585        F: Member<'a, R, Value = T> + Clone,
586        O: OperatorClass<<T as Operable>::Base>,
587        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
588        T: Operable,
589    {
590        if self.target == name {
591            let cls = FilterClassImpl::new(field.clone(), defop);
592            self.result = Some(cls.instantiate(self.rhs));
593        } else if self.target.starts_with(name) {
594            let mut m = QueryMemberProcessor {
595                target: self.target,
596                rhs: self.rhs,
597                name,
598                result: None,
599            };
600            field.accept_visitor(&mut m);
601            self.result = m.result;
602        }
603    }
604
605    fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
606    where
607        F: Field<R, Value = U> + Clone + 'a,
608        T: Meta<'a, U>,
609    {
610        if self.target.starts_with(name) {
611            let mut n = NestedMetaVisitor {
612                parent: self,
613                prefix: name.to_string(),
614                nester: NesterImpl {
615                    outer_field: field.clone(),
616                },
617                _marker: Default::default(),
618            };
619
620            inner_record.accept_visitor(&mut n);
621        }
622    }
623}
624
625struct QueryMemberProcessor<'a, 'b, 'c, R> {
626    target: &'a str,
627    rhs: &'a str,
628    name: &'b str,
629    result: Option<Result<Box<dyn Filter<R> + 'c>, FilterError>>,
630}
631
632impl<'a, 'b, 'c, F, R, T> MemberVisitor<'c, F, R, T> for QueryMemberProcessor<'a, 'b, 'c, R>
633where
634    F: Member<'c, R, Value = T> + Clone,
635    T: Operable,
636{
637    fn visit_operator<O>(&mut self, name: &str, field: &F, op: O)
638    where
639        O: OperatorClass<<T as Operable>::Base>,
640        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'c,
641    {
642        if format!("{}__{}", self.name, name) == self.target {
643            let cls = FilterClassImpl::new(field.clone(), op);
644            self.result = Some(cls.instantiate(self.rhs));
645        }
646    }
647}
648
649/// A collection of filters for a particular type.
650///
651/// An [`OperatorSet`] can be created for any type which implements
652/// [`Filterable`]. Its constructor supplies a visitor to the type's
653/// [`Meta`] type, and constructs the necessary [`FilterClass`] objects.
654/// It can be used directly to convert incoming query pairs from
655/// Django-style query URLs into appropriate [`Filter`] objects.
656pub struct OperatorSet<R> {
657    _marker: core::marker::PhantomData<R>,
658}
659
660impl<'a, R: Filterable<'a>> Default for OperatorSet<R> {
661    fn default() -> Self {
662        Self::new()
663    }
664}
665
666impl<'a, R: Filterable<'a>> OperatorSet<R> {
667    /// Create a new [`OperatorSet`], using the [`Meta`] record
668    /// from the target type
669    pub fn new() -> Self {
670        Self {
671            _marker: Default::default(),
672        }
673    }
674
675    /// Create a new filter from a decomposed URL.
676    ///
677    /// Note that the decomposition is ambiguous, so
678    /// [`create_filter_from_query_pair`](OperatorSet::create_filter_from_query_pair)
679    /// is often preferable. The ambiguity arises because there may be
680    /// no operator part, and the field part may have arbitrarily many
681    /// parts.  Since everything is separated with double underscores
682    /// there is no way without additional information to distinguish
683    /// an expression with an explicit operator from an expression on
684    /// a nested field with an implicit operator.  Here
685    /// - `field` is the field specification part of the string,
686    ///    including any nested fields.
687    /// - `operator` is the operator specification, if any.
688    /// - `rhs` is the argument part, after the `=` in the URL
689    ///    section.
690    pub fn create_filter(
691        &self,
692        field: &str,
693        operator: Option<&str>,
694        rhs: &str,
695    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
696        let lhs = if let Some(op) = operator {
697            format!("{}__{}", field, op)
698        } else {
699            field.to_string()
700        };
701
702        self.create_filter_from_query_pair(&lhs, rhs)
703    }
704
705    /// Create a new filter from a fragment of query URL.
706    ///
707    /// The expected input is a `lhs=rhs` pair from a query string,
708    /// with `lhs` and `rhs` given separately. The output will either
709    /// be an error, or a [`Filter`] which can apply the specified
710    /// test to objects of the target type, returning either `true`
711    /// (include) or `false` (exclude).
712    pub fn create_filter_from_query_pair(
713        &self,
714        lhs: &str,
715        rhs: &str,
716    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
717        let mut p = QueryProcessor {
718            target: lhs,
719            rhs,
720            result: None,
721        };
722
723        R::get_meta().accept_visitor(&mut p);
724
725        p.result
726            .ok_or_else(|| FilterError::NoField(lhs.to_string()))?
727    }
728
729    /// Create a new filter from a fragment of query URL.
730    ///
731    /// The expected input is a `lhs=rhs` pair from a query string,
732    /// with `lhs` and `rhs` given together in a single string. The
733    /// output will either be an error, or a [`Filter`] which can apply
734    /// the specified test to objects of the target type, returning
735    /// either `true` (include) or `false` (exclude).
736    pub fn create_filter_from_query(
737        &self,
738        expr: &str,
739    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
740        let parts = expr.splitn(2, '=').collect::<Vec<_>>();
741        if parts.len() != 2 {
742            Err(FilterError::MissingEquals)
743        } else {
744            self.create_filter_from_query_pair(parts[0], parts[1])
745        }
746    }
747}
748
749struct NestedMetaVisitor<'p, F, R, P> {
750    parent: &'p mut P,
751    prefix: String,
752    nester: NesterImpl<F>,
753    _marker: std::marker::PhantomData<R>,
754}
755
756impl<'a, 'p, R, G, P, S> MetaVisitor<'a, S> for NestedMetaVisitor<'p, G, R, P>
757where
758    G: Field<R, Value = S> + Clone + 'a,
759    P: MetaVisitor<'a, R>,
760{
761    fn visit_member<F, O, T>(&mut self, name: &str, field: &F, defop: O)
762    where
763        F: Member<'a, S, Value = T> + Clone,
764        O: OperatorClass<<T as Operable>::Base>,
765        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
766        T: Operable,
767    {
768        self.parent.visit_member(
769            format!("{}__{}", self.prefix, name).as_str(),
770            &self.nester.nest_member(field.clone()),
771            defop,
772        );
773    }
774
775    fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
776    where
777        F: Field<S, Value = U> + Clone + 'a,
778        T: Meta<'a, U>,
779    {
780        let name = format!("{}__{}", self.prefix, name);
781        let mut n = NestedMetaVisitor {
782            parent: self.parent,
783            prefix: name,
784            nester: NesterImpl {
785                outer_field: self.nester.nest_field(field.clone()),
786            },
787            _marker: Default::default(),
788        };
789        inner_record.accept_visitor(&mut n);
790    }
791}
792
793struct NestedMemberVisitor<'a, F, G, R, P> {
794    parent: &'a mut P,
795    field: &'a NestedField<F, G>,
796    _marker: core::marker::PhantomData<R>,
797}
798
799impl<'a, 'b, F, G, P, R, S, T> MemberVisitor<'b, G, S, T> for NestedMemberVisitor<'a, F, G, R, P>
800where
801    P: MemberVisitor<'b, NestedField<F, G>, R, T>,
802    F: Field<R, Value = S> + 'b,
803    G: Member<'b, S, Value = T>,
804    T: Operable,
805{
806    fn visit_operator<O>(&mut self, name: &str, _f: &G, op: O)
807    where
808        O: OperatorClass<<T as Operable>::Base>,
809        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'b,
810    {
811        self.parent.visit_operator(name, self.field, op);
812    }
813}
814
815#[derive(Clone)]
816struct IterableField<F> {
817    inner_field: F,
818}
819
820impl<F, R, T, I> Field<I> for IterableField<F>
821where
822    F: Field<R, Value = T>,
823    for<'i> &'i I: IntoIterator<Item = &'i R>,
824{
825    type Value = T;
826    fn apply<O: Operator<T>>(&'_ self, op: &O, data: &I) -> bool {
827        data.into_iter().any(|x| self.inner_field.apply(op, x))
828    }
829}
830
831impl<'a, F, R, T, I> Member<'a, I> for IterableField<F>
832where
833    F: Member<'a, R, Value = T>,
834    for<'i> &'i I: IntoIterator<Item = &'i R>,
835    T: Operable,
836{
837    type Value = T;
838    fn apply<O: Operator<<T as Operable>::Base>>(&'_ self, op: &O, data: &I) -> bool {
839        data.into_iter().any(|x| self.inner_field.apply(op, x))
840    }
841    fn accept_visitor<V: MemberVisitor<'a, Self, I, <Self as Member<'a, I>>::Value>>(
842        &self,
843        visitor: &mut V,
844    ) {
845        let mut n = IterableMemberVisitor {
846            parent: visitor,
847            field: self,
848            _marker: Default::default(),
849        };
850        self.inner_field.accept_visitor(&mut n);
851    }
852}
853
854struct IterableMemberVisitor<'a, F, I, P> {
855    parent: &'a mut P,
856    field: &'a IterableField<F>,
857    _marker: core::marker::PhantomData<I>,
858}
859
860impl<'a, 'b, F, P, R, T, I> MemberVisitor<'b, F, R, T> for IterableMemberVisitor<'a, F, I, P>
861where
862    P: MemberVisitor<'b, IterableField<F>, I, T>,
863    F: Member<'b, R, Value = T>,
864    for<'i> &'i I: IntoIterator<Item = &'i R>,
865    T: Operable,
866{
867    fn visit_operator<O>(&mut self, name: &str, _f: &F, op: O)
868    where
869        O: OperatorClass<<T as Operable>::Base>,
870        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'b,
871    {
872        self.parent.visit_operator(name, self.field, op);
873    }
874}
875
876#[doc(hidden)]
877pub struct IterableMeta;
878
879impl<'a, R, I> Meta<'a, I> for IterableMeta
880where
881    R: Filterable<'a>,
882    for<'i> &'i I: IntoIterator<Item = &'i R>,
883{
884    fn accept_visitor<V: MetaVisitor<'a, I>>(&self, visitor: &mut V)
885    where
886        Self: Sized,
887    {
888        let mut n = IterableMetaVisitor {
889            parent: visitor,
890            _marker: Default::default(),
891        };
892        R::get_meta().accept_visitor(&mut n);
893    }
894}
895
896struct IterableMetaVisitor<'p, P, I> {
897    parent: &'p mut P,
898    _marker: core::marker::PhantomData<I>,
899}
900
901impl<'a, 'p, P, R, I> MetaVisitor<'a, R> for IterableMetaVisitor<'p, P, I>
902where
903    P: MetaVisitor<'a, I>,
904    for<'i> &'i I: IntoIterator<Item = &'i R>,
905{
906    fn visit_member<F, O, T>(&mut self, name: &str, field: &F, defop: O)
907    where
908        F: Member<'a, R, Value = T> + Clone,
909        O: OperatorClass<<T as Operable>::Base>,
910        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
911        T: Operable,
912    {
913        self.parent.visit_member(
914            name,
915            &IterableField {
916                inner_field: field.clone(),
917            },
918            defop,
919        );
920    }
921
922    fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
923    where
924        F: Field<R, Value = U> + Clone + 'a,
925        T: Meta<'a, U>,
926    {
927        self.parent.visit_record(
928            name,
929            &IterableField {
930                inner_field: field.clone(),
931            },
932            inner_record,
933        )
934    }
935}
936
937struct PrintingVisitor {
938    prefix: Option<String>,
939}
940
941impl<'a, R> MetaVisitor<'a, R> for PrintingVisitor {
942    fn visit_member<F, O, T>(&mut self, name: &str, field: &F, _defop: O)
943    where
944        F: Member<'a, R, Value = T> + Clone,
945        O: OperatorClass<<T as Operable>::Base>,
946        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
947        T: Operable,
948    {
949        let name = if let Some(ref prefix) = self.prefix {
950            format!("{}__{}", prefix, name)
951        } else {
952            name.to_string()
953        };
954        println!("{}", name);
955        let mut pv = PrintingVisitor { prefix: Some(name) };
956        field.accept_visitor(&mut pv);
957    }
958    fn visit_record<F, T, U>(&mut self, name: &str, _field: &F, inner_record: &T)
959    where
960        F: Field<R, Value = U> + Clone + 'a,
961        T: Meta<'a, U>,
962    {
963        let new_prefix = if let Some(ref prefix) = self.prefix {
964            format!("{}__{}", prefix, name)
965        } else {
966            name.to_string()
967        };
968        let mut pv = PrintingVisitor {
969            prefix: Some(new_prefix),
970        };
971        inner_record.accept_visitor(&mut pv);
972    }
973}
974
975impl<'a, F, R, T> MemberVisitor<'a, F, R, T> for PrintingVisitor
976where
977    F: Member<'a, R, Value = T> + Clone,
978    T: Operable,
979{
980    fn visit_operator<O>(&mut self, name: &str, _f: &F, _op: O)
981    where
982        O: OperatorClass<<T as Operable>::Base>,
983        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
984    {
985        // unwrap is safe: there are no bare operators
986        println!("{}__{}", self.prefix.as_ref().unwrap(), name);
987    }
988}
989
990/// Debug print of a [`Filterable`] type showing the supported
991/// queries.
992///
993/// Example:
994/// ```rust
995/// use django_query::filtering::{print_filters, Filterable};
996///
997/// #[derive(Filterable)]
998/// struct Foo {
999///   #[django(op(lt,gt,gte,lte))]
1000///   a: i32
1001/// }
1002///
1003/// print_filters::<Foo>();
1004/// ```
1005/// produces
1006/// ```text
1007/// a
1008/// a__gt
1009/// a__gte
1010/// a__lt
1011/// a__lte
1012/// ```
1013pub fn print_filters<'a, Q: Filterable<'a>>() {
1014    let mut pv = PrintingVisitor { prefix: None };
1015    Q::get_meta().accept_visitor(&mut pv)
1016}
1017
1018impl<'a, T> Filterable<'a> for Vec<T>
1019where
1020    T: Filterable<'a>,
1021{
1022    type Meta = IterableMeta;
1023    fn get_meta() -> Self::Meta {
1024        IterableMeta
1025    }
1026}
1027
1028impl<'a, T> Filterable<'a> for Option<T>
1029where
1030    T: Filterable<'a>,
1031{
1032    type Meta = IterableMeta;
1033    fn get_meta() -> Self::Meta {
1034        IterableMeta
1035    }
1036}
1037
1038impl<'a, T> Filterable<'a> for Arc<T>
1039where
1040    T: Filterable<'a>,
1041{
1042    type Meta = ArcMeta;
1043    fn get_meta() -> Self::Meta {
1044        ArcMeta
1045    }
1046}
1047
1048#[doc(hidden)]
1049pub struct ArcMeta;
1050
1051impl<'a, R> Meta<'a, Arc<R>> for ArcMeta
1052where
1053    R: Filterable<'a>,
1054{
1055    fn accept_visitor<V: MetaVisitor<'a, Arc<R>>>(&self, visitor: &mut V)
1056    where
1057        Self: Sized,
1058    {
1059        let mut n = ArcMetaVisitor { parent: visitor };
1060        R::get_meta().accept_visitor(&mut n);
1061    }
1062}
1063
1064struct ArcMetaVisitor<'p, P> {
1065    parent: &'p mut P,
1066}
1067
1068impl<'a, 'p, P, R> MetaVisitor<'a, R> for ArcMetaVisitor<'p, P>
1069where
1070    P: MetaVisitor<'a, Arc<R>>,
1071{
1072    fn visit_member<F, O, T>(&mut self, name: &str, field: &F, defop: O)
1073    where
1074        F: Member<'a, R, Value = T> + Clone,
1075        O: OperatorClass<<T as Operable>::Base>,
1076        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
1077        T: Operable,
1078    {
1079        self.parent.visit_member(
1080            name,
1081            &WrapperField {
1082                inner_field: field.clone(),
1083            },
1084            defop,
1085        );
1086    }
1087
1088    fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
1089    where
1090        F: Field<R, Value = U> + Clone + 'a,
1091        T: Meta<'a, U>,
1092    {
1093        self.parent.visit_record(
1094            name,
1095            &WrapperField {
1096                inner_field: field.clone(),
1097            },
1098            inner_record,
1099        )
1100    }
1101}
1102
1103#[derive(Clone)]
1104struct WrapperField<F> {
1105    inner_field: F,
1106}
1107
1108impl<F, R, T, U> Field<U> for WrapperField<F>
1109where
1110    F: Field<R, Value = T>,
1111    U: Deref<Target = R>,
1112{
1113    type Value = T;
1114    fn apply<O: Operator<T>>(&'_ self, op: &O, data: &U) -> bool {
1115        self.inner_field.apply(op, &*data)
1116    }
1117}
1118
1119impl<'a, F, R, T, U> Member<'a, U> for WrapperField<F>
1120where
1121    F: Member<'a, R, Value = T>,
1122    U: Deref<Target = R>,
1123    T: Operable,
1124{
1125    type Value = T;
1126    fn apply<O: Operator<<T as Operable>::Base>>(&'_ self, op: &O, data: &U) -> bool {
1127        self.inner_field.apply(op, &*data)
1128    }
1129    fn accept_visitor<V: MemberVisitor<'a, Self, U, <Self as Member<'a, U>>::Value>>(
1130        &self,
1131        visitor: &mut V,
1132    ) {
1133        let mut n = WrapperMemberVisitor {
1134            parent: visitor,
1135            field: self,
1136            _marker: Default::default(),
1137        };
1138        self.inner_field.accept_visitor(&mut n);
1139    }
1140}
1141
1142struct WrapperMemberVisitor<'a, F, P, U> {
1143    parent: &'a mut P,
1144    field: &'a WrapperField<F>,
1145    _marker: core::marker::PhantomData<U>,
1146}
1147
1148impl<'a, 'b, F, P, R, T, U> MemberVisitor<'b, F, R, T> for WrapperMemberVisitor<'a, F, P, U>
1149where
1150    P: MemberVisitor<'b, WrapperField<F>, U, T>,
1151    F: Member<'b, R, Value = T>,
1152    U: Deref<Target = R>,
1153    T: Operable,
1154{
1155    fn visit_operator<O>(&mut self, name: &str, _f: &F, op: O)
1156    where
1157        O: OperatorClass<<T as Operable>::Base>,
1158        <O as OperatorClass<<T as Operable>::Base>>::Instance: 'b,
1159    {
1160        self.parent.visit_operator(name, self.field, op);
1161    }
1162}
1163
1164// State support
1165
1166/// Something that can describe how to filter itself if a context type
1167/// is provided.
1168///
1169/// Something implementing this trait can provide a [`Meta`] which
1170/// describes its supported fields and their operators, but only when
1171/// a context object is provided.  Note that the provided context
1172/// object may be stored within the [`Meta`] type, which is the origin
1173/// of the lifetime parameter.
1174///
1175#[cfg_attr(
1176    feature = "persian-rug",
1177    doc = r##"
1178This can be derived via the
1179[`FilterableWithPersianRug`](FilterableWithPersianRug)
1180derive macro for the case of a [`persian-rug`](::persian_rug)
1181type.
1182"##
1183)]
1184pub trait FilterableWithContext<'a, A: 'a>: Sized {
1185    /// `Meta` is the type which can describe our fields and their operators.
1186    type Meta: Meta<'a, Self>;
1187    /// `get_meta` produces an instance of our `Meta` type.
1188    ///
1189    /// Here `access` is some context object that we need in order to
1190    /// provide filters for our type.
1191    fn get_meta(access: A) -> Self::Meta;
1192}
1193
1194/// A collection of filters for a type that requires a context object.
1195///
1196/// An [`OperatorSetWithContext`] can be created for any type which
1197/// implements [`FilterableWithContext`]. Its constructor supplies a
1198/// visitor to the type's `Meta` type, and constructs the necessary
1199/// [`FilterClass`] objects.  It can be used directly to convert
1200/// incoming query pairs from Django-style query URLs into appropriate
1201/// [`Filter`] objects.
1202///
1203/// Note that the context object provided on construction may be
1204/// stored within the resulting object, and may also be cloned into
1205/// the [`Meta`] for other types.
1206pub struct OperatorSetWithContext<R, A> {
1207    _marker: core::marker::PhantomData<R>,
1208    access: A,
1209}
1210
1211impl<'a, A: Clone + 'a, R: FilterableWithContext<'a, A>> OperatorSetWithContext<R, A> {
1212    /// Create a new [`OperatorSetWithContext`], using the [`Meta`] record
1213    /// from the target type, which will be initialized from the provided
1214    /// context object `access`.
1215    pub fn new(access: A) -> Self {
1216        Self {
1217            _marker: Default::default(),
1218            access,
1219        }
1220    }
1221
1222    /// Create a new filter from a decomposed URL. Note that the
1223    /// decomposition is ambiguous, so
1224    /// [`create_filter_from_query_pair`](OperatorSetWithContext::create_filter_from_query_pair)
1225    /// is often preferable. The ambiguity arises because there may be
1226    /// no operator part, and the field part may have arbitrarily many
1227    /// parts.  Since everything is separated with double underscores
1228    /// there is no way without additional information to distinguish
1229    /// an expression with an explicit operator from an expression on
1230    /// a nested field with an implicit operator.  Here - `field` is
1231    /// the field specification part of the string, including any
1232    /// nested fields.  - `operator` is the operator specification, if
1233    /// any.  - `rhs` is the argument part, after the `=` in the URL
1234    /// section.
1235    pub fn create_filter(
1236        &self,
1237        field: &str,
1238        operator: Option<&str>,
1239        rhs: &str,
1240    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
1241        let lhs = if let Some(op) = operator {
1242            format!("{}__{}", field, op)
1243        } else {
1244            field.to_string()
1245        };
1246
1247        self.create_filter_from_query_pair(&lhs, rhs)
1248    }
1249
1250    /// Create a new filter from a fragment of query URL. The expected
1251    /// input is a `lhs=rhs` pair from a query string, with `lhs` and
1252    /// `rhs` given separately. The output will either be an error, or
1253    /// a [`Filter`] which can apply the specified test to objects of
1254    /// the target type, returning either `true` (include) or `false`
1255    /// (exclude).
1256    pub fn create_filter_from_query_pair(
1257        &self,
1258        lhs: &str,
1259        rhs: &str,
1260    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
1261        let mut p = QueryProcessor {
1262            target: lhs,
1263            rhs,
1264            result: None,
1265        };
1266
1267        R::get_meta(self.access.clone()).accept_visitor(&mut p);
1268
1269        p.result
1270            .ok_or_else(|| FilterError::NoField(lhs.to_string()))?
1271    }
1272
1273    /// Create a new filter from a fragment of query URL. The expected
1274    /// input is a `lhs=rhs` pair from a query string, with `lhs` and
1275    /// `rhs` given together in a single string. The output will
1276    /// either be an error, or a [`Filter`] which can apply the
1277    /// specified test to objects of the target type, returning
1278    /// either `true` (include) or `false` (exclude).
1279    pub fn create_filter_from_query(
1280        &self,
1281        expr: &str,
1282    ) -> Result<Box<dyn Filter<R> + 'a>, FilterError> {
1283        let parts = expr.splitn(2, '=').collect::<Vec<_>>();
1284        if parts.len() != 2 {
1285            Err(FilterError::MissingEquals)
1286        } else {
1287            self.create_filter_from_query_pair(parts[0], parts[1])
1288        }
1289    }
1290}
1291
1292#[doc(hidden)]
1293pub struct IterableMetaWithContext<A> {
1294    access: A,
1295}
1296
1297impl<'a, A, R, I> Meta<'a, I> for IterableMetaWithContext<A>
1298where
1299    A: 'a + Clone,
1300    R: FilterableWithContext<'a, A>,
1301    for<'i> &'i I: IntoIterator<Item = &'i R>,
1302{
1303    fn accept_visitor<V: MetaVisitor<'a, I>>(&self, visitor: &mut V)
1304    where
1305        Self: Sized,
1306    {
1307        let mut n = IterableMetaVisitor {
1308            parent: visitor,
1309            _marker: Default::default(),
1310        };
1311        R::get_meta(self.access.clone()).accept_visitor(&mut n);
1312    }
1313}
1314
1315impl<'a, A, T> FilterableWithContext<'a, A> for Option<T>
1316where
1317    T: FilterableWithContext<'a, A>,
1318    A: 'a + Clone,
1319{
1320    type Meta = IterableMetaWithContext<A>;
1321    fn get_meta(access: A) -> Self::Meta {
1322        IterableMetaWithContext { access }
1323    }
1324}
1325
1326impl<'a, A, T> FilterableWithContext<'a, A> for Vec<T>
1327where
1328    T: FilterableWithContext<'a, A>,
1329    A: 'a + Clone,
1330{
1331    type Meta = IterableMetaWithContext<A>;
1332    fn get_meta(access: A) -> Self::Meta {
1333        IterableMetaWithContext { access }
1334    }
1335}
1336
1337pub use django_query_derive::Filterable;
1338
1339#[cfg(feature = "persian-rug")]
1340#[cfg_attr(docsrs, doc(cfg(feature = "persian-rug")))]
1341pub use crate::persian_rug::FilterableWithPersianRug;