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

geo-engine / geoengine / 10178074589

31 Jul 2024 09:34AM UTC coverage: 91.068% (+0.4%) from 90.682%
10178074589

push

github

web-flow
Merge pull request #973 from geo-engine/remove-XGB-update-toolchain

Remove-XGB-update-toolchain

81 of 88 new or added lines in 29 files covered. (92.05%)

456 existing lines in 119 files now uncovered.

131088 of 143945 relevant lines covered (91.07%)

53581.03 hits per line

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

43.48
/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>(
43
        &'a self,
44
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
45
        ctx: &'a dyn QueryContext,
46
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
1,159✔
47
        self.result_descriptor().validate_query(&query)?;
1,159✔
48

1,159✔
49
        Ok(Box::pin(
1,159✔
50
            ctx.abort_registration()
1,159✔
51
                .wrap(self._query(query, ctx).await?),
1,159✔
52
        ))
1,159✔
53
    }
1,159✔
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(
66
        self,
67
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
68
        ctx: Box<dyn QueryContext>,
69
    ) -> Result<OwnedQueryResultStream<Self>>
70
    where
71
        Self: Sized + 'static,
72
    {
2✔
73
        Ok(
2✔
74
            OwnedQueryResultStream::try_new_async_send(self, ctx, |processor, ctx| {
2✔
75
                processor.query(query, ctx.as_ref())
2✔
76
            })
2✔
77
            .await?,
2✔
78
        )
2✔
79
    }
2✔
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>>
313✔
96
    where
313✔
97
        Self: Sized + 'static,
313✔
98
    {
313✔
99
        Box::new(self)
313✔
100
    }
313✔
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>(
121
        &'a self,
122
        query: RasterQueryRectangle, // TODO: query by reference
123
        ctx: &'a dyn QueryContext,
124
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>> {
724✔
125
        self.query(query, ctx).await
724✔
126
    }
724✔
127

128
    fn raster_result_descriptor(&self) -> &RasterResultDescriptor {
335✔
129
        self.result_descriptor()
335✔
130
    }
335✔
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>>
158✔
144
    where
158✔
145
        Self: Sized + 'static,
158✔
146
    {
158✔
147
        Box::new(self)
158✔
148
    }
158✔
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>(
167
        &'a self,
168
        query: VectorQueryRectangle, // TODO: query by reference
169
        ctx: &'a dyn QueryContext,
170
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>> {
65✔
171
        self.query(query, ctx).await
65✔
172
    }
65✔
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>>
56✔
193
    where
56✔
194
        Self: Sized + 'static,
56✔
195
    {
56✔
196
        Box::new(self)
56✔
197
    }
56✔
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

221
    fn result_descriptor(&self) -> &Self::ResultDescription {
×
222
        self.as_ref().result_descriptor()
×
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>(
237
        &'a self,
238
        query: RasterQueryRectangle, // TODO: query by reference
239
        ctx: &'a dyn QueryContext,
240
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
650✔
241
        self.as_ref().raster_query(query, ctx).await
650✔
242
    }
650✔
243

244
    fn result_descriptor(&self) -> &Self::ResultDescription {
736✔
245
        self.as_ref().raster_result_descriptor()
736✔
246
    }
736✔
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>(
260
        &'a self,
261
        query: VectorQueryRectangle, // TODO: query by reference
262
        ctx: &'a dyn QueryContext,
263
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
186✔
264
        self.as_ref().vector_query(query, ctx).await
186✔
265
    }
186✔
266

267
    fn result_descriptor(&self) -> &Self::ResultDescription {
194✔
268
        self.as_ref().vector_result_descriptor()
194✔
269
    }
194✔
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 {
19✔
288
        match self {
19✔
289
            Self::U8(_) => geoengine_datatypes::raster::RasterDataType::U8,
8✔
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,
10✔
294
            Self::I16(_) => geoengine_datatypes::raster::RasterDataType::I16,
1✔
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
    }
19✔
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>>> {
100✔
323
        match self {
100✔
324
            Self::U8(r) => Some(r),
100✔
325
            _ => None,
×
326
        }
327
    }
100✔
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>>> {
43✔
347
        match self {
43✔
348
            Self::I8(r) => Some(r),
43✔
349
            _ => None,
×
350
        }
351
    }
43✔
352
    pub fn get_i16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i16>>> {
2✔
353
        match self {
2✔
354
            Self::I16(r) => Some(r),
2✔
355
            _ => None,
×
356
        }
357
    }
2✔
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>>> {
25✔
371
        match self {
25✔
372
            Self::F32(r) => Some(r),
25✔
373
            _ => None,
×
374
        }
375
    }
25✔
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

UNCOV
443
    pub fn into_f32(self) -> BoxRasterQueryProcessor<f32> {
×
UNCOV
444
        match self {
×
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(),
×
UNCOV
451
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
452
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
453
            Self::F32(r) => r,
×
454
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
455
        }
UNCOV
456
    }
×
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> {
19✔
519
        match self {
19✔
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(),
13✔
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
    }
19✔
532
}
533

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

540
impl From<Box<dyn RasterQueryProcessor<RasterType = i8>>> for TypedRasterQueryProcessor {
541
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i8>>) -> Self {
41✔
542
        TypedRasterQueryProcessor::I8(value)
41✔
543
    }
41✔
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 {
25✔
566
        TypedRasterQueryProcessor::I32(value)
25✔
567
    }
25✔
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>>> {
5✔
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(
54✔
609
        self,
54✔
610
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>> {
54✔
611
        if let TypedVectorQueryProcessor::MultiPoint(p) = self {
54✔
612
            Some(p)
54✔
613
        } else {
614
            None
×
615
        }
616
    }
54✔
617

618
    pub fn multi_line_string(
2✔
619
        self,
2✔
620
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>> {
2✔
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(
11✔
629
        self,
11✔
630
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>> {
11✔
631
        if let TypedVectorQueryProcessor::MultiPolygon(p) = self {
11✔
632
            Some(p)
11✔
633
        } else {
634
            None
×
635
        }
636
    }
11✔
637
}
638

639
impl TypedVectorQueryProcessor {
640
    fn type_str(&self) -> &str {
×
641
        match self {
×
642
            TypedVectorQueryProcessor::Data(_) => "Data",
×
643
            TypedVectorQueryProcessor::MultiPoint(_) => "MultiPoint",
×
644
            TypedVectorQueryProcessor::MultiLineString(_) => "MultiLineString",
×
645
            TypedVectorQueryProcessor::MultiPolygon(_) => "MultiPolygon",
×
646
        }
647
    }
×
648
}
649

650
impl TryFrom<TypedVectorQueryProcessor>
651
    for Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>
652
{
653
    type Error = crate::error::Error;
654

655
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
2✔
656
        if let TypedVectorQueryProcessor::MultiPoint(p) = value {
2✔
657
            Ok(p)
2✔
658
        } else {
659
            Err(crate::error::Error::InvalidVectorType {
×
660
                expected: "MultiPointCollection".to_string(),
×
661
                found: value.type_str().to_string(),
×
662
            })
×
663
        }
664
    }
2✔
665
}
666

667
impl TryFrom<TypedVectorQueryProcessor>
668
    for Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>
669
{
670
    type Error = crate::error::Error;
671

672
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
×
673
        if let TypedVectorQueryProcessor::MultiLineString(p) = value {
×
674
            Ok(p)
×
675
        } else {
676
            Err(crate::error::Error::InvalidVectorType {
×
677
                expected: "MultiLineStringCollection".to_string(),
×
678
                found: value.type_str().to_string(),
×
679
            })
×
680
        }
681
    }
×
682
}
683

684
impl TryFrom<TypedVectorQueryProcessor>
685
    for Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>
686
{
687
    type Error = crate::error::Error;
688

689
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
1✔
690
        if let TypedVectorQueryProcessor::MultiPolygon(p) = value {
1✔
691
            Ok(p)
1✔
692
        } else {
693
            Err(crate::error::Error::InvalidVectorType {
×
694
                expected: "MultiPolygonCollection".to_string(),
×
695
                found: value.type_str().to_string(),
×
696
            })
×
697
        }
698
    }
1✔
699
}
700

701
impl TryFrom<TypedVectorQueryProcessor>
702
    for Box<dyn VectorQueryProcessor<VectorType = DataCollection>>
703
{
704
    type Error = crate::error::Error;
705

706
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
×
707
        if let TypedVectorQueryProcessor::Data(p) = value {
×
708
            Ok(p)
×
709
        } else {
710
            Err(crate::error::Error::InvalidVectorType {
×
711
                expected: "DataCollection".to_string(),
×
712
                found: value.type_str().to_string(),
×
713
            })
×
714
        }
715
    }
×
716
}
717

718
impl From<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>>
719
    for TypedVectorQueryProcessor
720
{
721
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = DataCollection>>) -> Self {
×
722
        TypedVectorQueryProcessor::Data(value)
×
723
    }
×
724
}
725

726
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>>
727
    for TypedVectorQueryProcessor
728
{
729
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>) -> Self {
8✔
730
        TypedVectorQueryProcessor::MultiPoint(value)
8✔
731
    }
8✔
732
}
733

734
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>>
735
    for TypedVectorQueryProcessor
736
{
737
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>) -> Self {
×
738
        TypedVectorQueryProcessor::MultiLineString(value)
×
739
    }
×
740
}
741

742
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>>
743
    for TypedVectorQueryProcessor
744
{
745
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>) -> Self {
1✔
746
        TypedVectorQueryProcessor::MultiPolygon(value)
1✔
747
    }
1✔
748
}
749

750
/// An enum that contains all possible query processor variants
751
pub enum TypedPlotQueryProcessor {
752
    JsonPlain(Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>),
753
    JsonVega(Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>),
754
    ImagePng(Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>),
755
}
756

757
impl From<&TypedPlotQueryProcessor> for PlotOutputFormat {
758
    fn from(typed_processor: &TypedPlotQueryProcessor) -> Self {
2✔
759
        match typed_processor {
2✔
760
            TypedPlotQueryProcessor::JsonPlain(_) => PlotOutputFormat::JsonPlain,
1✔
761
            TypedPlotQueryProcessor::JsonVega(_) => PlotOutputFormat::JsonVega,
1✔
762
            TypedPlotQueryProcessor::ImagePng(_) => PlotOutputFormat::ImagePng,
×
763
        }
764
    }
2✔
765
}
766

767
impl TypedPlotQueryProcessor {
768
    pub fn plot_type(&self) -> &'static str {
2✔
769
        match self {
2✔
770
            TypedPlotQueryProcessor::JsonPlain(p) => p.plot_type(),
1✔
771
            TypedPlotQueryProcessor::JsonVega(p) => p.plot_type(),
1✔
772
            TypedPlotQueryProcessor::ImagePng(p) => p.plot_type(),
×
773
        }
774
    }
2✔
775

776
    pub fn json_plain(
9✔
777
        self,
9✔
778
    ) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>> {
9✔
779
        if let TypedPlotQueryProcessor::JsonPlain(p) = self {
9✔
780
            Some(p)
9✔
781
        } else {
782
            None
×
783
        }
784
    }
9✔
785

786
    pub fn json_vega(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>> {
44✔
787
        if let TypedPlotQueryProcessor::JsonVega(p) = self {
44✔
788
            Some(p)
44✔
789
        } else {
790
            None
×
791
        }
792
    }
44✔
793

794
    pub fn image_png(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>> {
×
795
        if let TypedPlotQueryProcessor::ImagePng(p) = self {
×
796
            Some(p)
×
797
        } else {
798
            None
×
799
        }
800
    }
×
801
}
802

803
/// Maps a `TypedVectorQueryProcessor` to another `TypedVectorQueryProcessor` by calling a function on its variant.
804
/// Call via `map_typed_query_processor!(input, processor => function)`.
805
#[macro_export]
806
macro_rules! map_typed_query_processor {
807
    ($input:expr, $processor:ident => $function_call:expr) => {
808
        map_typed_query_processor!(
809
            @variants $input, $processor => $function_call,
810
            Data, MultiPoint, MultiLineString, MultiPolygon
811
        )
812
    };
813

814
    (@variants $input:expr, $processor:ident => $function_call:expr, $($variant:tt),+) => {
815
        match $input {
816
            $(
817
                $crate::engine::TypedVectorQueryProcessor::$variant($processor) => {
818
                    $crate::engine::TypedVectorQueryProcessor::$variant($function_call)
819
                }
820
            )+
821
        }
822
    };
823
}
824

825
/// In the case that it is required to store a query stream in a struct with a static lifetime,
826
///  one can use this struct.
827
/// This struct owns the query processor and the query context and thus ensures that the query
828
/// has the lifetime dependencies it needs.
829
#[self_referencing]
4✔
830
pub struct OwnedQueryResultStream<Q>
831
where
832
    Q: QueryProcessor + 'static,
833
{
834
    processor: Q,
835
    ctx: Box<dyn QueryContext>,
836
    #[borrows(processor, ctx)]
837
    #[covariant]
838
    stream: BoxStream<'this, Result<Q::Output>>,
839
}
840

841
impl<Q> OwnedQueryResultStream<Q>
842
where
843
    Q: QueryProcessor + 'static,
844
{
845
    /// Stop/drop the current stream and return the query processor.
846
    pub fn into_query_processor(self) -> Q {
×
847
        self.into_heads().processor
×
848
    }
×
849
}
850

851
impl<Q> Stream for OwnedQueryResultStream<Q>
852
where
853
    Q: QueryProcessor + 'static,
854
{
855
    type Item = Result<Q::Output>;
856

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