1use core::cmp::Ordering;
80use core::ops::Deref;
81
82use std::sync::Arc;
83
84use thiserror::Error;
85
86#[derive(Debug, Error)]
88pub enum SorterError {
89 #[error("cannot sort by expression '{0}'")]
91 NoSort(String),
92}
93
94pub struct Compare;
96
97impl<T: Ord> Sorter<T> for Compare {
98 fn compare(&self, a: &T, b: &T) -> Ordering {
99 a.cmp(b)
100 }
101}
102
103pub struct ReverseCompare;
106
107impl<T: Ord> Sorter<T> for ReverseCompare {
108 fn compare(&self, a: &T, b: &T) -> Ordering {
109 b.cmp(a)
110 }
111}
112
113#[derive(Clone)]
115pub struct CompareClass;
116
117impl<'s, T: Ord> SorterClass<'s, T> for CompareClass {
118 fn instantiate(&self, reverse: bool) -> Box<dyn Sorter<T> + 's> {
119 if reverse {
120 Box::new(ReverseCompare)
121 } else {
122 Box::new(Compare)
123 }
124 }
125}
126
127impl<T: Ord> SorterTypedClass<T> for CompareClass {
128 type Sorter = Compare;
129 fn instantiate(&self) -> Compare {
130 Compare
131 }
132}
133
134pub trait Field<R>: Clone {
145 type Value;
146 fn apply_sorter<V: Sorter<Self::Value>>(&self, op: &V, a: &R, b: &R) -> Ordering;
149}
150
151pub trait Accessor<R>: Clone {
184 type Value;
185 fn value<'a>(&self, data: &'a R) -> &'a Self::Value;
187}
188
189pub trait ReferenceField {}
198
199impl<R, F> Field<R> for F
200where
201 F: Accessor<R> + ReferenceField,
202{
203 type Value = <F as Accessor<R>>::Value;
204 fn apply_sorter<V: Sorter<Self::Value>>(&self, op: &V, a: &R, b: &R) -> Ordering {
205 op.compare(self.value(a), self.value(b))
206 }
207}
208
209pub trait Sorter<R> {
216 fn compare(&self, a: &R, b: &R) -> Ordering;
221
222 fn sort_vec(&self, vec: &mut Vec<R>) {
224 vec.sort_by(|x, y| self.compare(x, y))
225 }
226
227 fn sort_ref_vec(&self, vec: &mut Vec<&R>) {
229 vec.sort_by(|x, y| self.compare(x, y))
230 }
231}
232
233#[doc(hidden)]
234pub struct SorterImpl<F, S> {
235 field: F,
236 sorter: S,
237}
238
239impl<F, S> SorterImpl<F, S> {
240 pub fn new(field: F, sorter: S) -> Self {
241 Self { field, sorter }
242 }
243}
244
245impl<R, F, T, S> Sorter<R> for SorterImpl<F, S>
246where
247 F: Field<R, Value = T>,
248 S: Sorter<T>,
249{
250 fn compare(&self, a: &R, b: &R) -> Ordering {
251 self.field.apply_sorter(&self.sorter, a, b)
252 }
253}
254
255struct Reverser<S> {
256 inner: S,
257}
258
259impl<S> Reverser<S> {
260 pub fn new(inner: S) -> Self {
261 Self { inner }
262 }
263}
264
265impl<R, S> Sorter<R> for Reverser<S>
266where
267 S: Sorter<R>,
268{
269 fn compare(&self, a: &R, b: &R) -> Ordering {
270 self.inner.compare(a, b).reverse()
271 }
272}
273
274pub trait SorterClass<'s, R> {
279 fn instantiate(&self, reverse: bool) -> Box<dyn Sorter<R> + 's>;
281}
282
283pub trait SorterTypedClass<R>: Clone {
291 type Sorter: Sorter<R>;
292 fn instantiate(&self) -> Self::Sorter;
294}
295
296#[derive(Clone)]
297#[doc(hidden)]
298pub struct SorterClassImpl<F, S> {
299 field: F,
300 sorter: S,
301}
302
303impl<F, S> SorterClassImpl<F, S> {
304 pub fn new(field: F, sorter: S) -> Self {
305 Self { field, sorter }
306 }
307}
308
309impl<'s, R, F, T, S> SorterClass<'s, R> for SorterClassImpl<F, S>
310where
311 F: Field<R, Value = T> + 's,
312 S: SorterTypedClass<T>,
313 <S as SorterTypedClass<T>>::Sorter: 's,
314{
315 fn instantiate(&self, reverse: bool) -> Box<dyn Sorter<R> + 's> {
316 if reverse {
317 Box::new(Reverser::new(SorterImpl::new(
318 self.field.clone(),
319 self.sorter.instantiate(),
320 )))
321 } else {
322 Box::new(SorterImpl::new(
323 self.field.clone(),
324 self.sorter.instantiate(),
325 ))
326 }
327 }
328}
329
330impl<'s, R, F, T, S> SorterTypedClass<R> for SorterClassImpl<F, S>
331where
332 F: Field<R, Value = T> + 's,
333 S: SorterTypedClass<T>,
334{
335 type Sorter = SorterImpl<F, <S as SorterTypedClass<T>>::Sorter>;
336 fn instantiate(&self) -> Self::Sorter {
337 SorterImpl::new(self.field.clone(), self.sorter.instantiate())
338 }
339}
340
341pub trait SortVisitor<'s> {
347 type Target;
348 fn visit_sort<F, T, S>(&mut self, name: &str, field: &F, sort: &S)
351 where
352 F: Field<Self::Target, Value = T> + 's,
353 S: SorterTypedClass<T> + 's,
354 <S as SorterTypedClass<T>>::Sorter: 's;
355
356 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, sort_key: &str, meta: M)
362 where
363 F: Field<Self::Target, Value = T> + 's,
364 M: Meta<'s, T>;
365}
366
367pub trait Meta<'s, R> {
369 fn accept_visitor<V: SortVisitor<'s, Target = R>>(&self, visitor: &mut V)
372 where
373 Self: Sized;
374}
375
376pub trait Sortable<'s>: Sized {
383 type Meta: Meta<'s, Self>;
385 fn get_meta() -> Self::Meta;
387}
388
389impl<'s, T> Sortable<'s> for Arc<T>
390where
391 T: Sortable<'s>,
392{
393 type Meta = ArcMeta;
394 fn get_meta() -> Self::Meta {
395 ArcMeta
396 }
397}
398
399#[doc(hidden)]
400pub struct ArcMeta;
401
402impl<'s, T> Meta<'s, Arc<T>> for ArcMeta
403where
404 T: Sortable<'s>,
405{
406 fn accept_visitor<V: SortVisitor<'s, Target = Arc<T>>>(&self, visitor: &mut V) {
407 let mut v = VisitorWrapper { parent: visitor };
408 T::get_meta().accept_visitor(&mut v);
409 }
410}
411
412struct VisitorWrapper<'a, P> {
413 parent: &'a mut P,
414}
415
416impl<'a, 's, P, R, U> SortVisitor<'s> for VisitorWrapper<'a, P>
417where
418 P: SortVisitor<'s, Target = U>,
419 U: Deref<Target = R>,
420{
421 type Target = R;
422 fn visit_sort<F, T, S>(&mut self, name: &str, field: &F, sort: &S)
423 where
424 F: Field<R, Value = T> + 's,
425 S: SorterTypedClass<T> + 's,
426 <S as SorterTypedClass<T>>::Sorter: 's,
427 {
428 self.parent.visit_sort(
429 name,
430 &WrappedField {
431 inner: field.clone(),
432 },
433 sort,
434 );
435 }
436
437 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, sort_key: &str, meta: M)
438 where
439 F: Field<R, Value = T> + 's,
440 M: Meta<'s, T>,
441 {
442 self.parent.visit_key_sort(
443 name,
444 &WrappedField {
445 inner: field.clone(),
446 },
447 sort_key,
448 meta,
449 );
450 }
451}
452
453#[derive(Clone)]
454struct WrappedField<F> {
455 inner: F,
456}
457
458impl<R, F, T, U> Field<U> for WrappedField<F>
459where
460 F: Field<R, Value = T>,
461 U: Deref<Target = R>,
462{
463 type Value = T;
464 fn apply_sorter<V: Sorter<Self::Value>>(&self, op: &V, a: &U, b: &U) -> Ordering {
465 self.inner.apply_sorter(op, a, b)
466 }
467}
468
469impl<'s, T> Sortable<'s> for Option<T>
470where
471 T: Sortable<'s>,
472{
473 type Meta = OptionMeta;
474
475 fn get_meta() -> Self::Meta {
476 OptionMeta
477 }
478}
479
480#[doc(hidden)]
481pub struct OptionMeta;
482
483impl<'s, T> Meta<'s, Option<T>> for OptionMeta
484where
485 T: Sortable<'s>,
486{
487 fn accept_visitor<V: SortVisitor<'s, Target = Option<T>>>(&self, visitor: &mut V)
488 where
489 Self: Sized,
490 {
491 let mut v = OptionVisitor { parent: visitor };
492 T::get_meta().accept_visitor(&mut v);
493 }
494}
495
496struct OptionVisitor<'a, P> {
497 parent: &'a mut P,
498}
499
500impl<'a, 's, P, R> SortVisitor<'s> for OptionVisitor<'a, P>
501where
502 P: SortVisitor<'s, Target = Option<R>>,
503{
504 type Target = R;
505 fn visit_sort<F, T, S>(&mut self, name: &str, field: &F, sort: &S)
506 where
507 F: Field<R, Value = T> + 's,
508 S: SorterTypedClass<T> + 's,
509 <S as SorterTypedClass<T>>::Sorter: 's,
510 {
511 self.parent.visit_sort(
512 name,
513 &OptionField {
514 inner: field.clone(),
515 },
516 sort,
517 );
518 }
519
520 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, sort_key: &str, meta: M)
521 where
522 F: Field<R, Value = T> + 's,
523 M: Meta<'s, T>,
524 {
525 self.parent.visit_key_sort(
526 name,
527 &OptionField {
528 inner: field.clone(),
529 },
530 sort_key,
531 meta,
532 );
533 }
534}
535
536#[derive(Clone)]
537struct OptionField<F> {
538 inner: F,
539}
540
541impl<R, F, T> Field<Option<R>> for OptionField<F>
542where
543 F: Field<R, Value = T>,
544{
545 type Value = T;
546 fn apply_sorter<V: Sorter<Self::Value>>(
547 &self,
548 op: &V,
549 a: &Option<R>,
550 b: &Option<R>,
551 ) -> Ordering {
552 match (a.as_ref(), b.as_ref()) {
553 (Some(a), Some(b)) => self.inner.apply_sorter(&OptionOp { parent: op }, a, b),
554 (Some(_), None) => Ordering::Greater,
555 (None, Some(_)) => Ordering::Less,
556 (None, None) => Ordering::Equal,
557 }
558 }
559}
560
561struct OptionOp<'a, V> {
562 parent: &'a V,
563}
564
565impl<'a, V, T> Sorter<T> for OptionOp<'a, V>
566where
567 V: Sorter<T>,
568{
569 fn compare(&self, a: &T, b: &T) -> Ordering {
570 self.parent.compare(a, b)
571 }
572}
573
574pub struct OrderingSet<R> {
576 _marker: core::marker::PhantomData<R>,
577}
578
579impl<'s, R: Sortable<'s>> Default for OrderingSet<R> {
580 fn default() -> Self {
581 Self {
582 _marker: Default::default(),
583 }
584 }
585}
586
587impl<'s, R: Sortable<'s>> OrderingSet<R>
588where
589 R: 's,
594{
595 pub fn new() -> Self {
597 Default::default()
598 }
599
600 pub fn create_sort(&self, expr: &str) -> Result<Box<dyn Sorter<R> + 's>, SorterError> {
605 let parts = expr.split(',').collect::<Vec<&str>>();
606 let mut full_sort: Option<Box<dyn Sorter<R> + 's>> = None;
607 for part in parts.iter().rev() {
608 let part_sort = if let Some(name) = part.strip_prefix('-') {
609 let mut sp = SortProcessor { name, result: None };
610 R::get_meta().accept_visitor(&mut sp);
611
612 sp.result
613 .ok_or_else(|| SorterError::NoSort(part.to_string()))?
614 .instantiate(true)
615 } else {
616 let mut sp = SortProcessor {
617 name: *part,
618 result: None,
619 };
620 R::get_meta().accept_visitor(&mut sp);
621
622 sp.result
623 .ok_or_else(|| SorterError::NoSort(part.to_string()))?
624 .instantiate(false)
625 };
626 full_sort = if let Some(sort) = full_sort {
627 Some(Box::new(StackedSorter::new(part_sort, sort)))
628 } else {
629 Some(part_sort)
630 };
631 }
632 full_sort.ok_or_else(|| SorterError::NoSort(expr.to_string()))
633 }
634}
635
636#[doc(hidden)]
637pub struct SortProcessor<'s, 'q, R> {
638 pub name: &'q str,
639 pub result: Option<Box<dyn SorterClass<'s, R> + 's>>,
640}
641
642impl<'s, 'q, R> SortVisitor<'s> for SortProcessor<'s, 'q, R> {
643 type Target = R;
644 fn visit_sort<F, T, S>(&mut self, name: &str, field: &F, sort: &S)
645 where
646 F: Field<R, Value = T> + 's,
647 S: SorterTypedClass<T> + 's,
648 <S as SorterTypedClass<T>>::Sorter: 's,
649 {
650 if name == self.name {
651 self.result = Some(Box::new(SorterClassImpl::new(field.clone(), sort.clone())))
652 }
653 }
654
655 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, key: &str, meta: M)
656 where
657 F: Field<R, Value = T> + 's,
658 M: Meta<'s, T>,
659 {
660 let mut v = KeyVisitor::new(name, key, field.clone(), self);
661 meta.accept_visitor(&mut v);
662 }
663}
664
665#[doc(hidden)]
666pub struct KeyVisitor<'a, 'b, P, F> {
667 name: &'a str,
668 key: &'a str,
669 field: F,
670 parent: &'b mut P,
671}
672
673impl<'a, 'b, P, F> KeyVisitor<'a, 'b, P, F> {
674 pub fn new(name: &'a str, key: &'a str, field: F, parent: &'b mut P) -> Self {
675 Self {
676 name,
677 key,
678 field,
679 parent,
680 }
681 }
682}
683
684impl<'a, 'b, 's, P, G, R, S> SortVisitor<'s> for KeyVisitor<'a, 'b, P, G>
685where
686 P: SortVisitor<'s, Target = S>,
687 G: Field<S, Value = R> + 's,
688{
689 type Target = R;
690
691 fn visit_sort<F, T, Srt>(&mut self, name: &str, field: &F, sort: &Srt)
692 where
693 F: Field<R, Value = T> + 's,
694 Srt: SorterTypedClass<T> + 's,
695 <Srt as SorterTypedClass<T>>::Sorter: 's,
696 {
697 if name == self.key {
698 self.parent.visit_sort(
699 self.name,
700 &NestedField {
701 outer: self.field.clone(),
702 inner: field.clone(),
703 },
704 sort,
705 );
706 }
707 }
708
709 fn visit_key_sort<F, T, M>(&mut self, name: &str, field: &F, key: &str, meta: M)
710 where
711 F: Field<R, Value = T> + 's,
712 M: Meta<'s, T>,
713 {
714 if name == self.key {
715 let mut v = KeyVisitor {
716 name: self.name,
717 key,
718 field: NestedField {
719 outer: self.field.clone(),
720 inner: field.clone(),
721 },
722 parent: self.parent,
723 };
724 meta.accept_visitor(&mut v);
725 }
726 }
727}
728
729#[derive(Clone)]
730struct NestedField<F, G> {
731 outer: F,
732 inner: G,
733}
734
735impl<'s, F, G, R, T, U> Field<R> for NestedField<F, G>
736where
737 F: Field<R, Value = T>,
738 G: Field<T, Value = U>,
739{
740 type Value = U;
741 fn apply_sorter<V: Sorter<Self::Value>>(&self, op: &V, a: &R, b: &R) -> Ordering {
742 let n = NestedSorter {
743 inner: &self.inner,
744 op,
745 };
746 self.outer.apply_sorter(&n, a, b)
747 }
748}
749
750struct NestedSorter<'a, 'b, F, P> {
751 inner: &'a F,
752 op: &'b P,
753}
754
755impl<'a, 'b, F, P, T, U> Sorter<T> for NestedSorter<'a, 'b, F, P>
756where
757 F: Field<T, Value = U>,
758 P: Sorter<U>,
759{
760 fn compare(&self, a: &T, b: &T) -> Ordering {
761 self.inner.apply_sorter(self.op, a, b)
762 }
763}
764
765struct StackedSorter<'s, R> {
766 primary: Box<dyn Sorter<R> + 's>,
767 secondary: Box<dyn Sorter<R> + 's>,
768}
769
770impl<'s, R> StackedSorter<'s, R> {
771 pub fn new(primary: Box<dyn Sorter<R> + 's>, secondary: Box<dyn Sorter<R> + 's>) -> Self {
772 Self { primary, secondary }
773 }
774}
775
776impl<'s, R> Sorter<R> for StackedSorter<'s, R> {
777 fn compare(&self, a: &R, b: &R) -> Ordering {
778 match self.primary.compare(a, b) {
779 Ordering::Less => Ordering::Less,
780 Ordering::Greater => Ordering::Greater,
781 Ordering::Equal => self.secondary.compare(a, b),
782 }
783 }
784}
785
786#[cfg_attr(
798 feature = "persian-rug",
799 doc = r##"
800This can be derived via the
801[`SortableWithPersianRug`](SortableWithPersianRug)
802derive macro for the case of a [`persian-rug`](::persian_rug)
803type.
804"##
805)]
806pub trait SortableWithContext<'s, A: 's>: Sized {
807 type Meta: Meta<'s, Self>;
809 fn get_meta(access: A) -> Self::Meta;
811}
812
813pub struct OrderingSetWithContext<R, A> {
819 _marker: core::marker::PhantomData<R>,
820 access: A,
821}
822
823impl<'s, A: Clone + 's, R: SortableWithContext<'s, A>> OrderingSetWithContext<R, A>
824where
825 R: 's,
830{
831 pub fn new(access: A) -> Self {
833 Self {
834 _marker: Default::default(),
835 access,
836 }
837 }
838
839 pub fn create_sort(&self, expr: &str) -> Result<Box<dyn Sorter<R> + 's>, SorterError> {
844 let parts = expr.split(',').collect::<Vec<&str>>();
845 let mut full_sort: Option<Box<dyn Sorter<R> + 's>> = None;
846 for part in parts.iter().rev() {
847 let part_sort = if let Some(name) = part.strip_prefix('-') {
848 let mut sp = SortProcessor { name, result: None };
849 R::get_meta(self.access.clone()).accept_visitor(&mut sp);
850
851 sp.result
852 .ok_or_else(|| SorterError::NoSort(part.to_string()))?
853 .instantiate(true)
854 } else {
855 let mut sp = SortProcessor {
856 name: *part,
857 result: None,
858 };
859
860 R::get_meta(self.access.clone()).accept_visitor(&mut sp);
861
862 sp.result
863 .ok_or_else(|| SorterError::NoSort(part.to_string()))?
864 .instantiate(false)
865 };
866 full_sort = if let Some(sort) = full_sort {
867 Some(Box::new(StackedSorter::new(part_sort, sort)))
868 } else {
869 Some(part_sort)
870 };
871 }
872 full_sort.ok_or_else(|| SorterError::NoSort(expr.to_string()))
873 }
874}
875
876impl<'s, T, A> SortableWithContext<'s, A> for Option<T>
877where
878 T: SortableWithContext<'s, A>,
879 A: 's + Clone,
880{
881 type Meta = OptionMetaWithContext<A>;
882
883 fn get_meta(access: A) -> Self::Meta {
884 OptionMetaWithContext { access }
885 }
886}
887
888#[doc(hidden)]
889pub struct OptionMetaWithContext<A> {
890 access: A,
891}
892
893impl<'s, T, A> Meta<'s, Option<T>> for OptionMetaWithContext<A>
894where
895 A: 's + Clone,
896 T: SortableWithContext<'s, A>,
897{
898 fn accept_visitor<V: SortVisitor<'s, Target = Option<T>>>(&self, visitor: &mut V)
899 where
900 Self: Sized,
901 {
902 let mut v = OptionVisitor { parent: visitor };
903 T::get_meta(self.access.clone()).accept_visitor(&mut v);
904 }
905}
906
907pub use django_query_derive::Sortable;
908
909#[cfg(feature = "persian-rug")]
910#[cfg_attr(docsrs, doc(cfg(feature = "persian-rug")))]
911pub use crate::persian_rug::SortableWithPersianRug;