• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 4205117943

pending completion
4205117943

push

github

GitHub
Merge #737

473 of 473 new or added lines in 6 files covered. (100.0%)

90778 of 103195 relevant lines covered (87.97%)

75809.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

42.02
/operators/src/engine/query_processor.rs
1
use std::pin::Pin;
2
use std::task::{Context, Poll};
3

4
use super::query::QueryContext;
5
use crate::processing::RasterTypeConversionQueryProcessor;
6
use crate::util::Result;
7
use async_trait::async_trait;
8
use futures::stream::BoxStream;
9
use futures::Stream;
10
use geoengine_datatypes::collections::{
11
    DataCollection, MultiLineStringCollection, MultiPolygonCollection,
12
};
13
use geoengine_datatypes::plots::{PlotData, PlotOutputFormat};
14
use geoengine_datatypes::primitives::{
15
    AxisAlignedRectangle, BoundingBox2D, PlotQueryRectangle, QueryRectangle, RasterQueryRectangle,
16
    SpatialPartition2D, VectorQueryRectangle,
17
};
18
use geoengine_datatypes::raster::Pixel;
19
use geoengine_datatypes::{collections::MultiPointCollection, raster::RasterTile2D};
20
use ouroboros::self_referencing;
21

22
/// An instantiation of an operator that produces a stream of results for a query
23
#[async_trait]
24
pub trait QueryProcessor: Send + Sync {
25
    type Output;
26
    type SpatialBounds: AxisAlignedRectangle + Send + Sync;
27

28
    /// inner logic of the processor
29
    async fn _query<'a>(
30
        &'a self,
31
        query: QueryRectangle<Self::SpatialBounds>,
32
        ctx: &'a dyn QueryContext,
33
    ) -> Result<BoxStream<'a, Result<Self::Output>>>;
34

35
    async fn query<'a>(
916✔
36
        &'a self,
916✔
37
        query: QueryRectangle<Self::SpatialBounds>,
916✔
38
        ctx: &'a dyn QueryContext,
916✔
39
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
916✔
40
        Ok(Box::pin(
41
            ctx.abort_registration()
916✔
42
                .wrap(self._query(query, ctx).await?),
916✔
43
        ))
44
    }
1,832✔
45
}
46

47
/// Advanced methods for query processors
48
#[async_trait]
49
pub trait QueryProcessorExt: QueryProcessor {
50
    /// Query the processor and retrieve a stream of results.
51
    ///
52
    /// This stream owns the processor and the query context to provide a static lifetime.
53
    /// Thus, it can be stored in a struct.
54
    async fn query_into_owned_stream(
1✔
55
        self,
1✔
56
        query: QueryRectangle<Self::SpatialBounds>,
1✔
57
        ctx: Box<dyn QueryContext>,
1✔
58
    ) -> Result<OwnedQueryResultStream<Self>>
1✔
59
    where
1✔
60
        Self: Sized + 'static,
1✔
61
    {
1✔
62
        Ok(
63
            OwnedQueryResultStream::try_new_async_send(self, ctx, |processor, ctx| {
1✔
64
                processor.query(query, ctx.as_ref())
1✔
65
            })
1✔
66
            .await?,
×
67
        )
68
    }
2✔
69
}
70

71
impl<Q> QueryProcessorExt for Q where Q: QueryProcessor {}
72

73
/// An instantiation of a raster operator that produces a stream of raster results for a query
74
#[async_trait]
75
pub trait RasterQueryProcessor: Sync + Send {
76
    type RasterType: Pixel;
77

78
    async fn raster_query<'a>(
79
        &'a self,
80
        query: RasterQueryRectangle,
81
        ctx: &'a dyn QueryContext,
82
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>>;
83

84
    fn boxed(self) -> Box<dyn RasterQueryProcessor<RasterType = Self::RasterType>>
271✔
85
    where
271✔
86
        Self: Sized + 'static,
271✔
87
    {
271✔
88
        Box::new(self)
271✔
89
    }
271✔
90
}
91

92
pub type BoxRasterQueryProcessor<P> = Box<dyn RasterQueryProcessor<RasterType = P>>;
93

94
#[async_trait]
95
impl<S, T> RasterQueryProcessor for S
96
where
97
    S: QueryProcessor<Output = RasterTile2D<T>, SpatialBounds = SpatialPartition2D> + Sync + Send,
98
    T: Pixel,
99
{
100
    type RasterType = T;
101
    async fn raster_query<'a>(
538✔
102
        &'a self,
538✔
103
        query: RasterQueryRectangle,
538✔
104
        ctx: &'a dyn QueryContext,
538✔
105
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>> {
538✔
106
        self.query(query, ctx).await
538✔
107
    }
1,076✔
108
}
109

110
/// An instantiation of a vector operator that produces a stream of vector results for a query
111
#[async_trait]
112
pub trait VectorQueryProcessor: Sync + Send {
113
    type VectorType;
114
    async fn vector_query<'a>(
115
        &'a self,
116
        query: VectorQueryRectangle,
117
        ctx: &'a dyn QueryContext,
118
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>>;
119

120
    fn boxed(self) -> Box<dyn VectorQueryProcessor<VectorType = Self::VectorType>>
137✔
121
    where
137✔
122
        Self: Sized + 'static,
137✔
123
    {
137✔
124
        Box::new(self)
137✔
125
    }
137✔
126
}
127

128
#[async_trait]
129
impl<S, VD> VectorQueryProcessor for S
130
where
131
    S: QueryProcessor<Output = VD, SpatialBounds = BoundingBox2D> + Sync + Send,
132
{
133
    type VectorType = VD;
134

135
    async fn vector_query<'a>(
55✔
136
        &'a self,
55✔
137
        query: VectorQueryRectangle,
55✔
138
        ctx: &'a dyn QueryContext,
55✔
139
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>> {
55✔
140
        self.query(query, ctx).await
55✔
141
    }
110✔
142
}
143

144
/// An instantiation of a plot operator that produces a stream of vector results for a query
145
#[async_trait]
146
pub trait PlotQueryProcessor: Sync + Send {
147
    type OutputFormat;
148

149
    fn plot_type(&self) -> &'static str;
150

151
    async fn plot_query<'a>(
152
        &'a self,
153
        query: PlotQueryRectangle,
154
        ctx: &'a dyn QueryContext,
155
    ) -> Result<Self::OutputFormat>;
156

157
    fn boxed(self) -> Box<dyn PlotQueryProcessor<OutputFormat = Self::OutputFormat>>
54✔
158
    where
54✔
159
        Self: Sized + 'static,
54✔
160
    {
54✔
161
        Box::new(self)
54✔
162
    }
54✔
163
}
164

165
#[async_trait]
166
impl<T, S> QueryProcessor for Box<dyn QueryProcessor<Output = T, SpatialBounds = S>>
167
where
168
    S: AxisAlignedRectangle + Send + Sync,
169
{
170
    type Output = T;
171
    type SpatialBounds = S;
172

173
    async fn _query<'a>(
×
174
        &'a self,
×
175
        query: QueryRectangle<S>,
×
176
        ctx: &'a dyn QueryContext,
×
177
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
×
178
        self.as_ref().query(query, ctx).await
×
179
    }
×
180
}
181

182
#[async_trait]
183
impl<T> QueryProcessor for Box<dyn RasterQueryProcessor<RasterType = T>>
184
where
185
    T: Pixel,
186
{
187
    type Output = RasterTile2D<T>;
188
    type SpatialBounds = SpatialPartition2D;
189

190
    async fn _query<'a>(
452✔
191
        &'a self,
452✔
192
        query: RasterQueryRectangle,
452✔
193
        ctx: &'a dyn QueryContext,
452✔
194
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
452✔
195
        self.as_ref().raster_query(query, ctx).await
452✔
196
    }
904✔
197
}
198

199
#[async_trait]
200
impl<V> QueryProcessor for Box<dyn VectorQueryProcessor<VectorType = V>>
201
where
202
    V: 'static,
203
{
204
    type Output = V;
205
    type SpatialBounds = BoundingBox2D;
206

207
    async fn _query<'a>(
165✔
208
        &'a self,
165✔
209
        query: VectorQueryRectangle,
165✔
210
        ctx: &'a dyn QueryContext,
165✔
211
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
165✔
212
        self.as_ref().vector_query(query, ctx).await
165✔
213
    }
330✔
214
}
215

216
/// An enum to differentiate between outputs of raster processors
217
pub enum TypedRasterQueryProcessor {
218
    U8(Box<dyn RasterQueryProcessor<RasterType = u8>>),
219
    U16(Box<dyn RasterQueryProcessor<RasterType = u16>>),
220
    U32(Box<dyn RasterQueryProcessor<RasterType = u32>>),
221
    U64(Box<dyn RasterQueryProcessor<RasterType = u64>>),
222
    I8(Box<dyn RasterQueryProcessor<RasterType = i8>>),
223
    I16(Box<dyn RasterQueryProcessor<RasterType = i16>>),
224
    I32(Box<dyn RasterQueryProcessor<RasterType = i32>>),
225
    I64(Box<dyn RasterQueryProcessor<RasterType = i64>>),
226
    F32(Box<dyn RasterQueryProcessor<RasterType = f32>>),
227
    F64(Box<dyn RasterQueryProcessor<RasterType = f64>>),
228
}
229

230
impl std::fmt::Debug for TypedRasterQueryProcessor {
231
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
232
        let interals = "RasterQueryProcessor"; // TODO: implement debug for children
×
233
        match self {
×
234
            Self::U8(_) => f.debug_tuple("U8").field(&interals).finish(),
×
235
            Self::U16(_) => f.debug_tuple("U16").field(&interals).finish(),
×
236
            Self::U32(_) => f.debug_tuple("U32").field(&interals).finish(),
×
237
            Self::U64(_) => f.debug_tuple("U64").field(&interals).finish(),
×
238
            Self::I8(_) => f.debug_tuple("I8").field(&interals).finish(),
×
239
            Self::I16(_) => f.debug_tuple("I16").field(&interals).finish(),
×
240
            Self::I32(_) => f.debug_tuple("I32").field(&interals).finish(),
×
241
            Self::I64(_) => f.debug_tuple("I64").field(&interals).finish(),
×
242
            Self::F32(_) => f.debug_tuple("F32").field(&interals).finish(),
×
243
            Self::F64(_) => f.debug_tuple("F64").field(&interals).finish(),
×
244
        }
245
    }
×
246
}
247

248
impl TypedRasterQueryProcessor {
249
    pub fn get_u8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u8>>> {
67✔
250
        match self {
67✔
251
            Self::U8(r) => Some(r),
67✔
252
            _ => None,
×
253
        }
254
    }
67✔
255
    pub fn get_u16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u16>>> {
3✔
256
        match self {
3✔
257
            Self::U16(r) => Some(r),
3✔
258
            _ => None,
×
259
        }
260
    }
3✔
261
    pub fn get_u32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u32>>> {
×
262
        match self {
×
263
            Self::U32(r) => Some(r),
×
264
            _ => None,
×
265
        }
266
    }
×
267
    pub fn get_u64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u64>>> {
×
268
        match self {
×
269
            Self::U64(r) => Some(r),
×
270
            _ => None,
×
271
        }
272
    }
×
273
    pub fn get_i8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i8>>> {
10✔
274
        match self {
10✔
275
            Self::I8(r) => Some(r),
10✔
276
            _ => None,
×
277
        }
278
    }
10✔
279
    pub fn get_i16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i16>>> {
×
280
        match self {
×
281
            Self::I16(r) => Some(r),
×
282
            _ => None,
×
283
        }
284
    }
×
285
    pub fn get_i32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i32>>> {
×
286
        match self {
×
287
            Self::I32(r) => Some(r),
×
288
            _ => None,
×
289
        }
290
    }
×
291
    pub fn get_i64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i64>>> {
×
292
        match self {
×
293
            Self::I64(r) => Some(r),
×
294
            _ => None,
×
295
        }
296
    }
×
297
    pub fn get_f32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f32>>> {
27✔
298
        match self {
27✔
299
            Self::F32(r) => Some(r),
27✔
300
            _ => None,
×
301
        }
302
    }
27✔
303
    pub fn get_f64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f64>>> {
9✔
304
        match self {
9✔
305
            Self::F64(r) => Some(r),
9✔
306
            _ => None,
×
307
        }
308
    }
9✔
309

310
    pub fn into_u8(self) -> BoxRasterQueryProcessor<u8> {
×
311
        match self {
×
312
            Self::U8(r) => r,
×
313
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
314
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
315
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
316
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
317
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
318
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
319
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
320
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
321
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
322
        }
323
    }
×
324

325
    pub fn into_u16(self) -> BoxRasterQueryProcessor<u16> {
1✔
326
        match self {
1✔
327
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
328
            Self::U16(r) => r,
×
329
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
330
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
331
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
332
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
333
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
334
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
335
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
336
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
337
        }
338
    }
1✔
339

340
    pub fn into_u32(self) -> BoxRasterQueryProcessor<u32> {
×
341
        match self {
×
342
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
343
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
344
            Self::U32(r) => r,
×
345
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
346
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
347
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
348
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
349
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
350
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
351
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
352
        }
353
    }
×
354

355
    pub fn into_u64(self) -> BoxRasterQueryProcessor<u64> {
×
356
        match self {
×
357
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
358
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
359
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
360
            Self::U64(r) => r,
×
361
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
362
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
363
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
364
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
365
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
366
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
367
        }
368
    }
×
369

370
    pub fn into_f32(self) -> BoxRasterQueryProcessor<f32> {
6✔
371
        match self {
6✔
372
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
373
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
374
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
375
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
376
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
377
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
378
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
6✔
379
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
380
            Self::F32(r) => r,
×
381
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
382
        }
383
    }
6✔
384

385
    pub fn into_i8(self) -> BoxRasterQueryProcessor<i8> {
×
386
        match self {
×
387
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
388
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
389
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
390
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
391
            Self::I8(r) => r,
×
392
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
393
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
394
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
395
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
396
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
397
        }
398
    }
×
399

400
    pub fn into_i16(self) -> BoxRasterQueryProcessor<i16> {
×
401
        match self {
×
402
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
403
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
404
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
405
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
406
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
407
            Self::I16(r) => r,
×
408
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
409
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
410
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
411
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
412
        }
413
    }
×
414

415
    pub fn into_i32(self) -> BoxRasterQueryProcessor<i32> {
×
416
        match self {
×
417
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
418
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
419
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
420
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
421
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
422
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
423
            Self::I32(r) => r,
×
424
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
425
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
426
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
427
        }
428
    }
×
429

430
    pub fn into_i64(self) -> BoxRasterQueryProcessor<i64> {
×
431
        match self {
×
432
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
433
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
434
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
435
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
436
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
437
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
438
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
439
            Self::I64(r) => r,
×
440
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
441
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
442
        }
443
    }
×
444

445
    pub fn into_f64(self) -> BoxRasterQueryProcessor<f64> {
23✔
446
        match self {
23✔
447
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
4✔
448
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
449
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
450
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
451
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
18✔
452
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
453
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
454
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
455
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
456
            Self::F64(r) => r,
×
457
        }
458
    }
23✔
459
}
460

461
impl From<Box<dyn RasterQueryProcessor<RasterType = u8>>> for TypedRasterQueryProcessor {
462
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u8>>) -> Self {
102✔
463
        TypedRasterQueryProcessor::U8(value)
102✔
464
    }
102✔
465
}
466

467
impl From<Box<dyn RasterQueryProcessor<RasterType = i8>>> for TypedRasterQueryProcessor {
468
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i8>>) -> Self {
23✔
469
        TypedRasterQueryProcessor::I8(value)
23✔
470
    }
23✔
471
}
472

473
impl From<Box<dyn RasterQueryProcessor<RasterType = u16>>> for TypedRasterQueryProcessor {
474
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u16>>) -> Self {
3✔
475
        TypedRasterQueryProcessor::U16(value)
3✔
476
    }
3✔
477
}
478

479
impl From<Box<dyn RasterQueryProcessor<RasterType = i16>>> for TypedRasterQueryProcessor {
480
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i16>>) -> Self {
×
481
        TypedRasterQueryProcessor::I16(value)
×
482
    }
×
483
}
484

485
impl From<Box<dyn RasterQueryProcessor<RasterType = u32>>> for TypedRasterQueryProcessor {
486
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u32>>) -> Self {
×
487
        TypedRasterQueryProcessor::U32(value)
×
488
    }
×
489
}
490

491
impl From<Box<dyn RasterQueryProcessor<RasterType = i32>>> for TypedRasterQueryProcessor {
492
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i32>>) -> Self {
28✔
493
        TypedRasterQueryProcessor::I32(value)
28✔
494
    }
28✔
495
}
496

497
impl From<Box<dyn RasterQueryProcessor<RasterType = u64>>> for TypedRasterQueryProcessor {
498
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u64>>) -> Self {
×
499
        TypedRasterQueryProcessor::U64(value)
×
500
    }
×
501
}
502
impl From<Box<dyn RasterQueryProcessor<RasterType = i64>>> for TypedRasterQueryProcessor {
503
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i64>>) -> Self {
×
504
        TypedRasterQueryProcessor::I64(value)
×
505
    }
×
506
}
507
impl From<Box<dyn RasterQueryProcessor<RasterType = f32>>> for TypedRasterQueryProcessor {
508
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f32>>) -> Self {
10✔
509
        TypedRasterQueryProcessor::F32(value)
10✔
510
    }
10✔
511
}
512
impl From<Box<dyn RasterQueryProcessor<RasterType = f64>>> for TypedRasterQueryProcessor {
513
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f64>>) -> Self {
×
514
        TypedRasterQueryProcessor::F64(value)
×
515
    }
×
516
}
517

518
/// An enum that contains all possible query processor variants
519
pub enum TypedVectorQueryProcessor {
520
    Data(Box<dyn VectorQueryProcessor<VectorType = DataCollection>>),
521
    MultiPoint(Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>),
522
    MultiLineString(Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>),
523
    MultiPolygon(Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>),
524
}
525

526
impl TypedVectorQueryProcessor {
527
    pub fn data(self) -> Option<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>> {
528
        if let TypedVectorQueryProcessor::Data(p) = self {
5✔
529
            Some(p)
5✔
530
        } else {
531
            None
×
532
        }
533
    }
5✔
534

535
    pub fn multi_point(
536
        self,
537
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>> {
538
        if let TypedVectorQueryProcessor::MultiPoint(p) = self {
51✔
539
            Some(p)
51✔
540
        } else {
541
            None
×
542
        }
543
    }
51✔
544

545
    pub fn multi_line_string(
546
        self,
547
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>> {
548
        if let TypedVectorQueryProcessor::MultiLineString(p) = self {
1✔
549
            Some(p)
1✔
550
        } else {
551
            None
×
552
        }
553
    }
1✔
554

555
    pub fn multi_polygon(
556
        self,
557
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>> {
558
        if let TypedVectorQueryProcessor::MultiPolygon(p) = self {
8✔
559
            Some(p)
8✔
560
        } else {
561
            None
×
562
        }
563
    }
8✔
564
}
565

566
impl From<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>>
567
    for TypedVectorQueryProcessor
568
{
569
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = DataCollection>>) -> Self {
×
570
        TypedVectorQueryProcessor::Data(value)
×
571
    }
×
572
}
573

574
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>>
575
    for TypedVectorQueryProcessor
576
{
577
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>) -> Self {
4✔
578
        TypedVectorQueryProcessor::MultiPoint(value)
4✔
579
    }
4✔
580
}
581

582
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>>
583
    for TypedVectorQueryProcessor
584
{
585
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>) -> Self {
×
586
        TypedVectorQueryProcessor::MultiLineString(value)
×
587
    }
×
588
}
589

590
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>>
591
    for TypedVectorQueryProcessor
592
{
593
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>) -> Self {
×
594
        TypedVectorQueryProcessor::MultiPolygon(value)
×
595
    }
×
596
}
597

598
/// An enum that contains all possible query processor variants
599
pub enum TypedPlotQueryProcessor {
600
    JsonPlain(Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>),
601
    JsonVega(Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>),
602
    ImagePng(Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>),
603
}
604

605
impl From<&TypedPlotQueryProcessor> for PlotOutputFormat {
606
    fn from(typed_processor: &TypedPlotQueryProcessor) -> Self {
2✔
607
        match typed_processor {
2✔
608
            TypedPlotQueryProcessor::JsonPlain(_) => PlotOutputFormat::JsonPlain,
1✔
609
            TypedPlotQueryProcessor::JsonVega(_) => PlotOutputFormat::JsonVega,
1✔
610
            TypedPlotQueryProcessor::ImagePng(_) => PlotOutputFormat::ImagePng,
×
611
        }
612
    }
2✔
613
}
614

615
impl TypedPlotQueryProcessor {
616
    pub fn plot_type(&self) -> &'static str {
2✔
617
        match self {
2✔
618
            TypedPlotQueryProcessor::JsonPlain(p) => p.plot_type(),
1✔
619
            TypedPlotQueryProcessor::JsonVega(p) => p.plot_type(),
1✔
620
            TypedPlotQueryProcessor::ImagePng(p) => p.plot_type(),
×
621
        }
622
    }
2✔
623

624
    pub fn json_plain(
625
        self,
626
    ) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>> {
627
        if let TypedPlotQueryProcessor::JsonPlain(p) = self {
7✔
628
            Some(p)
7✔
629
        } else {
630
            None
×
631
        }
632
    }
7✔
633

634
    pub fn json_vega(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>> {
635
        if let TypedPlotQueryProcessor::JsonVega(p) = self {
44✔
636
            Some(p)
44✔
637
        } else {
638
            None
×
639
        }
640
    }
44✔
641

642
    pub fn image_png(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>> {
643
        if let TypedPlotQueryProcessor::ImagePng(p) = self {
×
644
            Some(p)
×
645
        } else {
646
            None
×
647
        }
648
    }
×
649
}
650

651
/// Maps a `TypedVectorQueryProcessor` to another `TypedVectorQueryProcessor` by calling a function on its variant.
652
/// Call via `map_typed_query_processor!(input, processor => function)`.
653
#[macro_export]
654
macro_rules! map_typed_query_processor {
655
    ($input:expr, $processor:ident => $function_call:expr) => {
656
        map_typed_query_processor!(
657
            @variants $input, $processor => $function_call,
658
            Data, MultiPoint, MultiLineString, MultiPolygon
659
        )
660
    };
661

662
    (@variants $input:expr, $processor:ident => $function_call:expr, $($variant:tt),+) => {
663
        match $input {
664
            $(
665
                $crate::engine::TypedVectorQueryProcessor::$variant($processor) => {
666
                    $crate::engine::TypedVectorQueryProcessor::$variant($function_call)
667
                }
668
            )+
669
        }
670
    };
671
}
672

673
/// In the case that it is required to store a query stream in a struct with a static lifetime,
674
///  one can use this struct.
675
/// This struct owns the query processor and the query context and thus ensures that the query
676
/// has the lifetime dependencies it needs.
677
#[self_referencing]
4✔
678
pub struct OwnedQueryResultStream<Q>
679
where
680
    Q: QueryProcessor + 'static,
681
{
682
    processor: Q,
683
    ctx: Box<dyn QueryContext>,
684
    #[borrows(processor, ctx)]
685
    #[covariant]
686
    stream: BoxStream<'this, Result<Q::Output>>,
687
}
688

689
impl<Q> OwnedQueryResultStream<Q>
690
where
691
    Q: QueryProcessor + 'static,
692
{
693
    /// Stop/drop the current stream and return the query processor.
694
    pub fn into_query_processor(self) -> Q {
×
695
        self.into_heads().processor
×
696
    }
×
697
}
698

699
impl<Q> Stream for OwnedQueryResultStream<Q>
700
where
701
    Q: QueryProcessor + 'static,
702
{
703
    type Item = Result<Q::Output>;
704

705
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
9✔
706
        self.with_stream_mut(|stream| Pin::new(stream).poll_next(cx))
9✔
707
    }
9✔
708
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc