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

geo-engine / geoengine / 17457762072

04 Sep 2025 08:18AM UTC coverage: 88.257%. First build
17457762072

Pull #1079

github

web-flow
Merge d0272c3f0 into 85068105d
Pull Request #1079: refactor(operators): Reorder QueryProcessor and RasterQueryProcessor traits

70 of 78 new or added lines in 18 files covered. (89.74%)

113324 of 128402 relevant lines covered (88.26%)

229107.11 hits per line

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

43.82
/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;
10
use futures::stream::BoxStream;
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, VectorQueryRectangle,
18
};
19
use geoengine_datatypes::raster::{DynamicRasterDataType, GridBoundingBox2D, Pixel};
20
use geoengine_datatypes::{collections::MultiPointCollection, raster::RasterTile2D};
21
use ouroboros::self_referencing;
22

23
/// An instantiation of an operator that produces a stream of results for a query
24
#[async_trait]
25
pub trait QueryProcessor: Send + Sync {
26
    type Output;
27
    type SpatialBounds: Send + Sync;
28
    type Selection: QueryAttributeSelection;
29
    type ResultDescription: ResultDescriptor<
30
            QueryRectangleSpatialBounds = Self::SpatialBounds,
31
            QueryRectangleAttributeSelection = Self::Selection,
32
        >;
33
    /// inner logic of the processor
34
    async fn _query<'a>(
35
        &'a self,
36
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
37
        ctx: &'a dyn QueryContext,
38
    ) -> Result<BoxStream<'a, Result<Self::Output>>>;
39

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

47
        #[allow(clippy::used_underscore_items)] // TODO: maybe rename?
48
        Ok(Box::pin(
2,303✔
49
            ctx.abort_registration()
2,306✔
50
                .wrap(self._query(query, ctx).await?),
2,306✔
51
        ))
52
    }
4,612✔
53

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

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

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

83
/// An instantiation of a raster operator that produces a stream of raster results for a query
84
#[async_trait]
85
pub trait RasterQueryProcessor:
86
    QueryProcessor<
87
        Output = RasterTile2D<Self::RasterType>,
88
        SpatialBounds = GridBoundingBox2D,
89
        Selection = BandSelection,
90
        ResultDescription = RasterResultDescriptor,
91
    > + Sync
92
    + Send
93
{
94
    type RasterType: Pixel;
95

96
    async fn raster_query<'a>(
97
        &'a self,
98
        query: RasterQueryRectangle, // TODO: query by reference
99
        ctx: &'a dyn QueryContext,
100
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>> {
3,546✔
101
        self.query(query, ctx).await
1,773✔
102
    }
3,546✔
103

104
    fn boxed(
339✔
105
        self,
339✔
106
    ) -> Box<
339✔
107
        dyn RasterQueryProcessor<
339✔
108
                RasterType = Self::RasterType,
339✔
109
                Output = RasterTile2D<Self::RasterType>,
339✔
110
                SpatialBounds = GridBoundingBox2D,
339✔
111
                Selection = BandSelection,
339✔
112
                ResultDescription = RasterResultDescriptor,
339✔
113
            >,
339✔
114
    >
339✔
115
    where
339✔
116
        Self: Sized + 'static,
339✔
117
    {
118
        Box::new(self)
339✔
119
    }
339✔
120

121
    fn raster_result_descriptor(&self) -> &RasterResultDescriptor {
1,623✔
122
        self.result_descriptor()
1,623✔
123
    }
1,623✔
124
}
125

126
pub type BoxRasterQueryProcessor<P> = Box<
127
    dyn RasterQueryProcessor<
128
            RasterType = P,
129
            Output = RasterTile2D<P>,
130
            SpatialBounds = GridBoundingBox2D,
131
            Selection = BandSelection,
132
            ResultDescription = RasterResultDescriptor,
133
        >,
134
>;
135

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

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

153
    fn vector_result_descriptor(&self) -> &VectorResultDescriptor;
154
}
155

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

169
    async fn vector_query<'a>(
170
        &'a self,
171
        query: VectorQueryRectangle, // TODO: query by reference
172
        ctx: &'a dyn QueryContext,
173
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>> {
146✔
174
        self.query(query, ctx).await
73✔
175
    }
146✔
176

177
    fn vector_result_descriptor(&self) -> &VectorResultDescriptor {
75✔
178
        self.result_descriptor()
75✔
179
    }
75✔
180
}
181

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

187
    fn plot_type(&self) -> &'static str;
188

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

195
    fn boxed(self) -> Box<dyn PlotQueryProcessor<OutputFormat = Self::OutputFormat>>
56✔
196
    where
56✔
197
        Self: Sized + 'static,
56✔
198
    {
199
        Box::new(self)
56✔
200
    }
56✔
201
}
202

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

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

224
    fn result_descriptor(&self) -> &Self::ResultDescription {
×
225
        self.as_ref().result_descriptor()
×
226
    }
×
227
}
228

229
#[async_trait]
230
impl<T> QueryProcessor for BoxRasterQueryProcessor<T>
231
where
232
    T: Pixel,
233
{
234
    type Output = RasterTile2D<T>;
235
    type SpatialBounds = GridBoundingBox2D;
236
    type Selection = BandSelection;
237
    type ResultDescription = RasterResultDescriptor;
238

239
    async fn _query<'a>(
240
        &'a self,
241
        query: RasterQueryRectangle, // TODO: query by reference
242
        ctx: &'a dyn QueryContext,
243
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
2,020✔
244
        self.as_ref().raster_query(query, ctx).await
1,010✔
245
    }
2,020✔
246

247
    fn result_descriptor(&self) -> &Self::ResultDescription {
1,464✔
248
        self.as_ref().raster_result_descriptor()
1,464✔
249
    }
1,464✔
250
}
251

252
#[async_trait]
253
impl<T: Pixel> RasterQueryProcessor for BoxRasterQueryProcessor<T> {
254
    type RasterType = T;
255
}
256

257
#[async_trait]
258
impl<V> QueryProcessor for Box<dyn VectorQueryProcessor<VectorType = V>>
259
where
260
    V: 'static,
261
{
262
    type Output = V;
263
    type SpatialBounds = BoundingBox2D;
264
    type Selection = ColumnSelection;
265
    type ResultDescription = VectorResultDescriptor;
266

267
    async fn _query<'a>(
268
        &'a self,
269
        query: VectorQueryRectangle, // TODO: query by reference
270
        ctx: &'a dyn QueryContext,
271
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
354✔
272
        self.as_ref().vector_query(query, ctx).await
177✔
273
    }
354✔
274

275
    fn result_descriptor(&self) -> &Self::ResultDescription {
199✔
276
        self.as_ref().vector_result_descriptor()
199✔
277
    }
199✔
278
}
279

280
/// An enum to differentiate between outputs of raster processors
281
pub enum TypedRasterQueryProcessor {
282
    U8(BoxRasterQueryProcessor<u8>),
283
    U16(BoxRasterQueryProcessor<u16>),
284
    U32(BoxRasterQueryProcessor<u32>),
285
    U64(BoxRasterQueryProcessor<u64>),
286
    I8(BoxRasterQueryProcessor<i8>),
287
    I16(BoxRasterQueryProcessor<i16>),
288
    I32(BoxRasterQueryProcessor<i32>),
289
    I64(BoxRasterQueryProcessor<i64>),
290
    F32(BoxRasterQueryProcessor<f32>),
291
    F64(BoxRasterQueryProcessor<f64>),
292
}
293

294
impl DynamicRasterDataType for TypedRasterQueryProcessor {
295
    fn raster_data_type(&self) -> geoengine_datatypes::raster::RasterDataType {
25✔
296
        match self {
25✔
297
            Self::U8(_) => geoengine_datatypes::raster::RasterDataType::U8,
10✔
298
            Self::U16(_) => geoengine_datatypes::raster::RasterDataType::U16,
×
299
            Self::U32(_) => geoengine_datatypes::raster::RasterDataType::U32,
×
300
            Self::U64(_) => geoengine_datatypes::raster::RasterDataType::U64,
×
301
            Self::I8(_) => geoengine_datatypes::raster::RasterDataType::I8,
11✔
302
            Self::I16(_) => geoengine_datatypes::raster::RasterDataType::I16,
1✔
303
            Self::I32(_) => geoengine_datatypes::raster::RasterDataType::I32,
×
304
            Self::I64(_) => geoengine_datatypes::raster::RasterDataType::I64,
×
305
            Self::F32(_) => geoengine_datatypes::raster::RasterDataType::F32,
3✔
306
            Self::F64(_) => geoengine_datatypes::raster::RasterDataType::F64,
×
307
        }
308
    }
25✔
309
}
310

311
impl std::fmt::Debug for TypedRasterQueryProcessor {
312
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
313
        let interals = "RasterQueryProcessor"; // TODO: implement debug for children
×
314
        match self {
×
315
            Self::U8(_) => f.debug_tuple("U8").field(&interals).finish(),
×
316
            Self::U16(_) => f.debug_tuple("U16").field(&interals).finish(),
×
317
            Self::U32(_) => f.debug_tuple("U32").field(&interals).finish(),
×
318
            Self::U64(_) => f.debug_tuple("U64").field(&interals).finish(),
×
319
            Self::I8(_) => f.debug_tuple("I8").field(&interals).finish(),
×
320
            Self::I16(_) => f.debug_tuple("I16").field(&interals).finish(),
×
321
            Self::I32(_) => f.debug_tuple("I32").field(&interals).finish(),
×
322
            Self::I64(_) => f.debug_tuple("I64").field(&interals).finish(),
×
323
            Self::F32(_) => f.debug_tuple("F32").field(&interals).finish(),
×
324
            Self::F64(_) => f.debug_tuple("F64").field(&interals).finish(),
×
325
        }
326
    }
×
327
}
328

329
impl TypedRasterQueryProcessor {
330
    pub fn get_u8(self) -> Option<BoxRasterQueryProcessor<u8>> {
110✔
331
        match self {
110✔
332
            Self::U8(r) => Some(r),
110✔
333
            _ => None,
×
334
        }
335
    }
110✔
336
    pub fn get_u16(self) -> Option<BoxRasterQueryProcessor<u16>> {
3✔
337
        match self {
3✔
338
            Self::U16(r) => Some(r),
3✔
339
            _ => None,
×
340
        }
341
    }
3✔
NEW
342
    pub fn get_u32(self) -> Option<BoxRasterQueryProcessor<u32>> {
×
343
        match self {
×
344
            Self::U32(r) => Some(r),
×
345
            _ => None,
×
346
        }
347
    }
×
NEW
348
    pub fn get_u64(self) -> Option<BoxRasterQueryProcessor<u64>> {
×
349
        match self {
×
350
            Self::U64(r) => Some(r),
×
351
            _ => None,
×
352
        }
353
    }
×
354
    pub fn get_i8(self) -> Option<BoxRasterQueryProcessor<i8>> {
44✔
355
        match self {
44✔
356
            Self::I8(r) => Some(r),
44✔
357
            _ => None,
×
358
        }
359
    }
44✔
360
    pub fn get_i16(self) -> Option<BoxRasterQueryProcessor<i16>> {
2✔
361
        match self {
2✔
362
            Self::I16(r) => Some(r),
2✔
363
            _ => None,
×
364
        }
365
    }
2✔
NEW
366
    pub fn get_i32(self) -> Option<BoxRasterQueryProcessor<i32>> {
×
367
        match self {
×
368
            Self::I32(r) => Some(r),
×
369
            _ => None,
×
370
        }
371
    }
×
372
    pub fn get_i64(self) -> Option<BoxRasterQueryProcessor<i64>> {
1✔
373
        match self {
1✔
374
            Self::I64(r) => Some(r),
1✔
375
            _ => None,
×
376
        }
377
    }
1✔
378
    pub fn get_f32(self) -> Option<BoxRasterQueryProcessor<f32>> {
34✔
379
        match self {
34✔
380
            Self::F32(r) => Some(r),
34✔
381
            _ => None,
×
382
        }
383
    }
34✔
384
    pub fn get_f64(self) -> Option<BoxRasterQueryProcessor<f64>> {
7✔
385
        match self {
7✔
386
            Self::F64(r) => Some(r),
7✔
387
            _ => None,
×
388
        }
389
    }
7✔
390

391
    pub fn into_u8(self) -> BoxRasterQueryProcessor<u8> {
×
392
        match self {
×
393
            Self::U8(r) => r,
×
394
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
395
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
396
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
397
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
398
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
399
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
400
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
401
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
402
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
403
        }
404
    }
×
405

406
    pub fn into_u16(self) -> BoxRasterQueryProcessor<u16> {
1✔
407
        match self {
1✔
408
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
409
            Self::U16(r) => r,
×
410
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
411
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
412
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
413
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
414
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
415
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
416
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
417
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
418
        }
419
    }
1✔
420

421
    pub fn into_u32(self) -> BoxRasterQueryProcessor<u32> {
×
422
        match self {
×
423
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
424
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
425
            Self::U32(r) => r,
×
426
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
427
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
428
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
429
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
430
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
431
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
432
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
433
        }
434
    }
×
435

436
    pub fn into_u64(self) -> BoxRasterQueryProcessor<u64> {
×
437
        match self {
×
438
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
439
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
440
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
441
            Self::U64(r) => r,
×
442
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
443
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
444
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
445
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
446
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
447
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
448
        }
449
    }
×
450

451
    pub fn into_f32(self) -> BoxRasterQueryProcessor<f32> {
×
452
        match self {
×
453
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
454
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
455
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
456
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
457
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
458
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
459
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
460
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
461
            Self::F32(r) => r,
×
462
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
463
        }
464
    }
×
465

466
    pub fn into_i8(self) -> BoxRasterQueryProcessor<i8> {
×
467
        match self {
×
468
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
469
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
470
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
471
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
472
            Self::I8(r) => r,
×
473
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
474
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
475
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
476
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
477
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
478
        }
479
    }
×
480

481
    pub fn into_i16(self) -> BoxRasterQueryProcessor<i16> {
×
482
        match self {
×
483
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
484
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
485
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
486
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
487
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
488
            Self::I16(r) => r,
×
489
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
490
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
491
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
492
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
493
        }
494
    }
×
495

496
    pub fn into_i32(self) -> BoxRasterQueryProcessor<i32> {
×
497
        match self {
×
498
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
499
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
500
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
501
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
502
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
503
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
504
            Self::I32(r) => r,
×
505
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
506
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
507
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
508
        }
509
    }
×
510

511
    pub fn into_i64(self) -> BoxRasterQueryProcessor<i64> {
×
512
        match self {
×
513
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
514
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
515
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
516
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
517
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
518
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
519
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
520
            Self::I64(r) => r,
×
521
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
522
            Self::F64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
523
        }
524
    }
×
525

526
    pub fn into_f64(self) -> BoxRasterQueryProcessor<f64> {
19✔
527
        match self {
19✔
528
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
7✔
529
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
530
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
531
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
532
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
11✔
533
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
534
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
535
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
536
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
537
            Self::F64(r) => r,
×
538
        }
539
    }
19✔
540

541
    pub fn result_descriptor(&self) -> &RasterResultDescriptor {
33✔
542
        match self {
33✔
543
            Self::U8(r) => r.raster_result_descriptor(),
7✔
544
            Self::U16(r) => r.raster_result_descriptor(),
×
545
            Self::U32(r) => r.raster_result_descriptor(),
×
546
            Self::U64(r) => r.raster_result_descriptor(),
×
547
            Self::I8(r) => r.raster_result_descriptor(),
×
548
            Self::I16(r) => r.raster_result_descriptor(),
×
549
            Self::I32(r) => r.raster_result_descriptor(),
26✔
550
            Self::I64(r) => r.raster_result_descriptor(),
×
551
            Self::F32(r) => r.raster_result_descriptor(),
×
552
            Self::F64(r) => r.raster_result_descriptor(),
×
553
        }
554
    }
33✔
555
}
556

557
impl From<BoxRasterQueryProcessor<u8>> for TypedRasterQueryProcessor {
558
    fn from(value: BoxRasterQueryProcessor<u8>) -> Self {
136✔
559
        TypedRasterQueryProcessor::U8(value)
136✔
560
    }
136✔
561
}
562

563
impl From<BoxRasterQueryProcessor<i8>> for TypedRasterQueryProcessor {
564
    fn from(value: BoxRasterQueryProcessor<i8>) -> Self {
39✔
565
        TypedRasterQueryProcessor::I8(value)
39✔
566
    }
39✔
567
}
568

569
impl From<BoxRasterQueryProcessor<u16>> for TypedRasterQueryProcessor {
570
    fn from(value: BoxRasterQueryProcessor<u16>) -> Self {
3✔
571
        TypedRasterQueryProcessor::U16(value)
3✔
572
    }
3✔
573
}
574

575
impl From<BoxRasterQueryProcessor<i16>> for TypedRasterQueryProcessor {
576
    fn from(value: BoxRasterQueryProcessor<i16>) -> Self {
1✔
577
        TypedRasterQueryProcessor::I16(value)
1✔
578
    }
1✔
579
}
580

581
impl From<BoxRasterQueryProcessor<u32>> for TypedRasterQueryProcessor {
NEW
582
    fn from(value: BoxRasterQueryProcessor<u32>) -> Self {
×
583
        TypedRasterQueryProcessor::U32(value)
×
584
    }
×
585
}
586

587
impl From<BoxRasterQueryProcessor<i32>> for TypedRasterQueryProcessor {
588
    fn from(value: BoxRasterQueryProcessor<i32>) -> Self {
25✔
589
        TypedRasterQueryProcessor::I32(value)
25✔
590
    }
25✔
591
}
592

593
impl From<BoxRasterQueryProcessor<u64>> for TypedRasterQueryProcessor {
NEW
594
    fn from(value: BoxRasterQueryProcessor<u64>) -> Self {
×
595
        TypedRasterQueryProcessor::U64(value)
×
596
    }
×
597
}
598
impl From<BoxRasterQueryProcessor<i64>> for TypedRasterQueryProcessor {
NEW
599
    fn from(value: BoxRasterQueryProcessor<i64>) -> Self {
×
600
        TypedRasterQueryProcessor::I64(value)
×
601
    }
×
602
}
603
impl From<BoxRasterQueryProcessor<f32>> for TypedRasterQueryProcessor {
604
    fn from(value: BoxRasterQueryProcessor<f32>) -> Self {
17✔
605
        TypedRasterQueryProcessor::F32(value)
17✔
606
    }
17✔
607
}
608
impl From<BoxRasterQueryProcessor<f64>> for TypedRasterQueryProcessor {
NEW
609
    fn from(value: BoxRasterQueryProcessor<f64>) -> Self {
×
610
        TypedRasterQueryProcessor::F64(value)
×
611
    }
×
612
}
613

614
/// An enum that contains all possible query processor variants
615
pub enum TypedVectorQueryProcessor {
616
    Data(Box<dyn VectorQueryProcessor<VectorType = DataCollection>>),
617
    MultiPoint(Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>),
618
    MultiLineString(Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>),
619
    MultiPolygon(Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>),
620
}
621

622
impl TypedVectorQueryProcessor {
623
    pub fn data(self) -> Option<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>> {
5✔
624
        if let TypedVectorQueryProcessor::Data(p) = self {
5✔
625
            Some(p)
5✔
626
        } else {
627
            None
×
628
        }
629
    }
5✔
630

631
    pub fn multi_point(
54✔
632
        self,
54✔
633
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>> {
54✔
634
        if let TypedVectorQueryProcessor::MultiPoint(p) = self {
54✔
635
            Some(p)
54✔
636
        } else {
637
            None
×
638
        }
639
    }
54✔
640

641
    pub fn multi_line_string(
2✔
642
        self,
2✔
643
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>> {
2✔
644
        if let TypedVectorQueryProcessor::MultiLineString(p) = self {
2✔
645
            Some(p)
2✔
646
        } else {
647
            None
×
648
        }
649
    }
2✔
650

651
    pub fn multi_polygon(
11✔
652
        self,
11✔
653
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>> {
11✔
654
        if let TypedVectorQueryProcessor::MultiPolygon(p) = self {
11✔
655
            Some(p)
11✔
656
        } else {
657
            None
×
658
        }
659
    }
11✔
660
}
661

662
impl TypedVectorQueryProcessor {
663
    fn type_str(&self) -> &str {
×
664
        match self {
×
665
            TypedVectorQueryProcessor::Data(_) => "Data",
×
666
            TypedVectorQueryProcessor::MultiPoint(_) => "MultiPoint",
×
667
            TypedVectorQueryProcessor::MultiLineString(_) => "MultiLineString",
×
668
            TypedVectorQueryProcessor::MultiPolygon(_) => "MultiPolygon",
×
669
        }
670
    }
×
671
}
672

673
impl TryFrom<TypedVectorQueryProcessor>
674
    for Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>
675
{
676
    type Error = crate::error::Error;
677

678
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
2✔
679
        if let TypedVectorQueryProcessor::MultiPoint(p) = value {
2✔
680
            Ok(p)
2✔
681
        } else {
682
            Err(crate::error::Error::InvalidVectorType {
×
683
                expected: "MultiPointCollection".to_string(),
×
684
                found: value.type_str().to_string(),
×
685
            })
×
686
        }
687
    }
2✔
688
}
689

690
impl TryFrom<TypedVectorQueryProcessor>
691
    for Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>
692
{
693
    type Error = crate::error::Error;
694

695
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
×
696
        if let TypedVectorQueryProcessor::MultiLineString(p) = value {
×
697
            Ok(p)
×
698
        } else {
699
            Err(crate::error::Error::InvalidVectorType {
×
700
                expected: "MultiLineStringCollection".to_string(),
×
701
                found: value.type_str().to_string(),
×
702
            })
×
703
        }
704
    }
×
705
}
706

707
impl TryFrom<TypedVectorQueryProcessor>
708
    for Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>
709
{
710
    type Error = crate::error::Error;
711

712
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
1✔
713
        if let TypedVectorQueryProcessor::MultiPolygon(p) = value {
1✔
714
            Ok(p)
1✔
715
        } else {
716
            Err(crate::error::Error::InvalidVectorType {
×
717
                expected: "MultiPolygonCollection".to_string(),
×
718
                found: value.type_str().to_string(),
×
719
            })
×
720
        }
721
    }
1✔
722
}
723

724
impl TryFrom<TypedVectorQueryProcessor>
725
    for Box<dyn VectorQueryProcessor<VectorType = DataCollection>>
726
{
727
    type Error = crate::error::Error;
728

729
    fn try_from(value: TypedVectorQueryProcessor) -> Result<Self, Self::Error> {
×
730
        if let TypedVectorQueryProcessor::Data(p) = value {
×
731
            Ok(p)
×
732
        } else {
733
            Err(crate::error::Error::InvalidVectorType {
×
734
                expected: "DataCollection".to_string(),
×
735
                found: value.type_str().to_string(),
×
736
            })
×
737
        }
738
    }
×
739
}
740

741
impl From<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>>
742
    for TypedVectorQueryProcessor
743
{
744
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = DataCollection>>) -> Self {
×
745
        TypedVectorQueryProcessor::Data(value)
×
746
    }
×
747
}
748

749
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>>
750
    for TypedVectorQueryProcessor
751
{
752
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>) -> Self {
8✔
753
        TypedVectorQueryProcessor::MultiPoint(value)
8✔
754
    }
8✔
755
}
756

757
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>>
758
    for TypedVectorQueryProcessor
759
{
760
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>) -> Self {
×
761
        TypedVectorQueryProcessor::MultiLineString(value)
×
762
    }
×
763
}
764

765
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>>
766
    for TypedVectorQueryProcessor
767
{
768
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>) -> Self {
1✔
769
        TypedVectorQueryProcessor::MultiPolygon(value)
1✔
770
    }
1✔
771
}
772

773
/// An enum that contains all possible query processor variants
774
pub enum TypedPlotQueryProcessor {
775
    JsonPlain(Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>),
776
    JsonVega(Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>),
777
    ImagePng(Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>),
778
}
779

780
impl From<&TypedPlotQueryProcessor> for PlotOutputFormat {
781
    fn from(typed_processor: &TypedPlotQueryProcessor) -> Self {
2✔
782
        match typed_processor {
2✔
783
            TypedPlotQueryProcessor::JsonPlain(_) => PlotOutputFormat::JsonPlain,
1✔
784
            TypedPlotQueryProcessor::JsonVega(_) => PlotOutputFormat::JsonVega,
1✔
785
            TypedPlotQueryProcessor::ImagePng(_) => PlotOutputFormat::ImagePng,
×
786
        }
787
    }
2✔
788
}
789

790
impl TypedPlotQueryProcessor {
791
    pub fn plot_type(&self) -> &'static str {
2✔
792
        match self {
2✔
793
            TypedPlotQueryProcessor::JsonPlain(p) => p.plot_type(),
1✔
794
            TypedPlotQueryProcessor::JsonVega(p) => p.plot_type(),
1✔
795
            TypedPlotQueryProcessor::ImagePng(p) => p.plot_type(),
×
796
        }
797
    }
2✔
798

799
    pub fn json_plain(
9✔
800
        self,
9✔
801
    ) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>> {
9✔
802
        if let TypedPlotQueryProcessor::JsonPlain(p) = self {
9✔
803
            Some(p)
9✔
804
        } else {
805
            None
×
806
        }
807
    }
9✔
808

809
    pub fn json_vega(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>> {
44✔
810
        if let TypedPlotQueryProcessor::JsonVega(p) = self {
44✔
811
            Some(p)
44✔
812
        } else {
813
            None
×
814
        }
815
    }
44✔
816

817
    pub fn image_png(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>> {
×
818
        if let TypedPlotQueryProcessor::ImagePng(p) = self {
×
819
            Some(p)
×
820
        } else {
821
            None
×
822
        }
823
    }
×
824
}
825

826
/// Maps a `TypedVectorQueryProcessor` to another `TypedVectorQueryProcessor` by calling a function on its variant.
827
/// Call via `map_typed_query_processor!(input, processor => function)`.
828
#[macro_export]
829
macro_rules! map_typed_query_processor {
830
    ($input:expr, $processor:ident => $function_call:expr) => {
831
        map_typed_query_processor!(
832
            @variants $input, $processor => $function_call,
833
            Data, MultiPoint, MultiLineString, MultiPolygon
834
        )
835
    };
836

837
    (@variants $input:expr, $processor:ident => $function_call:expr, $($variant:tt),+) => {
838
        match $input {
839
            $(
840
                $crate::engine::TypedVectorQueryProcessor::$variant($processor) => {
841
                    $crate::engine::TypedVectorQueryProcessor::$variant($function_call)
842
                }
843
            )+
844
        }
845
    };
846
}
847

848
/// In the case that it is required to store a query stream in a struct with a static lifetime,
849
///  one can use this struct.
850
/// This struct owns the query processor and the query context and thus ensures that the query
851
/// has the lifetime dependencies it needs.
852
#[self_referencing]
853
pub struct OwnedQueryResultStream<Q>
854
where
855
    Q: QueryProcessor + 'static,
856
{
857
    processor: Q,
858
    ctx: Box<dyn QueryContext>,
859
    #[borrows(processor, ctx)]
860
    #[covariant]
861
    stream: BoxStream<'this, Result<Q::Output>>,
862
}
863

864
impl<Q> OwnedQueryResultStream<Q>
865
where
866
    Q: QueryProcessor + 'static,
867
{
868
    /// Stop/drop the current stream and return the query processor.
869
    pub fn into_query_processor(self) -> Q {
×
870
        self.into_heads().processor
×
871
    }
×
872
}
873

874
impl<Q> Stream for OwnedQueryResultStream<Q>
875
where
876
    Q: QueryProcessor + 'static,
877
{
878
    type Item = Result<Q::Output>;
879

880
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
9✔
881
        self.with_stream_mut(|stream| Pin::new(stream).poll_next(cx))
9✔
882
    }
9✔
883
}
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