graphrecords_query/element/
emission.rs1use 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}