Skip to main content

graphrecords_query/element/
arity.rs

1use crate::sealed::Sealed;
2use std::marker::PhantomData;
3
4pub type BoxedIterator<'a, T> = Box<dyn Iterator<Item = T> + 'a>;
5
6pub trait Arity: 'static {
7    type Container<'a, X: 'a>: 'a;
8    type AfterDrop: Arity;
9    type AfterOrderedExpansion: Arity;
10    type AfterUnorderedExpansion: Arity;
11
12    fn map_elements<'a, X: 'a, Y: 'a>(
13        container: Self::Container<'a, X>,
14        function: impl Fn(X) -> Y + 'a,
15    ) -> Self::Container<'a, Y>;
16
17    fn filter_map_elements<'a, X: 'a, Y: 'a>(
18        container: Self::Container<'a, X>,
19        function: impl Fn(X) -> Option<Y> + 'a,
20    ) -> <Self::AfterDrop as Arity>::Container<'a, Y>;
21
22    fn flat_map_ordered_elements<'a, X: 'a, Y: 'a>(
23        container: Self::Container<'a, X>,
24        function: impl Fn(X) -> Vec<Y> + 'a,
25    ) -> <Self::AfterOrderedExpansion as Arity>::Container<'a, Y>;
26
27    fn flat_map_unordered_elements<'a, X: 'a, Y: 'a>(
28        container: Self::Container<'a, X>,
29        function: impl Fn(X) -> Vec<Y> + 'a,
30    ) -> <Self::AfterUnorderedExpansion as Arity>::Container<'a, Y>;
31}
32
33pub trait OrderState: Sealed + 'static {}
34
35pub struct Ordered;
36pub struct Unordered;
37
38impl Sealed for Ordered {}
39impl Sealed for Unordered {}
40
41impl OrderState for Ordered {}
42
43impl OrderState for Unordered {}
44
45pub struct Multiple<O: OrderState>(PhantomData<O>);
46pub struct Single;
47pub struct Definite;
48
49impl<O: OrderState> Arity for Multiple<O> {
50    type AfterDrop = Self;
51    type AfterOrderedExpansion = Self;
52    type AfterUnorderedExpansion = Multiple<Unordered>;
53    type Container<'a, X: 'a> = BoxedIterator<'a, X>;
54
55    fn map_elements<'a, X: 'a, Y: 'a>(
56        container: Self::Container<'a, X>,
57        function: impl Fn(X) -> Y + 'a,
58    ) -> Self::Container<'a, Y> {
59        Box::new(container.map(function))
60    }
61
62    fn filter_map_elements<'a, X: 'a, Y: 'a>(
63        container: Self::Container<'a, X>,
64        function: impl Fn(X) -> Option<Y> + 'a,
65    ) -> <Self::AfterDrop as Arity>::Container<'a, Y> {
66        Box::new(container.filter_map(function))
67    }
68
69    fn flat_map_ordered_elements<'a, X: 'a, Y: 'a>(
70        container: Self::Container<'a, X>,
71        function: impl Fn(X) -> Vec<Y> + 'a,
72    ) -> <Self::AfterOrderedExpansion as Arity>::Container<'a, Y> {
73        Box::new(container.flat_map(function))
74    }
75
76    fn flat_map_unordered_elements<'a, X: 'a, Y: 'a>(
77        container: Self::Container<'a, X>,
78        function: impl Fn(X) -> Vec<Y> + 'a,
79    ) -> <Self::AfterUnorderedExpansion as Arity>::Container<'a, Y> {
80        Box::new(container.flat_map(function))
81    }
82}
83
84impl Arity for Single {
85    type AfterDrop = Self;
86    type AfterOrderedExpansion = Multiple<Ordered>;
87    type AfterUnorderedExpansion = Multiple<Unordered>;
88    type Container<'a, X: 'a> = Option<X>;
89
90    fn map_elements<'a, X: 'a, Y: 'a>(
91        container: Self::Container<'a, X>,
92        function: impl Fn(X) -> Y + 'a,
93    ) -> Self::Container<'a, Y> {
94        container.map(function)
95    }
96
97    fn filter_map_elements<'a, X: 'a, Y: 'a>(
98        container: Self::Container<'a, X>,
99        function: impl Fn(X) -> Option<Y> + 'a,
100    ) -> <Self::AfterDrop as Arity>::Container<'a, Y> {
101        container.and_then(function)
102    }
103
104    fn flat_map_ordered_elements<'a, X: 'a, Y: 'a>(
105        container: Self::Container<'a, X>,
106        function: impl Fn(X) -> Vec<Y> + 'a,
107    ) -> <Self::AfterOrderedExpansion as Arity>::Container<'a, Y> {
108        Box::new(container.into_iter().flat_map(function))
109    }
110
111    fn flat_map_unordered_elements<'a, X: 'a, Y: 'a>(
112        container: Self::Container<'a, X>,
113        function: impl Fn(X) -> Vec<Y> + 'a,
114    ) -> <Self::AfterUnorderedExpansion as Arity>::Container<'a, Y> {
115        Box::new(container.into_iter().flat_map(function))
116    }
117}
118
119impl Arity for Definite {
120    type AfterDrop = Single;
121    type AfterOrderedExpansion = Multiple<Ordered>;
122    type AfterUnorderedExpansion = Multiple<Unordered>;
123    type Container<'a, X: 'a> = X;
124
125    fn map_elements<'a, X: 'a, Y: 'a>(
126        container: Self::Container<'a, X>,
127        function: impl Fn(X) -> Y + 'a,
128    ) -> Self::Container<'a, Y> {
129        function(container)
130    }
131
132    fn filter_map_elements<'a, X: 'a, Y: 'a>(
133        container: Self::Container<'a, X>,
134        function: impl Fn(X) -> Option<Y> + 'a,
135    ) -> <Self::AfterDrop as Arity>::Container<'a, Y> {
136        function(container)
137    }
138
139    fn flat_map_ordered_elements<'a, X: 'a, Y: 'a>(
140        container: Self::Container<'a, X>,
141        function: impl Fn(X) -> Vec<Y> + 'a,
142    ) -> <Self::AfterOrderedExpansion as Arity>::Container<'a, Y> {
143        Box::new(function(container).into_iter())
144    }
145
146    fn flat_map_unordered_elements<'a, X: 'a, Y: 'a>(
147        container: Self::Container<'a, X>,
148        function: impl Fn(X) -> Vec<Y> + 'a,
149    ) -> <Self::AfterUnorderedExpansion as Arity>::Container<'a, Y> {
150        Box::new(function(container).into_iter())
151    }
152}