django_query/persian_rug/
filtering.rs1use crate::filtering::{FilterableWithContext, Meta, MetaVisitor};
2
3use crate::filtering::{Field, Member, MemberVisitor, Operable, Operator, OperatorClass};
4
5use persian_rug::{Accessor, Contextual, Proxy};
6
7#[persian_rug::constraints(context = C, access(T))]
8impl<'a, A, C, T> FilterableWithContext<'a, A> for Proxy<T>
9where
10 T: FilterableWithContext<'a, A> + Contextual<Context = C>,
11 A: Accessor<Context = C> + 'a,
12{
13 type Meta = ProxyMeta<A>;
14 fn get_meta(access: A) -> Self::Meta {
15 ProxyMeta { access }
16 }
17}
18
19pub struct ProxyMeta<A> {
20 access: A,
21}
22
23#[persian_rug::constraints(context = C, access(T))]
24impl<'f, A, C, T> Meta<'f, Proxy<T>> for ProxyMeta<A>
25where
26 T: FilterableWithContext<'f, A>,
27 A: Accessor<Context = C> + 'f,
28 T: Contextual<Context = C>,
29{
30 fn accept_visitor<V: MetaVisitor<'f, Proxy<T>>>(&self, visitor: &mut V)
31 where
32 Self: Sized,
33 {
34 let mut n = ProxyMetaVisitor {
35 parent: visitor,
36 access: self.access.clone(),
37 };
38 T::get_meta(self.access.clone()).accept_visitor(&mut n);
39 }
40}
41
42struct ProxyMetaVisitor<'p, P, A> {
43 parent: &'p mut P,
44 access: A,
45}
46
47#[persian_rug::constraints(context = C, access(R))]
48impl<'a, 'p, A, C, P, R> MetaVisitor<'a, R> for ProxyMetaVisitor<'p, P, A>
49where
50 P: MetaVisitor<'a, Proxy<R>>,
51 A: Accessor<Context = C> + 'a,
52{
53 fn visit_member<F, O, T>(&mut self, name: &str, field: &F, defop: O)
54 where
55 F: Member<'a, R, Value = T> + Clone,
56 O: OperatorClass<<T as Operable>::Base>,
57 <O as OperatorClass<<T as Operable>::Base>>::Instance: 'a,
58 T: Operable,
59 {
60 self.parent.visit_member(
61 name,
62 &ProxyField {
63 inner_field: field.clone(),
64 access: self.access.clone(),
65 },
66 defop,
67 );
68 }
69
70 fn visit_record<F, T, U>(&mut self, name: &str, field: &F, inner_record: &T)
71 where
72 F: Field<R, Value = U> + Clone + 'a,
73 T: Meta<'a, U>,
74 {
75 self.parent.visit_record(
76 name,
77 &ProxyField {
78 inner_field: field.clone(),
79 access: self.access.clone(),
80 },
81 inner_record,
82 )
83 }
84}
85
86#[derive(Clone)]
87struct ProxyField<F, A> {
88 inner_field: F,
89 access: A,
90}
91
92#[persian_rug::constraints(context = C, access(U))]
93impl<A, C, F, T, U> Field<Proxy<U>> for ProxyField<F, A>
94where
95 F: Field<U, Value = T>,
96 A: Accessor<Context = C>,
97{
98 type Value = T;
99 fn apply<O: Operator<T>>(&'_ self, op: &O, data: &Proxy<U>) -> bool {
100 self.inner_field.apply(op, self.access.get(data))
101 }
102}
103
104#[persian_rug::constraints(context = C, access(U))]
105impl<'a, A, C, F, T, U> Member<'a, Proxy<U>> for ProxyField<F, A>
106where
107 F: Member<'a, U, Value = T>,
108 T: Operable,
109 A: Accessor<Context = C> + 'a,
110{
111 type Value = T;
112 fn apply<O: Operator<<T as Operable>::Base>>(&'_ self, op: &O, data: &Proxy<U>) -> bool {
113 self.inner_field.apply(op, self.access.get(data))
114 }
115 fn accept_visitor<V: MemberVisitor<'a, Self, Proxy<U>, T>>(&self, visitor: &mut V) {
116 let mut n = ProxyMemberVisitor {
117 parent: visitor,
118 field: self,
119 _marker: Default::default(),
120 };
121 self.inner_field.accept_visitor(&mut n);
122 }
123}
124
125struct ProxyMemberVisitor<'a, A, F, P, U> {
126 parent: &'a mut P,
127 field: &'a ProxyField<F, A>,
128 _marker: core::marker::PhantomData<U>,
129}
130
131#[persian_rug::constraints(context = C, access(U))]
132impl<'a, 'b, A, C, F, P, T, U> MemberVisitor<'b, F, U, T> for ProxyMemberVisitor<'a, A, F, P, U>
133where
134 P: MemberVisitor<'b, ProxyField<F, A>, Proxy<U>, T>,
135 F: Member<'b, U, Value = T>,
136 T: Operable,
137 A: Accessor<Context = C> + 'b,
138{
139 fn visit_operator<O>(&mut self, name: &str, _f: &F, op: O)
140 where
141 O: OperatorClass<<T as Operable>::Base>,
142 <O as OperatorClass<<T as Operable>::Base>>::Instance: 'b,
143 {
144 self.parent.visit_operator(name, self.field, op);
145 }
146}
147
148pub use django_query_derive::FilterableWithPersianRug;