Skip to main content

graphrecords_query/capabilities/
sortable.rs

1use crate::{ExpandedIndexOwned, ExpandedIndexReference, IndexDomain, Position};
2use graphrecords_core::graphrecord::{EdgeIndex, GraphRecordAttribute, GraphRecordValue};
3
4pub trait EnsureSortable: PartialOrd + Sized {
5    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)>
6    where
7        Self: 'a;
8}
9
10pub fn incomparable_with_first<'a, V: PartialOrd + 'a>(
11    mut values: impl Iterator<Item = &'a V>,
12) -> Option<(usize, usize)> {
13    let first = values.next()?;
14
15    values
16        .position(|value| value.partial_cmp(first).is_none())
17        .map(|position| (0, position + 1))
18}
19
20pub fn incomparable_pair<'a, V: PartialOrd + 'a>(
21    values: impl Iterator<Item = &'a V>,
22) -> Option<(usize, usize)> {
23    let values: Vec<_> = values.collect();
24
25    for first_position in 0..values.len() {
26        for second_position in (first_position + 1)..values.len() {
27            if values[first_position]
28                .partial_cmp(values[second_position])
29                .is_none()
30            {
31                return Some((first_position, second_position));
32            }
33        }
34    }
35
36    None
37}
38
39impl<T: EnsureSortable> EnsureSortable for &T {
40    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)>
41    where
42        Self: 'a,
43    {
44        T::find_incomparable(values.copied())
45    }
46}
47
48impl EnsureSortable for GraphRecordValue {
49    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)> {
50        incomparable_with_first(values)
51    }
52}
53
54impl EnsureSortable for GraphRecordAttribute {
55    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)> {
56        incomparable_with_first(values)
57    }
58}
59
60impl EnsureSortable for bool {
61    fn find_incomparable<'a>(_values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)> {
62        None
63    }
64}
65
66impl EnsureSortable for Position {
67    fn find_incomparable<'a>(_values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)> {
68        None
69    }
70}
71
72impl EnsureSortable for EdgeIndex {
73    fn find_incomparable<'a>(_values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)> {
74        None
75    }
76}
77
78impl<P, C> EnsureSortable for ExpandedIndexOwned<P, C>
79where
80    P: IndexDomain,
81    C: IndexDomain,
82    P::Owned: EnsureSortable,
83    C::Owned: EnsureSortable,
84{
85    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)>
86    where
87        Self: 'a,
88    {
89        incomparable_pair(values)
90    }
91}
92
93impl<'index, P, C> EnsureSortable for ExpandedIndexReference<'index, P, C>
94where
95    P: IndexDomain,
96    C: IndexDomain,
97    P::Index<'index>: EnsureSortable,
98    C::Index<'index>: EnsureSortable,
99{
100    fn find_incomparable<'a>(values: impl Iterator<Item = &'a Self>) -> Option<(usize, usize)>
101    where
102        Self: 'a,
103    {
104        incomparable_pair(values)
105    }
106}