django_query/persian_rug/
sorting.rs1use crate::sorting::{Field, SortVisitor, Sorter, SorterTypedClass};
2use crate::sorting::{Meta, SortableWithContext};
3
4use core::cmp::Ordering;
5
6use persian_rug::{Accessor, Proxy};
7
8#[persian_rug::constraints(context=C, access(T))]
9impl<'s, A, T, C> SortableWithContext<'s, A> for Proxy<T>
10where
11 T: SortableWithContext<'s, A>,
12 A: Accessor<Context = C> + 's,
13{
14 type Meta = ProxyMeta<A>;
15
16 fn get_meta(access: A) -> Self::Meta {
17 ProxyMeta { access }
18 }
19}
20
21pub struct ProxyMeta<A> {
22 access: A,
23}
24
25#[persian_rug::constraints(context = C, access(T))]
26impl<'s, A, C, T> Meta<'s, Proxy<T>> for ProxyMeta<A>
27where
28 A: Accessor<Context = C> + 's,
29 T: SortableWithContext<'s, A>,
30{
31 fn accept_visitor<V: SortVisitor<'s, Target = Proxy<T>>>(&self, visitor: &mut V)
32 where
33 Self: Sized,
34 {
35 let mut v = ProxyVisitor {
36 parent: visitor,
37 access: self.access.clone(),
38 };
39 T::get_meta(self.access.clone()).accept_visitor(&mut v);
40 }
41}
42
43struct ProxyVisitor<'a, P, A> {
44 parent: &'a mut P,
45 access: A,
46}
47
48#[persian_rug::constraints(context = C, access(R))]
49impl<'a, 's, A, C, P, R> SortVisitor<'s> for ProxyVisitor<'a, P, A>
50where
51 A: Accessor<Context = C> + 's,
52 P: SortVisitor<'s, Target = Proxy<R>>,
53{
54 type Target = R;
55 fn visit_sort<F, T, S>(&mut self, name: &str, field: &F, sort: &S)
56 where
57 F: Field<R, Value = T> + 's,
58 S: SorterTypedClass<T> + 's,
59 <S as SorterTypedClass<T>>::Sorter: 's,
60 {
61 self.parent.visit_sort(
62 name,
63 &ProxyField {
64 inner: field.clone(),
65 access: self.access.clone(),
66 },
67 sort,
68 );
69 }
70
71 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, sort_key: &str, meta: M)
72 where
73 F: Field<R, Value = T> + 's,
74 M: Meta<'s, T>,
75 {
76 self.parent.visit_key_sort(
77 name,
78 &ProxyField {
79 inner: field.clone(),
80 access: self.access.clone(),
81 },
82 sort_key,
83 meta,
84 );
85 }
86}
87
88#[derive(Clone)]
89struct ProxyField<F, A> {
90 inner: F,
91 access: A,
92}
93
94#[persian_rug::constraints(context=C, access(R))]
95impl<A, C, R, F, T> Field<Proxy<R>> for ProxyField<F, A>
96where
97 A: Accessor<Context = C>,
98 F: Field<R, Value = T>,
99{
100 type Value = T;
101 fn apply_sorter<V: Sorter<Self::Value>>(&self, op: &V, a: &Proxy<R>, b: &Proxy<R>) -> Ordering {
102 self.inner.apply_sorter(
103 &ProxyOp { parent: op },
104 self.access.get(a),
105 self.access.get(b),
106 )
107 }
108}
109
110struct ProxyOp<'a, V> {
111 parent: &'a V,
112}
113
114impl<'a, V, T> Sorter<T> for ProxyOp<'a, V>
115where
116 V: Sorter<T>,
117{
118 fn compare(&self, a: &T, b: &T) -> Ordering {
119 self.parent.compare(a, b)
120 }
121}
122
123pub use django_query_derive::SortableWithPersianRug;