Skip to main content

graphrecords_query/element/
emission.rs

1use crate::{
2    element::{Arity, OrderState, Ordered, Unordered},
3    optimizer::Estimate,
4    sealed::Sealed,
5};
6use std::marker::PhantomData;
7
8pub trait ElementEmission: Sealed + 'static {
9    type Step<T>;
10    type OutArity<C: Arity>: Arity;
11
12    fn map_step<T, U>(step: Self::Step<T>, function: impl Fn(T) -> U) -> Self::Step<U>;
13
14    fn apply<'a, C: Arity, X: 'a, Y: 'a>(
15        container: C::Container<'a, X>,
16        function: impl Fn(X) -> Self::Step<Y> + 'a,
17    ) -> <Self::OutArity<C> as Arity>::Container<'a, Y>;
18
19    fn default_estimate(input: Estimate) -> Estimate;
20}
21
22pub struct Preserving;
23pub struct Dropping;
24pub struct Expanding<O: OrderState>(PhantomData<O>);
25
26impl Sealed for Preserving {}
27impl Sealed for Dropping {}
28impl<O: OrderState> Sealed for Expanding<O> {}
29
30impl ElementEmission for Preserving {
31    type OutArity<C: Arity> = C;
32    type Step<T> = T;
33
34    fn map_step<T, U>(step: Self::Step<T>, function: impl Fn(T) -> U) -> Self::Step<U> {
35        function(step)
36    }
37
38    fn apply<'a, C: Arity, X: 'a, Y: 'a>(
39        container: C::Container<'a, X>,
40        function: impl Fn(X) -> Self::Step<Y> + 'a,
41    ) -> <Self::OutArity<C> as Arity>::Container<'a, Y> {
42        C::map_elements(container, function)
43    }
44
45    fn default_estimate(input: Estimate) -> Estimate {
46        Estimate {
47            elements: input.elements,
48            ..Estimate::UNKNOWN
49        }
50    }
51}
52
53impl ElementEmission for Dropping {
54    type OutArity<C: Arity> = C::AfterDrop;
55    type Step<T> = Option<T>;
56
57    fn map_step<T, U>(step: Self::Step<T>, function: impl Fn(T) -> U) -> Self::Step<U> {
58        step.map(function)
59    }
60
61    fn apply<'a, C: Arity, X: 'a, Y: 'a>(
62        container: C::Container<'a, X>,
63        function: impl Fn(X) -> Self::Step<Y> + 'a,
64    ) -> <Self::OutArity<C> as Arity>::Container<'a, Y> {
65        C::filter_map_elements(container, function)
66    }
67
68    fn default_estimate(_input: Estimate) -> Estimate {
69        Estimate::UNKNOWN
70    }
71}
72
73impl ElementEmission for Expanding<Ordered> {
74    type OutArity<C: Arity> = C::AfterOrderedExpansion;
75    type Step<T> = Vec<T>;
76
77    fn map_step<T, U>(step: Self::Step<T>, function: impl Fn(T) -> U) -> Self::Step<U> {
78        step.into_iter().map(function).collect()
79    }
80
81    fn apply<'a, C: Arity, X: 'a, Y: 'a>(
82        container: C::Container<'a, X>,
83        function: impl Fn(X) -> Self::Step<Y> + 'a,
84    ) -> <Self::OutArity<C> as Arity>::Container<'a, Y> {
85        C::flat_map_ordered_elements(container, function)
86    }
87
88    fn default_estimate(_input: Estimate) -> Estimate {
89        Estimate::UNKNOWN
90    }
91}
92
93impl ElementEmission for Expanding<Unordered> {
94    type OutArity<C: Arity> = C::AfterUnorderedExpansion;
95    type Step<T> = Vec<T>;
96
97    fn map_step<T, U>(step: Self::Step<T>, function: impl Fn(T) -> U) -> Self::Step<U> {
98        step.into_iter().map(function).collect()
99    }
100
101    fn apply<'a, C: Arity, X: 'a, Y: 'a>(
102        container: C::Container<'a, X>,
103        function: impl Fn(X) -> Self::Step<Y> + 'a,
104    ) -> <Self::OutArity<C> as Arity>::Container<'a, Y> {
105        C::flat_map_unordered_elements(container, function)
106    }
107
108    fn default_estimate(_input: Estimate) -> Estimate {
109        Estimate::UNKNOWN
110    }
111}
112
113pub trait Retention: ElementEmission {
114    type Then<R: Retention>: Retention;
115
116    fn keep<T>(value: T) -> Self::Step<T>;
117
118    fn absent<T, E>(error: impl FnOnce() -> E) -> Self::Step<Result<T, E>>;
119
120    fn map_step<T, U>(step: Self::Step<T>, function: impl FnOnce(T) -> U) -> Self::Step<U>;
121
122    fn collapse<T>(step: Self::Step<T>) -> Option<T>;
123
124    fn and_then<R, T, U, E, F>(
125        step: Self::Step<Result<T, E>>,
126        function: F,
127    ) -> <Self::Then<R> as ElementEmission>::Step<Result<U, E>>
128    where
129        R: Retention,
130        F: FnOnce(T) -> R::Step<Result<U, E>>;
131}
132
133impl Retention for Preserving {
134    type Then<R: Retention> = R;
135
136    fn keep<T>(value: T) -> Self::Step<T> {
137        value
138    }
139
140    fn absent<T, E>(error: impl FnOnce() -> E) -> Self::Step<Result<T, E>> {
141        Err(error())
142    }
143
144    fn map_step<T, U>(step: Self::Step<T>, function: impl FnOnce(T) -> U) -> Self::Step<U> {
145        function(step)
146    }
147
148    fn collapse<T>(step: Self::Step<T>) -> Option<T> {
149        Some(step)
150    }
151
152    fn and_then<R, T, U, E, F>(
153        step: Self::Step<Result<T, E>>,
154        function: F,
155    ) -> <Self::Then<R> as ElementEmission>::Step<Result<U, E>>
156    where
157        R: Retention,
158        F: FnOnce(T) -> R::Step<Result<U, E>>,
159    {
160        match step {
161            Ok(value) => function(value),
162            Err(error) => R::keep(Err(error)),
163        }
164    }
165}
166
167impl Retention for Dropping {
168    type Then<R: Retention> = Self;
169
170    fn keep<T>(value: T) -> Self::Step<T> {
171        Some(value)
172    }
173
174    fn absent<T, E>(_error: impl FnOnce() -> E) -> Self::Step<Result<T, E>> {
175        None
176    }
177
178    fn map_step<T, U>(step: Self::Step<T>, function: impl FnOnce(T) -> U) -> Self::Step<U> {
179        step.map(function)
180    }
181
182    fn collapse<T>(step: Self::Step<T>) -> Option<T> {
183        step
184    }
185
186    fn and_then<R, T, U, E, F>(
187        step: Self::Step<Result<T, E>>,
188        function: F,
189    ) -> <Self::Then<R> as ElementEmission>::Step<Result<U, E>>
190    where
191        R: Retention,
192        F: FnOnce(T) -> R::Step<Result<U, E>>,
193    {
194        match step {
195            None => None,
196            Some(Err(error)) => Some(Err(error)),
197            Some(Ok(value)) => R::collapse(function(value)),
198        }
199    }
200}