1
1
use crate :: future_wrapper:: FutureWrapper ;
2
- use crate :: resolve:: { Env , ResolvedPath } ;
2
+ use crate :: resolve:: { DataEquivalence , Env , ResolvedPath } ;
3
3
use futures:: future:: Shared ;
4
4
use std:: hash:: Hash ;
5
5
use std:: rc:: Rc ;
6
6
7
7
/// Interface for environment containers that support the operations required for query resolution.
8
- pub trait EnvContainer < ' sg , ' rslv , LABEL : ' sg , DATA : ' sg , DWFO > :
8
+ pub trait EnvContainer < ' sg , ' rslv , LABEL : ' sg , DATA : ' sg > :
9
9
From < Env < ' sg , LABEL , DATA > > + ' rslv
10
+ where
11
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
10
12
{
11
- /// Creates a new, container with an empty environment.
12
- fn empty ( ) -> Self ;
13
+ /// Creates a new container with an empty environment.
14
+ fn empty ( ) -> Self {
15
+ Self :: from ( Env :: new ( ) )
16
+ }
13
17
14
- /// Creates a new environment that contains path when `data_ok` is `true`, and is empty otherwise.
15
- fn inject_if ( data_ok : DWFO , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self ;
18
+ /// Creates a new container with a single path.
19
+ fn single ( path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
20
+ Self :: from ( Env :: single ( path) )
21
+ }
16
22
17
23
/// Maps the current container to a new one, based a provided mapping of the underlying environment.
18
24
fn flat_map (
@@ -21,23 +27,11 @@ pub trait EnvContainer<'sg, 'rslv, LABEL: 'sg, DATA: 'sg, DWFO>:
21
27
) -> Self ;
22
28
}
23
29
24
- impl < ' sg : ' rslv , ' rslv , LABEL : Eq , DATA : Eq > EnvContainer < ' sg , ' rslv , LABEL , DATA , bool >
30
+ impl < ' sg : ' rslv , ' rslv , LABEL : Eq , DATA : Eq > EnvContainer < ' sg , ' rslv , LABEL , DATA >
25
31
for Env < ' sg , LABEL , DATA >
26
32
where
27
33
ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
28
34
{
29
- fn empty ( ) -> Self {
30
- Self :: new ( )
31
- }
32
-
33
- fn inject_if ( data_ok : bool , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
34
- if data_ok {
35
- Self :: single ( path)
36
- } else {
37
- Self :: empty ( )
38
- }
39
- }
40
-
41
35
fn flat_map (
42
36
& self ,
43
37
map : impl ' rslv + for <' short > FnOnce ( & ' short Env < ' sg , LABEL , DATA > ) -> Self ,
@@ -46,25 +40,13 @@ where
46
40
}
47
41
}
48
42
49
- impl < ' sg : ' rslv , ' rslv , LABEL , DATA > EnvContainer < ' sg , ' rslv , LABEL , DATA , bool >
43
+ impl < ' sg : ' rslv , ' rslv , LABEL , DATA > EnvContainer < ' sg , ' rslv , LABEL , DATA >
50
44
for Rc < Env < ' sg , LABEL , DATA > >
51
45
where
52
46
ResolvedPath < ' sg , LABEL , DATA > : Hash ,
53
47
LABEL : ' sg + Eq + Clone ,
54
48
DATA : ' sg + Eq ,
55
49
{
56
- fn empty ( ) -> Self {
57
- Self :: new ( Env :: empty ( ) )
58
- }
59
-
60
- fn inject_if ( data_ok : bool , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
61
- if data_ok {
62
- Env :: single ( path) . into ( )
63
- } else {
64
- Self :: empty ( )
65
- }
66
- }
67
-
68
50
fn flat_map (
69
51
& self ,
70
52
map : impl for < ' short > FnOnce ( & ' short Env < ' sg , LABEL , DATA > ) -> Self ,
73
55
}
74
56
}
75
57
76
- // Implementations for Results
77
58
impl < ' sg , LABEL : ' sg , DATA : ' sg , E > From < Env < ' sg , LABEL , DATA > >
78
59
for Result < Env < ' sg , LABEL , DATA > , E >
79
60
{
@@ -83,23 +64,11 @@ impl<'sg, LABEL: 'sg, DATA: 'sg, E> From<Env<'sg, LABEL, DATA>>
83
64
}
84
65
85
66
impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq , E : ' rslv >
86
- EnvContainer < ' sg , ' rslv , LABEL , DATA , bool > for Result < Env < ' sg , LABEL , DATA > , E >
67
+ EnvContainer < ' sg , ' rslv , LABEL , DATA > for Result < Env < ' sg , LABEL , DATA > , E >
87
68
where
88
69
ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
89
70
E : Clone ,
90
71
{
91
- fn empty ( ) -> Self {
92
- Ok ( Env :: empty ( ) )
93
- }
94
-
95
- fn inject_if ( data_ok : bool , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
96
- if data_ok {
97
- Env :: single ( path) . into ( )
98
- } else {
99
- Env :: empty ( ) . into ( )
100
- }
101
- }
102
-
103
72
fn flat_map ( & self , map : impl for < ' short > FnOnce ( & Env < ' sg , LABEL , DATA > ) -> Self ) -> Self {
104
73
match self {
105
74
Ok ( env) => map ( env) ,
@@ -108,45 +77,22 @@ where
108
77
}
109
78
}
110
79
111
- impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq , E : ' rslv >
112
- EnvContainer < ' sg , ' rslv , LABEL , DATA , Result < bool , E > > for Result < Env < ' sg , LABEL , DATA > , E >
80
+ impl < ' sg : ' rslv , ' rslv , LABEL , DATA > From < Env < ' sg , LABEL , DATA > >
81
+ for FutureWrapper < ' rslv , Env < ' sg , LABEL , DATA > >
113
82
where
114
- ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
115
- E : Clone ,
83
+ LABEL : Clone ,
116
84
{
117
- fn empty ( ) -> Self {
118
- Ok ( Env :: empty ( ) )
119
- }
120
-
121
- fn inject_if ( data_ok : Result < bool , E > , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
122
- data_ok. map ( |ok| if ok { Env :: single ( path) } else { Env :: empty ( ) } )
123
- }
124
-
125
- fn flat_map ( & self , map : impl for < ' short > FnOnce ( & Env < ' sg , LABEL , DATA > ) -> Self ) -> Self {
126
- match self {
127
- Ok ( env) => map ( env) ,
128
- Err ( err) => Err ( err. clone ( ) ) ,
129
- }
85
+ fn from ( value : Env < ' sg , LABEL , DATA > ) -> Self {
86
+ FutureWrapper :: new ( std:: future:: ready ( value) )
130
87
}
131
88
}
132
- impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq > EnvContainer < ' sg , ' rslv , LABEL , DATA , bool >
89
+
90
+ impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq > EnvContainer < ' sg , ' rslv , LABEL , DATA >
133
91
for FutureWrapper < ' rslv , Env < ' sg , LABEL , DATA > >
134
92
where
135
93
ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
136
94
LABEL : Clone ,
137
95
{
138
- fn empty ( ) -> Self {
139
- FutureWrapper :: new ( std:: future:: ready ( Env :: empty ( ) ) )
140
- }
141
-
142
- fn inject_if ( data_ok : bool , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
143
- if data_ok {
144
- Env :: single ( path) . into ( )
145
- } else {
146
- Env :: empty ( ) . into ( )
147
- }
148
- }
149
-
150
96
fn flat_map (
151
97
& self ,
152
98
map : impl ' rslv + for <' short > FnOnce ( & ' short Env < ' sg , LABEL , DATA > ) -> Self ,
@@ -159,17 +105,51 @@ where
159
105
}
160
106
}
161
107
108
+ // Injectable
109
+
110
+ /// Environment Container in which a path can be injected based on a condition.
111
+ pub trait Injectable < ' sg , ' rslv , LABEL : ' sg , DATA : ' sg , DWFO > :
112
+ EnvContainer < ' sg , ' rslv , LABEL , DATA >
113
+ where
114
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
115
+ {
116
+ /// Creates a new environment that contains path when `data_ok` is `true`, and is empty otherwise.
117
+ fn inject_if ( data_ok : DWFO , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self ;
118
+ }
119
+
120
+ impl < ' sg : ' rslv , ' rslv , LABEL : Eq + ' sg , DATA : Eq + ' sg , ENVC >
121
+ Injectable < ' sg , ' rslv , LABEL , DATA , bool > for ENVC
122
+ where
123
+ ENVC : EnvContainer < ' sg , ' rslv , LABEL , DATA > ,
124
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
125
+ {
126
+ fn inject_if ( data_ok : bool , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
127
+ if data_ok {
128
+ Self :: single ( path)
129
+ } else {
130
+ Self :: empty ( )
131
+ }
132
+ }
133
+ }
134
+
135
+ impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq , E : ' rslv >
136
+ Injectable < ' sg , ' rslv , LABEL , DATA , Result < bool , E > > for Result < Env < ' sg , LABEL , DATA > , E >
137
+ where
138
+ ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
139
+ E : Clone ,
140
+ {
141
+ fn inject_if ( data_ok : Result < bool , E > , path : ResolvedPath < ' sg , LABEL , DATA > ) -> Self {
142
+ data_ok. map ( |ok| if ok { Env :: single ( path) } else { Env :: empty ( ) } )
143
+ }
144
+ }
145
+
162
146
impl < ' sg : ' rslv , ' rslv , LABEL : ' sg + Eq , DATA : ' sg + Eq >
163
- EnvContainer < ' sg , ' rslv , LABEL , DATA , FutureWrapper < ' rslv , bool > >
147
+ Injectable < ' sg , ' rslv , LABEL , DATA , FutureWrapper < ' rslv , bool > >
164
148
for FutureWrapper < ' rslv , Env < ' sg , LABEL , DATA > >
165
149
where
166
150
ResolvedPath < ' sg , LABEL , DATA > : Hash + Clone ,
167
151
LABEL : Clone ,
168
152
{
169
- fn empty ( ) -> Self {
170
- FutureWrapper :: new ( std:: future:: ready ( Env :: empty ( ) ) )
171
- }
172
-
173
153
fn inject_if (
174
154
data_ok : FutureWrapper < ' rslv , bool > ,
175
155
path : ResolvedPath < ' sg , LABEL , DATA > ,
@@ -183,25 +163,107 @@ where
183
163
}
184
164
} )
185
165
}
166
+ }
186
167
187
- fn flat_map (
188
- & self ,
189
- map : impl ' rslv + for <' short > FnOnce ( & ' short Env < ' sg , LABEL , DATA > ) -> Self ,
168
+ // Filtering
169
+
170
+ /// Sub trait of [EnvContainer] that validates that filtering operations (for shadowing) can be applied on it.
171
+ pub trait Filterable < ' sg , ' rslv , LABEL : ' sg , DATA : ' sg , DEQO > :
172
+ EnvContainer < ' sg , ' rslv , LABEL , DATA >
173
+ where
174
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
175
+ {
176
+ /// Implementation of the filter operation on this container.
177
+ fn filter (
178
+ base_env : & Env < ' sg , LABEL , DATA > ,
179
+ sub_env : & Env < ' sg , LABEL , DATA > ,
180
+ equiv : & ' rslv impl DataEquivalence < ' sg , DATA , Output = DEQO > ,
181
+ ) -> Self ;
182
+ }
183
+
184
+ impl < ' sg : ' rslv , ' rslv , LABEL : ' sg , DATA : ' sg , ENVC > Filterable < ' sg , ' rslv , LABEL , DATA , bool >
185
+ for ENVC
186
+ where
187
+ ENVC : EnvContainer < ' sg , ' rslv , LABEL , DATA > ,
188
+ Env < ' sg , LABEL , DATA > : Clone ,
189
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
190
+ {
191
+ fn filter (
192
+ base_env : & Env < ' sg , LABEL , DATA > ,
193
+ sub_env : & Env < ' sg , LABEL , DATA > ,
194
+ equiv : & ' rslv impl DataEquivalence < ' sg , DATA , Output = bool > ,
190
195
) -> Self {
191
- let fut = Shared :: clone ( & self . 0 ) ;
192
- FutureWrapper :: new ( async move {
193
- let env = fut. await ;
194
- map ( & env) . 0 . await
195
- } )
196
+ sub_env
197
+ . iter ( )
198
+ . filter ( |p1| !base_env. iter ( ) . any ( |p2| equiv. data_equiv ( p1. data , p2. data ) ) )
199
+ . cloned ( )
200
+ . collect :: < Env < _ , _ > > ( )
201
+ . into ( )
196
202
}
197
203
}
198
204
199
- impl < ' sg : ' rslv , ' rslv , LABEL , DATA > From < Env < ' sg , LABEL , DATA > >
205
+ impl < ' sg : ' rslv , ' rslv , LABEL : Clone + Eq + ' sg , DATA : Eq + ' sg , E : Clone + ' rslv >
206
+ Filterable < ' sg , ' rslv , LABEL , DATA , Result < bool , E > > for Result < Env < ' sg , LABEL , DATA > , E >
207
+ where
208
+ Env < ' sg , LABEL , DATA > : Clone ,
209
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
210
+ {
211
+ fn filter (
212
+ base_env : & Env < ' sg , LABEL , DATA > ,
213
+ sub_env : & Env < ' sg , LABEL , DATA > ,
214
+ equiv : & ' rslv impl DataEquivalence < ' sg , DATA , Output = Result < bool , E > > ,
215
+ ) -> Self {
216
+ let sub_env = sub_env. clone ( ) ;
217
+ sub_env. into_iter ( ) . try_fold (
218
+ Env :: new ( ) ,
219
+ |mut filtered_env : Env < ' sg , LABEL , DATA > , p1 : ResolvedPath < ' sg , LABEL , DATA > | {
220
+ let shadowed = base_env. iter ( ) . try_fold (
221
+ /* initially, not shadowed */ false ,
222
+ |previously_shadowed : bool , p2 : & ResolvedPath < ' sg , LABEL , DATA > | {
223
+ if previously_shadowed {
224
+ Ok ( true ) // if it was shadowed, it will be
225
+ } else {
226
+ // not yet shadowed, try if current path shadows
227
+ equiv. data_equiv ( p1. data , p2. data )
228
+ }
229
+ } ,
230
+ ) ?;
231
+ // p1 is not shadowed, so add it to accumulator
232
+ if !shadowed {
233
+ filtered_env. insert ( p1) ;
234
+ }
235
+
236
+ Ok ( filtered_env)
237
+ } ,
238
+ )
239
+ }
240
+ }
241
+
242
+ impl < ' sg : ' rslv , ' rslv , LABEL : Clone + Eq + ' sg , DATA : Eq + ' sg >
243
+ Filterable < ' sg , ' rslv , LABEL , DATA , FutureWrapper < ' rslv , bool > >
200
244
for FutureWrapper < ' rslv , Env < ' sg , LABEL , DATA > >
201
245
where
202
- LABEL : Clone ,
246
+ Env < ' sg , LABEL , DATA > : Clone ,
247
+ ResolvedPath < ' sg , LABEL , DATA > : Eq + Hash + Clone ,
203
248
{
204
- fn from ( value : Env < ' sg , LABEL , DATA > ) -> Self {
205
- FutureWrapper :: new ( std:: future:: ready ( value) )
249
+ fn filter (
250
+ base_env : & Env < ' sg , LABEL , DATA > ,
251
+ sub_env : & Env < ' sg , LABEL , DATA > ,
252
+ equiv : & ' rslv impl DataEquivalence < ' sg , DATA , Output = FutureWrapper < ' rslv , bool > > ,
253
+ ) -> Self {
254
+ let base_env = base_env. clone ( ) ;
255
+ let sub_env = sub_env. clone ( ) ;
256
+ FutureWrapper :: new ( async move {
257
+ let mut filtered_env = Env :: new ( ) ;
258
+ ' outer: for sub_path in sub_env {
259
+ for base_path in & base_env {
260
+ if equiv. data_equiv ( sub_path. data , base_path. data ) . await {
261
+ continue ' outer;
262
+ }
263
+ }
264
+ filtered_env. insert ( sub_path. clone ( ) ) ;
265
+ }
266
+ filtered_env
267
+ } )
206
268
}
207
269
}
0 commit comments