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

geo-engine / geoengine / 7276350647

20 Dec 2023 01:21PM UTC coverage: 89.798% (-0.03%) from 89.823%
7276350647

push

github

web-flow
Merge pull request #906 from geo-engine/raster_result_describer

result descriptors for query processors

1080 of 1240 new or added lines in 43 files covered. (87.1%)

11 existing lines in 3 files now uncovered.

115920 of 129090 relevant lines covered (89.8%)

58689.64 hits per line

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

45.08
/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 super::{RasterResultDescriptor, ResultDescriptor, VectorResultDescriptor};
6
use crate::processing::RasterTypeConversionQueryProcessor;
7
use crate::util::Result;
8
use async_trait::async_trait;
9
use futures::stream::BoxStream;
10
use futures::Stream;
11
use geoengine_datatypes::collections::{
12
    DataCollection, MultiLineStringCollection, MultiPolygonCollection,
13
};
14
use geoengine_datatypes::plots::{PlotData, PlotOutputFormat};
15
use geoengine_datatypes::primitives::{
16
    AxisAlignedRectangle, BandSelection, BoundingBox2D, ColumnSelection, PlotQueryRectangle,
17
    QueryAttributeSelection, QueryRectangle, RasterQueryRectangle, SpatialPartition2D,
18
    VectorQueryRectangle,
19
};
20
use geoengine_datatypes::raster::{DynamicRasterDataType, Pixel};
21
use geoengine_datatypes::{collections::MultiPointCollection, raster::RasterTile2D};
22
use ouroboros::self_referencing;
23

24
/// An instantiation of an operator that produces a stream of results for a query
25
#[async_trait]
26
pub trait QueryProcessor: Send + Sync {
27
    type Output;
28
    type SpatialBounds: AxisAlignedRectangle + Send + Sync;
29
    type Selection: QueryAttributeSelection;
30
    type ResultDescription: ResultDescriptor<
31
        QueryRectangleSpatialBounds = Self::SpatialBounds,
32
        QueryRectangleAttributeSelection = Self::Selection,
33
    >;
34

35
    /// inner logic of the processor
36
    async fn _query<'a>(
37
        &'a self,
38
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
39
        ctx: &'a dyn QueryContext,
40
    ) -> Result<BoxStream<'a, Result<Self::Output>>>;
41

42
    async fn query<'a>(
1,126✔
43
        &'a self,
1,126✔
44
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
1,126✔
45
        ctx: &'a dyn QueryContext,
1,126✔
46
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
1,126✔
47
        self.result_descriptor().validate_query(&query)?;
1,126✔
48

49
        Ok(Box::pin(
50
            ctx.abort_registration()
1,126✔
51
                .wrap(self._query(query, ctx).await?),
1,126✔
52
        ))
53
    }
2,252✔
54

55
    fn result_descriptor(&self) -> &Self::ResultDescription;
56
}
57

58
/// Advanced methods for query processors
59
#[async_trait]
60
pub trait QueryProcessorExt: QueryProcessor {
61
    /// Query the processor and retrieve a stream of results.
62
    ///
63
    /// This stream owns the processor and the query context to provide a static lifetime.
64
    /// Thus, it can be stored in a struct.
65
    async fn query_into_owned_stream(
2✔
66
        self,
2✔
67
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
2✔
68
        ctx: Box<dyn QueryContext>,
2✔
69
    ) -> Result<OwnedQueryResultStream<Self>>
2✔
70
    where
2✔
71
        Self: Sized + 'static,
2✔
72
    {
2✔
73
        Ok(
74
            OwnedQueryResultStream::try_new_async_send(self, ctx, |processor, ctx| {
2✔
75
                processor.query(query, ctx.as_ref())
2✔
76
            })
2✔
77
            .await?,
×
78
        )
79
    }
4✔
80
}
81

82
impl<Q> QueryProcessorExt for Q where Q: QueryProcessor {}
83

84
/// An instantiation of a raster operator that produces a stream of raster results for a query
85
#[async_trait]
86
pub trait RasterQueryProcessor: Sync + Send {
87
    type RasterType: Pixel;
88

89
    async fn raster_query<'a>(
90
        &'a self,
91
        query: RasterQueryRectangle, // TODO: query by reference
92
        ctx: &'a dyn QueryContext,
93
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>>;
94

95
    fn boxed(self) -> Box<dyn RasterQueryProcessor<RasterType = Self::RasterType>>
341✔
96
    where
341✔
97
        Self: Sized + 'static,
341✔
98
    {
341✔
99
        Box::new(self)
341✔
100
    }
341✔
101

102
    fn raster_result_descriptor(&self) -> &RasterResultDescriptor;
103
}
104

105
pub type BoxRasterQueryProcessor<P> = Box<dyn RasterQueryProcessor<RasterType = P>>;
106

107
#[async_trait]
108
impl<S, T> RasterQueryProcessor for S
109
where
110
    S: QueryProcessor<
111
            Output = RasterTile2D<T>,
112
            SpatialBounds = SpatialPartition2D,
113
            Selection = BandSelection,
114
            ResultDescription = RasterResultDescriptor,
115
        > + Sync
116
        + Send,
117
    T: Pixel,
118
{
119
    type RasterType = T;
120
    async fn raster_query<'a>(
692✔
121
        &'a self,
692✔
122
        query: RasterQueryRectangle, // TODO: query by reference
692✔
123
        ctx: &'a dyn QueryContext,
692✔
124
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>> {
692✔
125
        self.query(query, ctx).await
692✔
126
    }
1,384✔
127

128
    fn raster_result_descriptor(&self) -> &RasterResultDescriptor {
443✔
129
        self.result_descriptor()
443✔
130
    }
443✔
131
}
132

133
/// An instantiation of a vector operator that produces a stream of vector results for a query
134
#[async_trait]
135
pub trait VectorQueryProcessor: Sync + Send {
136
    type VectorType;
137
    async fn vector_query<'a>(
138
        &'a self,
139
        query: VectorQueryRectangle, // TODO: query by reference
140
        ctx: &'a dyn QueryContext,
141
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>>;
142

143
    fn boxed(self) -> Box<dyn VectorQueryProcessor<VectorType = Self::VectorType>>
146✔
144
    where
146✔
145
        Self: Sized + 'static,
146✔
146
    {
146✔
147
        Box::new(self)
146✔
148
    }
146✔
149

150
    fn vector_result_descriptor(&self) -> &VectorResultDescriptor;
151
}
152

153
#[async_trait]
154
impl<S, VD> VectorQueryProcessor for S
155
where
156
    S: QueryProcessor<
157
            Output = VD,
158
            SpatialBounds = BoundingBox2D,
159
            Selection = ColumnSelection,
160
            ResultDescription = VectorResultDescriptor,
161
        > + Sync
162
        + Send,
163
{
164
    type VectorType = VD;
165

166
    async fn vector_query<'a>(
60✔
167
        &'a self,
60✔
168
        query: VectorQueryRectangle, // TODO: query by reference
60✔
169
        ctx: &'a dyn QueryContext,
60✔
170
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>> {
60✔
171
        self.query(query, ctx).await
60✔
172
    }
120✔
173

174
    fn vector_result_descriptor(&self) -> &VectorResultDescriptor {
53✔
175
        self.result_descriptor()
53✔
176
    }
53✔
177
}
178

179
/// An instantiation of a plot operator that produces a stream of vector results for a query
180
#[async_trait]
181
pub trait PlotQueryProcessor: Sync + Send {
182
    type OutputFormat;
183

184
    fn plot_type(&self) -> &'static str;
185

186
    async fn plot_query<'a>(
187
        &'a self,
188
        query: PlotQueryRectangle, // TODO: query by reference
189
        ctx: &'a dyn QueryContext,
190
    ) -> Result<Self::OutputFormat>;
191

192
    fn boxed(self) -> Box<dyn PlotQueryProcessor<OutputFormat = Self::OutputFormat>>
54✔
193
    where
54✔
194
        Self: Sized + 'static,
54✔
195
    {
54✔
196
        Box::new(self)
54✔
197
    }
54✔
198
}
199

200
#[async_trait]
201
impl<T, S, U, R> QueryProcessor
202
    for Box<dyn QueryProcessor<Output = T, SpatialBounds = S, Selection = U, ResultDescription = R>>
203
where
204
    S: AxisAlignedRectangle + Send + Sync,
205
    U: QueryAttributeSelection,
206
    R: ResultDescriptor<QueryRectangleSpatialBounds = S, QueryRectangleAttributeSelection = U>,
207
{
208
    type Output = T;
209
    type SpatialBounds = S;
210
    type Selection = U;
211
    type ResultDescription = R;
212

213
    async fn _query<'a>(
×
214
        &'a self,
×
215
        query: QueryRectangle<S, U>, // TODO: query by reference
×
216
        ctx: &'a dyn QueryContext,
×
217
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
×
218
        self.as_ref().query(query, ctx).await
×
219
    }
×
220

NEW
221
    fn result_descriptor(&self) -> &Self::ResultDescription {
×
NEW
222
        self.as_ref().result_descriptor()
×
NEW
223
    }
×
224
}
225

226
#[async_trait]
227
impl<T> QueryProcessor for Box<dyn RasterQueryProcessor<RasterType = T>>
228
where
229
    T: Pixel,
230
{
231
    type Output = RasterTile2D<T>;
232
    type SpatialBounds = SpatialPartition2D;
233
    type Selection = BandSelection;
234
    type ResultDescription = RasterResultDescriptor;
235

236
    async fn _query<'a>(
602✔
237
        &'a self,
602✔
238
        query: RasterQueryRectangle, // TODO: query by reference
602✔
239
        ctx: &'a dyn QueryContext,
602✔
240
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
602✔
241
        self.as_ref().raster_query(query, ctx).await
602✔
242
    }
1,204✔
243

244
    fn result_descriptor(&self) -> &Self::ResultDescription {
772✔
245
        self.as_ref().raster_result_descriptor()
772✔
246
    }
772✔
247
}
248

249
#[async_trait]
250
impl<V> QueryProcessor for Box<dyn VectorQueryProcessor<VectorType = V>>
251
where
252
    V: 'static,
253
{
254
    type Output = V;
255
    type SpatialBounds = BoundingBox2D;
256
    type Selection = ColumnSelection;
257
    type ResultDescription = VectorResultDescriptor;
258

259
    async fn _query<'a>(
174✔
260
        &'a self,
174✔
261
        query: VectorQueryRectangle, // TODO: query by reference
174✔
262
        ctx: &'a dyn QueryContext,
174✔
263
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
174✔
264
        self.as_ref().vector_query(query, ctx).await
174✔
265
    }
348✔
266

267
    fn result_descriptor(&self) -> &Self::ResultDescription {
182✔
268
        self.as_ref().vector_result_descriptor()
182✔
269
    }
182✔
270
}
271

272
/// An enum to differentiate between outputs of raster processors
273
pub enum TypedRasterQueryProcessor {
274
    U8(Box<dyn RasterQueryProcessor<RasterType = u8>>),
275
    U16(Box<dyn RasterQueryProcessor<RasterType = u16>>),
276
    U32(Box<dyn RasterQueryProcessor<RasterType = u32>>),
277
    U64(Box<dyn RasterQueryProcessor<RasterType = u64>>),
278
    I8(Box<dyn RasterQueryProcessor<RasterType = i8>>),
279
    I16(Box<dyn RasterQueryProcessor<RasterType = i16>>),
280
    I32(Box<dyn RasterQueryProcessor<RasterType = i32>>),
281
    I64(Box<dyn RasterQueryProcessor<RasterType = i64>>),
282
    F32(Box<dyn RasterQueryProcessor<RasterType = f32>>),
283
    F64(Box<dyn RasterQueryProcessor<RasterType = f64>>),
284
}
285

286
impl DynamicRasterDataType for TypedRasterQueryProcessor {
287
    fn raster_data_type(&self) -> geoengine_datatypes::raster::RasterDataType {
5✔
288
        match self {
5✔
289
            Self::U8(_) => geoengine_datatypes::raster::RasterDataType::U8,
5✔
290
            Self::U16(_) => geoengine_datatypes::raster::RasterDataType::U16,
×
291
            Self::U32(_) => geoengine_datatypes::raster::RasterDataType::U32,
×
292
            Self::U64(_) => geoengine_datatypes::raster::RasterDataType::U64,
×
293
            Self::I8(_) => geoengine_datatypes::raster::RasterDataType::I8,
×
294
            Self::I16(_) => geoengine_datatypes::raster::RasterDataType::I16,
×
295
            Self::I32(_) => geoengine_datatypes::raster::RasterDataType::I32,
×
296
            Self::I64(_) => geoengine_datatypes::raster::RasterDataType::I64,
×
297
            Self::F32(_) => geoengine_datatypes::raster::RasterDataType::F32,
×
298
            Self::F64(_) => geoengine_datatypes::raster::RasterDataType::F64,
×
299
        }
300
    }
5✔
301
}
302

303
impl std::fmt::Debug for TypedRasterQueryProcessor {
304
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
305
        let interals = "RasterQueryProcessor"; // TODO: implement debug for children
×
306
        match self {
×
307
            Self::U8(_) => f.debug_tuple("U8").field(&interals).finish(),
×
308
            Self::U16(_) => f.debug_tuple("U16").field(&interals).finish(),
×
309
            Self::U32(_) => f.debug_tuple("U32").field(&interals).finish(),
×
310
            Self::U64(_) => f.debug_tuple("U64").field(&interals).finish(),
×
311
            Self::I8(_) => f.debug_tuple("I8").field(&interals).finish(),
×
312
            Self::I16(_) => f.debug_tuple("I16").field(&interals).finish(),
×
313
            Self::I32(_) => f.debug_tuple("I32").field(&interals).finish(),
×
314
            Self::I64(_) => f.debug_tuple("I64").field(&interals).finish(),
×
315
            Self::F32(_) => f.debug_tuple("F32").field(&interals).finish(),
×
316
            Self::F64(_) => f.debug_tuple("F64").field(&interals).finish(),
×
317
        }
318
    }
×
319
}
320

321
impl TypedRasterQueryProcessor {
322
    pub fn get_u8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u8>>> {
91✔
323
        match self {
91✔
324
            Self::U8(r) => Some(r),
91✔
325
            _ => None,
×
326
        }
327
    }
91✔
328
    pub fn get_u16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u16>>> {
3✔
329
        match self {
3✔
330
            Self::U16(r) => Some(r),
3✔
331
            _ => None,
×
332
        }
333
    }
3✔
334
    pub fn get_u32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u32>>> {
1✔
335
        match self {
1✔
336
            Self::U32(r) => Some(r),
1✔
337
            _ => None,
×
338
        }
339
    }
1✔
340
    pub fn get_u64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u64>>> {
×
341
        match self {
×
342
            Self::U64(r) => Some(r),
×
343
            _ => None,
×
344
        }
345
    }
×
346
    pub fn get_i8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i8>>> {
14✔
347
        match self {
14✔
348
            Self::I8(r) => Some(r),
14✔
349
            _ => None,
×
350
        }
351
    }
14✔
352
    pub fn get_i16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i16>>> {
×
353
        match self {
×
354
            Self::I16(r) => Some(r),
×
355
            _ => None,
×
356
        }
357
    }
×
358
    pub fn get_i32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i32>>> {
×
359
        match self {
×
360
            Self::I32(r) => Some(r),
×
361
            _ => None,
×
362
        }
363
    }
×
364
    pub fn get_i64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i64>>> {
×
365
        match self {
×
366
            Self::I64(r) => Some(r),
×
367
            _ => None,
×
368
        }
369
    }
×
370
    pub fn get_f32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f32>>> {
28✔
371
        match self {
28✔
372
            Self::F32(r) => Some(r),
28✔
373
            _ => None,
×
374
        }
375
    }
28✔
376
    pub fn get_f64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f64>>> {
9✔
377
        match self {
9✔
378
            Self::F64(r) => Some(r),
9✔
379
            _ => None,
×
380
        }
381
    }
9✔
382

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

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

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

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

443
    pub fn into_f32(self) -> BoxRasterQueryProcessor<f32> {
12✔
444
        match self {
12✔
445
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
446
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
447
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
448
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
449
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
450
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
451
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
12✔
452
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
453
            Self::F32(r) => r,
×
454
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
455
        }
456
    }
12✔
457

458
    pub fn into_i8(self) -> BoxRasterQueryProcessor<i8> {
×
459
        match self {
×
460
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
461
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
462
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
463
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
464
            Self::I8(r) => r,
×
465
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
466
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
467
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
468
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
469
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
470
        }
471
    }
×
472

473
    pub fn into_i16(self) -> BoxRasterQueryProcessor<i16> {
×
474
        match self {
×
475
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
476
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
477
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
478
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
479
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
480
            Self::I16(r) => r,
×
481
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
482
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
483
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
484
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
485
        }
486
    }
×
487

488
    pub fn into_i32(self) -> BoxRasterQueryProcessor<i32> {
×
489
        match self {
×
490
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
491
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
492
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
493
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
494
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
495
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
496
            Self::I32(r) => r,
×
497
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
498
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
499
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
500
        }
501
    }
×
502

503
    pub fn into_i64(self) -> BoxRasterQueryProcessor<i64> {
×
504
        match self {
×
505
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
506
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
507
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
508
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
509
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
510
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
511
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
512
            Self::I64(r) => r,
×
513
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
514
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
515
        }
516
    }
×
517

518
    pub fn into_f64(self) -> BoxRasterQueryProcessor<f64> {
33✔
519
        match self {
33✔
520
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
5✔
521
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
522
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
523
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
524
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
27✔
525
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
526
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
527
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
528
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
529
            Self::F64(r) => r,
×
530
        }
531
    }
33✔
532
}
533

534
impl From<Box<dyn RasterQueryProcessor<RasterType = u8>>> for TypedRasterQueryProcessor {
535
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u8>>) -> Self {
120✔
536
        TypedRasterQueryProcessor::U8(value)
120✔
537
    }
120✔
538
}
539

540
impl From<Box<dyn RasterQueryProcessor<RasterType = i8>>> for TypedRasterQueryProcessor {
541
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i8>>) -> Self {
34✔
542
        TypedRasterQueryProcessor::I8(value)
34✔
543
    }
34✔
544
}
545

546
impl From<Box<dyn RasterQueryProcessor<RasterType = u16>>> for TypedRasterQueryProcessor {
547
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u16>>) -> Self {
3✔
548
        TypedRasterQueryProcessor::U16(value)
3✔
549
    }
3✔
550
}
551

552
impl From<Box<dyn RasterQueryProcessor<RasterType = i16>>> for TypedRasterQueryProcessor {
553
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i16>>) -> Self {
×
554
        TypedRasterQueryProcessor::I16(value)
×
555
    }
×
556
}
557

558
impl From<Box<dyn RasterQueryProcessor<RasterType = u32>>> for TypedRasterQueryProcessor {
559
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u32>>) -> Self {
1✔
560
        TypedRasterQueryProcessor::U32(value)
1✔
561
    }
1✔
562
}
563

564
impl From<Box<dyn RasterQueryProcessor<RasterType = i32>>> for TypedRasterQueryProcessor {
565
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i32>>) -> Self {
43✔
566
        TypedRasterQueryProcessor::I32(value)
43✔
567
    }
43✔
568
}
569

570
impl From<Box<dyn RasterQueryProcessor<RasterType = u64>>> for TypedRasterQueryProcessor {
571
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u64>>) -> Self {
×
572
        TypedRasterQueryProcessor::U64(value)
×
573
    }
×
574
}
575
impl From<Box<dyn RasterQueryProcessor<RasterType = i64>>> for TypedRasterQueryProcessor {
576
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i64>>) -> Self {
×
577
        TypedRasterQueryProcessor::I64(value)
×
578
    }
×
579
}
580
impl From<Box<dyn RasterQueryProcessor<RasterType = f32>>> for TypedRasterQueryProcessor {
581
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f32>>) -> Self {
10✔
582
        TypedRasterQueryProcessor::F32(value)
10✔
583
    }
10✔
584
}
585
impl From<Box<dyn RasterQueryProcessor<RasterType = f64>>> for TypedRasterQueryProcessor {
586
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f64>>) -> Self {
×
587
        TypedRasterQueryProcessor::F64(value)
×
588
    }
×
589
}
590

591
/// An enum that contains all possible query processor variants
592
pub enum TypedVectorQueryProcessor {
593
    Data(Box<dyn VectorQueryProcessor<VectorType = DataCollection>>),
594
    MultiPoint(Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>),
595
    MultiLineString(Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>),
596
    MultiPolygon(Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>),
597
}
598

599
impl TypedVectorQueryProcessor {
600
    pub fn data(self) -> Option<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>> {
601
        if let TypedVectorQueryProcessor::Data(p) = self {
5✔
602
            Some(p)
5✔
603
        } else {
604
            None
×
605
        }
606
    }
5✔
607

608
    pub fn multi_point(
609
        self,
610
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>> {
611
        if let TypedVectorQueryProcessor::MultiPoint(p) = self {
52✔
612
            Some(p)
52✔
613
        } else {
614
            None
×
615
        }
616
    }
52✔
617

618
    pub fn multi_line_string(
619
        self,
620
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>> {
621
        if let TypedVectorQueryProcessor::MultiLineString(p) = self {
2✔
622
            Some(p)
2✔
623
        } else {
624
            None
×
625
        }
626
    }
2✔
627

628
    pub fn multi_polygon(
629
        self,
630
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>> {
631
        if let TypedVectorQueryProcessor::MultiPolygon(p) = self {
10✔
632
            Some(p)
10✔
633
        } else {
634
            None
×
635
        }
636
    }
10✔
637
}
638

639
impl From<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>>
640
    for TypedVectorQueryProcessor
641
{
642
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = DataCollection>>) -> Self {
×
643
        TypedVectorQueryProcessor::Data(value)
×
644
    }
×
645
}
646

647
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>>
648
    for TypedVectorQueryProcessor
649
{
650
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>) -> Self {
4✔
651
        TypedVectorQueryProcessor::MultiPoint(value)
4✔
652
    }
4✔
653
}
654

655
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>>
656
    for TypedVectorQueryProcessor
657
{
658
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>) -> Self {
×
659
        TypedVectorQueryProcessor::MultiLineString(value)
×
660
    }
×
661
}
662

663
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>>
664
    for TypedVectorQueryProcessor
665
{
666
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>) -> Self {
×
667
        TypedVectorQueryProcessor::MultiPolygon(value)
×
668
    }
×
669
}
670

671
/// An enum that contains all possible query processor variants
672
pub enum TypedPlotQueryProcessor {
673
    JsonPlain(Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>),
674
    JsonVega(Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>),
675
    ImagePng(Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>),
676
}
677

678
impl From<&TypedPlotQueryProcessor> for PlotOutputFormat {
679
    fn from(typed_processor: &TypedPlotQueryProcessor) -> Self {
2✔
680
        match typed_processor {
2✔
681
            TypedPlotQueryProcessor::JsonPlain(_) => PlotOutputFormat::JsonPlain,
1✔
682
            TypedPlotQueryProcessor::JsonVega(_) => PlotOutputFormat::JsonVega,
1✔
683
            TypedPlotQueryProcessor::ImagePng(_) => PlotOutputFormat::ImagePng,
×
684
        }
685
    }
2✔
686
}
687

688
impl TypedPlotQueryProcessor {
689
    pub fn plot_type(&self) -> &'static str {
2✔
690
        match self {
2✔
691
            TypedPlotQueryProcessor::JsonPlain(p) => p.plot_type(),
1✔
692
            TypedPlotQueryProcessor::JsonVega(p) => p.plot_type(),
1✔
693
            TypedPlotQueryProcessor::ImagePng(p) => p.plot_type(),
×
694
        }
695
    }
2✔
696

697
    pub fn json_plain(
698
        self,
699
    ) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>> {
700
        if let TypedPlotQueryProcessor::JsonPlain(p) = self {
7✔
701
            Some(p)
7✔
702
        } else {
703
            None
×
704
        }
705
    }
7✔
706

707
    pub fn json_vega(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>> {
708
        if let TypedPlotQueryProcessor::JsonVega(p) = self {
44✔
709
            Some(p)
44✔
710
        } else {
711
            None
×
712
        }
713
    }
44✔
714

715
    pub fn image_png(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>> {
716
        if let TypedPlotQueryProcessor::ImagePng(p) = self {
×
717
            Some(p)
×
718
        } else {
719
            None
×
720
        }
721
    }
×
722
}
723

724
/// Maps a `TypedVectorQueryProcessor` to another `TypedVectorQueryProcessor` by calling a function on its variant.
725
/// Call via `map_typed_query_processor!(input, processor => function)`.
726
#[macro_export]
727
macro_rules! map_typed_query_processor {
728
    ($input:expr, $processor:ident => $function_call:expr) => {
729
        map_typed_query_processor!(
730
            @variants $input, $processor => $function_call,
731
            Data, MultiPoint, MultiLineString, MultiPolygon
732
        )
733
    };
734

735
    (@variants $input:expr, $processor:ident => $function_call:expr, $($variant:tt),+) => {
736
        match $input {
737
            $(
738
                $crate::engine::TypedVectorQueryProcessor::$variant($processor) => {
739
                    $crate::engine::TypedVectorQueryProcessor::$variant($function_call)
740
                }
741
            )+
742
        }
743
    };
744
}
745

746
/// In the case that it is required to store a query stream in a struct with a static lifetime,
747
///  one can use this struct.
748
/// This struct owns the query processor and the query context and thus ensures that the query
749
/// has the lifetime dependencies it needs.
750
#[self_referencing]
8✔
751
pub struct OwnedQueryResultStream<Q>
752
where
753
    Q: QueryProcessor + 'static,
754
{
755
    processor: Q,
756
    ctx: Box<dyn QueryContext>,
757
    #[borrows(processor, ctx)]
758
    #[covariant]
759
    stream: BoxStream<'this, Result<Q::Output>>,
760
}
761

762
impl<Q> OwnedQueryResultStream<Q>
763
where
764
    Q: QueryProcessor + 'static,
765
{
766
    /// Stop/drop the current stream and return the query processor.
767
    pub fn into_query_processor(self) -> Q {
×
768
        self.into_heads().processor
×
769
    }
×
770
}
771

772
impl<Q> Stream for OwnedQueryResultStream<Q>
773
where
774
    Q: QueryProcessor + 'static,
775
{
776
    type Item = Result<Q::Output>;
777

778
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
13✔
779
        self.with_stream_mut(|stream| Pin::new(stream).poll_next(cx))
13✔
780
    }
13✔
781
}
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

© 2026 Coveralls, Inc