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

geo-engine / geoengine / 7006568925

27 Nov 2023 02:07PM UTC coverage: 89.651% (+0.2%) from 89.498%
7006568925

push

github

web-flow
Merge pull request #888 from geo-engine/raster_stacks

raster stacking

4032 of 4274 new or added lines in 107 files covered. (94.34%)

12 existing lines in 8 files now uncovered.

113020 of 126066 relevant lines covered (89.65%)

59901.79 hits per line

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

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

4
use super::query::QueryContext;
5
use crate::processing::RasterTypeConversionQueryProcessor;
6
use crate::util::Result;
7
use async_trait::async_trait;
8
use futures::stream::BoxStream;
9
use futures::Stream;
10
use geoengine_datatypes::collections::{
11
    DataCollection, MultiLineStringCollection, MultiPolygonCollection,
12
};
13
use geoengine_datatypes::plots::{PlotData, PlotOutputFormat};
14
use geoengine_datatypes::primitives::{
15
    AxisAlignedRectangle, BandSelection, BoundingBox2D, ColumnSelection, PlotQueryRectangle,
16
    QueryAttributeSelection, QueryRectangle, RasterQueryRectangle, SpatialPartition2D,
17
    VectorQueryRectangle,
18
};
19
use geoengine_datatypes::raster::{DynamicRasterDataType, 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: AxisAlignedRectangle + Send + Sync;
28
    type Selection: QueryAttributeSelection;
29

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

37
    async fn query<'a>(
1,069✔
38
        &'a self,
1,069✔
39
        query: QueryRectangle<Self::SpatialBounds, Self::Selection>, // TODO: query by reference
1,069✔
40
        ctx: &'a dyn QueryContext,
1,069✔
41
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
1,069✔
42
        Ok(Box::pin(
43
            ctx.abort_registration()
1,069✔
44
                .wrap(self._query(query, ctx).await?),
1,069✔
45
        ))
46
    }
2,138✔
47
}
48

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

73
impl<Q> QueryProcessorExt for Q where Q: QueryProcessor {}
74

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

80
    async fn raster_query<'a>(
81
        &'a self,
82
        query: RasterQueryRectangle, // TODO: query by reference
83
        ctx: &'a dyn QueryContext,
84
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>>;
85

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

94
pub type BoxRasterQueryProcessor<P> = Box<dyn RasterQueryProcessor<RasterType = P>>;
95

96
#[async_trait]
97
impl<S, T> RasterQueryProcessor for S
98
where
99
    S: QueryProcessor<
100
            Output = RasterTile2D<T>,
101
            SpatialBounds = SpatialPartition2D,
102
            Selection = BandSelection,
103
        > + Sync
104
        + Send,
105
    T: Pixel,
106
{
107
    type RasterType = T;
108
    async fn raster_query<'a>(
637✔
109
        &'a self,
637✔
110
        query: RasterQueryRectangle, // TODO: query by reference
637✔
111
        ctx: &'a dyn QueryContext,
637✔
112
    ) -> Result<BoxStream<'a, Result<RasterTile2D<Self::RasterType>>>> {
637✔
113
        self.query(query, ctx).await
637✔
114
    }
1,274✔
115
}
116

117
/// An instantiation of a vector operator that produces a stream of vector results for a query
118
#[async_trait]
119
pub trait VectorQueryProcessor: Sync + Send {
120
    type VectorType;
121
    async fn vector_query<'a>(
122
        &'a self,
123
        query: VectorQueryRectangle, // TODO: query by reference
124
        ctx: &'a dyn QueryContext,
125
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>>;
126

127
    fn boxed(self) -> Box<dyn VectorQueryProcessor<VectorType = Self::VectorType>>
146✔
128
    where
146✔
129
        Self: Sized + 'static,
146✔
130
    {
146✔
131
        Box::new(self)
146✔
132
    }
146✔
133
}
134

135
#[async_trait]
136
impl<S, VD> VectorQueryProcessor for S
137
where
138
    S: QueryProcessor<Output = VD, SpatialBounds = BoundingBox2D, Selection = ColumnSelection>
139
        + Sync
140
        + Send,
141
{
142
    type VectorType = VD;
143

144
    async fn vector_query<'a>(
60✔
145
        &'a self,
60✔
146
        query: VectorQueryRectangle, // TODO: query by reference
60✔
147
        ctx: &'a dyn QueryContext,
60✔
148
    ) -> Result<BoxStream<'a, Result<Self::VectorType>>> {
60✔
149
        self.query(query, ctx).await
60✔
150
    }
120✔
151
}
152

153
/// An instantiation of a plot operator that produces a stream of vector results for a query
154
#[async_trait]
155
pub trait PlotQueryProcessor: Sync + Send {
156
    type OutputFormat;
157

158
    fn plot_type(&self) -> &'static str;
159

160
    async fn plot_query<'a>(
161
        &'a self,
162
        query: PlotQueryRectangle, // TODO: query by reference
163
        ctx: &'a dyn QueryContext,
164
    ) -> Result<Self::OutputFormat>;
165

166
    fn boxed(self) -> Box<dyn PlotQueryProcessor<OutputFormat = Self::OutputFormat>>
54✔
167
    where
54✔
168
        Self: Sized + 'static,
54✔
169
    {
54✔
170
        Box::new(self)
54✔
171
    }
54✔
172
}
173

174
#[async_trait]
175
impl<T, S, U> QueryProcessor
176
    for Box<dyn QueryProcessor<Output = T, SpatialBounds = S, Selection = U>>
177
where
178
    S: AxisAlignedRectangle + Send + Sync,
179
    U: QueryAttributeSelection,
180
{
181
    type Output = T;
182
    type SpatialBounds = S;
183
    type Selection = U;
184

185
    async fn _query<'a>(
×
186
        &'a self,
×
NEW
187
        query: QueryRectangle<S, U>, // TODO: query by reference
×
188
        ctx: &'a dyn QueryContext,
×
189
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
×
190
        self.as_ref().query(query, ctx).await
×
191
    }
×
192
}
193

194
#[async_trait]
195
impl<T> QueryProcessor for Box<dyn RasterQueryProcessor<RasterType = T>>
196
where
197
    T: Pixel,
198
{
199
    type Output = RasterTile2D<T>;
200
    type SpatialBounds = SpatialPartition2D;
201
    type Selection = BandSelection;
202

203
    async fn _query<'a>(
553✔
204
        &'a self,
553✔
205
        query: RasterQueryRectangle, // TODO: query by reference
553✔
206
        ctx: &'a dyn QueryContext,
553✔
207
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
553✔
208
        self.as_ref().raster_query(query, ctx).await
553✔
209
    }
1,106✔
210
}
211

212
#[async_trait]
213
impl<V> QueryProcessor for Box<dyn VectorQueryProcessor<VectorType = V>>
214
where
215
    V: 'static,
216
{
217
    type Output = V;
218
    type SpatialBounds = BoundingBox2D;
219
    type Selection = ColumnSelection;
220

221
    async fn _query<'a>(
174✔
222
        &'a self,
174✔
223
        query: VectorQueryRectangle, // TODO: query by reference
174✔
224
        ctx: &'a dyn QueryContext,
174✔
225
    ) -> Result<BoxStream<'a, Result<Self::Output>>> {
174✔
226
        self.as_ref().vector_query(query, ctx).await
174✔
227
    }
348✔
228
}
229

230
/// An enum to differentiate between outputs of raster processors
231
pub enum TypedRasterQueryProcessor {
232
    U8(Box<dyn RasterQueryProcessor<RasterType = u8>>),
233
    U16(Box<dyn RasterQueryProcessor<RasterType = u16>>),
234
    U32(Box<dyn RasterQueryProcessor<RasterType = u32>>),
235
    U64(Box<dyn RasterQueryProcessor<RasterType = u64>>),
236
    I8(Box<dyn RasterQueryProcessor<RasterType = i8>>),
237
    I16(Box<dyn RasterQueryProcessor<RasterType = i16>>),
238
    I32(Box<dyn RasterQueryProcessor<RasterType = i32>>),
239
    I64(Box<dyn RasterQueryProcessor<RasterType = i64>>),
240
    F32(Box<dyn RasterQueryProcessor<RasterType = f32>>),
241
    F64(Box<dyn RasterQueryProcessor<RasterType = f64>>),
242
}
243

244
impl DynamicRasterDataType for TypedRasterQueryProcessor {
245
    fn raster_data_type(&self) -> geoengine_datatypes::raster::RasterDataType {
4✔
246
        match self {
4✔
247
            Self::U8(_) => geoengine_datatypes::raster::RasterDataType::U8,
4✔
248
            Self::U16(_) => geoengine_datatypes::raster::RasterDataType::U16,
×
249
            Self::U32(_) => geoengine_datatypes::raster::RasterDataType::U32,
×
250
            Self::U64(_) => geoengine_datatypes::raster::RasterDataType::U64,
×
251
            Self::I8(_) => geoengine_datatypes::raster::RasterDataType::I8,
×
252
            Self::I16(_) => geoengine_datatypes::raster::RasterDataType::I16,
×
253
            Self::I32(_) => geoengine_datatypes::raster::RasterDataType::I32,
×
254
            Self::I64(_) => geoengine_datatypes::raster::RasterDataType::I64,
×
255
            Self::F32(_) => geoengine_datatypes::raster::RasterDataType::F32,
×
256
            Self::F64(_) => geoengine_datatypes::raster::RasterDataType::F64,
×
257
        }
258
    }
4✔
259
}
260

261
impl std::fmt::Debug for TypedRasterQueryProcessor {
262
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
263
        let interals = "RasterQueryProcessor"; // TODO: implement debug for children
×
264
        match self {
×
265
            Self::U8(_) => f.debug_tuple("U8").field(&interals).finish(),
×
266
            Self::U16(_) => f.debug_tuple("U16").field(&interals).finish(),
×
267
            Self::U32(_) => f.debug_tuple("U32").field(&interals).finish(),
×
268
            Self::U64(_) => f.debug_tuple("U64").field(&interals).finish(),
×
269
            Self::I8(_) => f.debug_tuple("I8").field(&interals).finish(),
×
270
            Self::I16(_) => f.debug_tuple("I16").field(&interals).finish(),
×
271
            Self::I32(_) => f.debug_tuple("I32").field(&interals).finish(),
×
272
            Self::I64(_) => f.debug_tuple("I64").field(&interals).finish(),
×
273
            Self::F32(_) => f.debug_tuple("F32").field(&interals).finish(),
×
274
            Self::F64(_) => f.debug_tuple("F64").field(&interals).finish(),
×
275
        }
276
    }
×
277
}
278

279
impl TypedRasterQueryProcessor {
280
    pub fn get_u8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u8>>> {
78✔
281
        match self {
78✔
282
            Self::U8(r) => Some(r),
78✔
283
            _ => None,
×
284
        }
285
    }
78✔
286
    pub fn get_u16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u16>>> {
3✔
287
        match self {
3✔
288
            Self::U16(r) => Some(r),
3✔
289
            _ => None,
×
290
        }
291
    }
3✔
292
    pub fn get_u32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u32>>> {
1✔
293
        match self {
1✔
294
            Self::U32(r) => Some(r),
1✔
295
            _ => None,
×
296
        }
297
    }
1✔
298
    pub fn get_u64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = u64>>> {
×
299
        match self {
×
300
            Self::U64(r) => Some(r),
×
301
            _ => None,
×
302
        }
303
    }
×
304
    pub fn get_i8(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i8>>> {
14✔
305
        match self {
14✔
306
            Self::I8(r) => Some(r),
14✔
307
            _ => None,
×
308
        }
309
    }
14✔
310
    pub fn get_i16(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i16>>> {
×
311
        match self {
×
312
            Self::I16(r) => Some(r),
×
313
            _ => None,
×
314
        }
315
    }
×
316
    pub fn get_i32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i32>>> {
×
317
        match self {
×
318
            Self::I32(r) => Some(r),
×
319
            _ => None,
×
320
        }
321
    }
×
322
    pub fn get_i64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = i64>>> {
×
323
        match self {
×
324
            Self::I64(r) => Some(r),
×
325
            _ => None,
×
326
        }
327
    }
×
328
    pub fn get_f32(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f32>>> {
28✔
329
        match self {
28✔
330
            Self::F32(r) => Some(r),
28✔
331
            _ => None,
×
332
        }
333
    }
28✔
334
    pub fn get_f64(self) -> Option<Box<dyn RasterQueryProcessor<RasterType = f64>>> {
9✔
335
        match self {
9✔
336
            Self::F64(r) => Some(r),
9✔
337
            _ => None,
×
338
        }
339
    }
9✔
340

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

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

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

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

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

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

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

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

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

476
    pub fn into_f64(self) -> BoxRasterQueryProcessor<f64> {
32✔
477
        match self {
32✔
478
            Self::U8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
4✔
479
            Self::U16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
480
            Self::U32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
481
            Self::U64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
482
            Self::I8(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
27✔
483
            Self::I16(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
1✔
484
            Self::I32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
485
            Self::I64(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
486
            Self::F32(r) => RasterTypeConversionQueryProcessor::new(r).boxed(),
×
487
            Self::F64(r) => r,
×
488
        }
489
    }
32✔
490
}
491

492
impl From<Box<dyn RasterQueryProcessor<RasterType = u8>>> for TypedRasterQueryProcessor {
493
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u8>>) -> Self {
110✔
494
        TypedRasterQueryProcessor::U8(value)
110✔
495
    }
110✔
496
}
497

498
impl From<Box<dyn RasterQueryProcessor<RasterType = i8>>> for TypedRasterQueryProcessor {
499
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i8>>) -> Self {
34✔
500
        TypedRasterQueryProcessor::I8(value)
34✔
501
    }
34✔
502
}
503

504
impl From<Box<dyn RasterQueryProcessor<RasterType = u16>>> for TypedRasterQueryProcessor {
505
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u16>>) -> Self {
3✔
506
        TypedRasterQueryProcessor::U16(value)
3✔
507
    }
3✔
508
}
509

510
impl From<Box<dyn RasterQueryProcessor<RasterType = i16>>> for TypedRasterQueryProcessor {
511
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i16>>) -> Self {
×
512
        TypedRasterQueryProcessor::I16(value)
×
513
    }
×
514
}
515

516
impl From<Box<dyn RasterQueryProcessor<RasterType = u32>>> for TypedRasterQueryProcessor {
517
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u32>>) -> Self {
1✔
518
        TypedRasterQueryProcessor::U32(value)
1✔
519
    }
1✔
520
}
521

522
impl From<Box<dyn RasterQueryProcessor<RasterType = i32>>> for TypedRasterQueryProcessor {
523
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i32>>) -> Self {
43✔
524
        TypedRasterQueryProcessor::I32(value)
43✔
525
    }
43✔
526
}
527

528
impl From<Box<dyn RasterQueryProcessor<RasterType = u64>>> for TypedRasterQueryProcessor {
529
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = u64>>) -> Self {
×
530
        TypedRasterQueryProcessor::U64(value)
×
531
    }
×
532
}
533
impl From<Box<dyn RasterQueryProcessor<RasterType = i64>>> for TypedRasterQueryProcessor {
534
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = i64>>) -> Self {
×
535
        TypedRasterQueryProcessor::I64(value)
×
536
    }
×
537
}
538
impl From<Box<dyn RasterQueryProcessor<RasterType = f32>>> for TypedRasterQueryProcessor {
539
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f32>>) -> Self {
10✔
540
        TypedRasterQueryProcessor::F32(value)
10✔
541
    }
10✔
542
}
543
impl From<Box<dyn RasterQueryProcessor<RasterType = f64>>> for TypedRasterQueryProcessor {
544
    fn from(value: Box<dyn RasterQueryProcessor<RasterType = f64>>) -> Self {
×
545
        TypedRasterQueryProcessor::F64(value)
×
546
    }
×
547
}
548

549
/// An enum that contains all possible query processor variants
550
pub enum TypedVectorQueryProcessor {
551
    Data(Box<dyn VectorQueryProcessor<VectorType = DataCollection>>),
552
    MultiPoint(Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>),
553
    MultiLineString(Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>),
554
    MultiPolygon(Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>),
555
}
556

557
impl TypedVectorQueryProcessor {
558
    pub fn data(self) -> Option<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>> {
559
        if let TypedVectorQueryProcessor::Data(p) = self {
5✔
560
            Some(p)
5✔
561
        } else {
562
            None
×
563
        }
564
    }
5✔
565

566
    pub fn multi_point(
567
        self,
568
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>> {
569
        if let TypedVectorQueryProcessor::MultiPoint(p) = self {
52✔
570
            Some(p)
52✔
571
        } else {
572
            None
×
573
        }
574
    }
52✔
575

576
    pub fn multi_line_string(
577
        self,
578
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>> {
579
        if let TypedVectorQueryProcessor::MultiLineString(p) = self {
2✔
580
            Some(p)
2✔
581
        } else {
582
            None
×
583
        }
584
    }
2✔
585

586
    pub fn multi_polygon(
587
        self,
588
    ) -> Option<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>> {
589
        if let TypedVectorQueryProcessor::MultiPolygon(p) = self {
10✔
590
            Some(p)
10✔
591
        } else {
592
            None
×
593
        }
594
    }
10✔
595
}
596

597
impl From<Box<dyn VectorQueryProcessor<VectorType = DataCollection>>>
598
    for TypedVectorQueryProcessor
599
{
600
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = DataCollection>>) -> Self {
×
601
        TypedVectorQueryProcessor::Data(value)
×
602
    }
×
603
}
604

605
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>>
606
    for TypedVectorQueryProcessor
607
{
608
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPointCollection>>) -> Self {
4✔
609
        TypedVectorQueryProcessor::MultiPoint(value)
4✔
610
    }
4✔
611
}
612

613
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>>
614
    for TypedVectorQueryProcessor
615
{
616
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiLineStringCollection>>) -> Self {
×
617
        TypedVectorQueryProcessor::MultiLineString(value)
×
618
    }
×
619
}
620

621
impl From<Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>>
622
    for TypedVectorQueryProcessor
623
{
624
    fn from(value: Box<dyn VectorQueryProcessor<VectorType = MultiPolygonCollection>>) -> Self {
×
625
        TypedVectorQueryProcessor::MultiPolygon(value)
×
626
    }
×
627
}
628

629
/// An enum that contains all possible query processor variants
630
pub enum TypedPlotQueryProcessor {
631
    JsonPlain(Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>),
632
    JsonVega(Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>),
633
    ImagePng(Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>),
634
}
635

636
impl From<&TypedPlotQueryProcessor> for PlotOutputFormat {
637
    fn from(typed_processor: &TypedPlotQueryProcessor) -> Self {
2✔
638
        match typed_processor {
2✔
639
            TypedPlotQueryProcessor::JsonPlain(_) => PlotOutputFormat::JsonPlain,
1✔
640
            TypedPlotQueryProcessor::JsonVega(_) => PlotOutputFormat::JsonVega,
1✔
641
            TypedPlotQueryProcessor::ImagePng(_) => PlotOutputFormat::ImagePng,
×
642
        }
643
    }
2✔
644
}
645

646
impl TypedPlotQueryProcessor {
647
    pub fn plot_type(&self) -> &'static str {
2✔
648
        match self {
2✔
649
            TypedPlotQueryProcessor::JsonPlain(p) => p.plot_type(),
1✔
650
            TypedPlotQueryProcessor::JsonVega(p) => p.plot_type(),
1✔
651
            TypedPlotQueryProcessor::ImagePng(p) => p.plot_type(),
×
652
        }
653
    }
2✔
654

655
    pub fn json_plain(
656
        self,
657
    ) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = serde_json::Value>>> {
658
        if let TypedPlotQueryProcessor::JsonPlain(p) = self {
7✔
659
            Some(p)
7✔
660
        } else {
661
            None
×
662
        }
663
    }
7✔
664

665
    pub fn json_vega(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = PlotData>>> {
666
        if let TypedPlotQueryProcessor::JsonVega(p) = self {
44✔
667
            Some(p)
44✔
668
        } else {
669
            None
×
670
        }
671
    }
44✔
672

673
    pub fn image_png(self) -> Option<Box<dyn PlotQueryProcessor<OutputFormat = Vec<u8>>>> {
674
        if let TypedPlotQueryProcessor::ImagePng(p) = self {
×
675
            Some(p)
×
676
        } else {
677
            None
×
678
        }
679
    }
×
680
}
681

682
/// Maps a `TypedVectorQueryProcessor` to another `TypedVectorQueryProcessor` by calling a function on its variant.
683
/// Call via `map_typed_query_processor!(input, processor => function)`.
684
#[macro_export]
685
macro_rules! map_typed_query_processor {
686
    ($input:expr, $processor:ident => $function_call:expr) => {
687
        map_typed_query_processor!(
688
            @variants $input, $processor => $function_call,
689
            Data, MultiPoint, MultiLineString, MultiPolygon
690
        )
691
    };
692

693
    (@variants $input:expr, $processor:ident => $function_call:expr, $($variant:tt),+) => {
694
        match $input {
695
            $(
696
                $crate::engine::TypedVectorQueryProcessor::$variant($processor) => {
697
                    $crate::engine::TypedVectorQueryProcessor::$variant($function_call)
698
                }
699
            )+
700
        }
701
    };
702
}
703

704
/// In the case that it is required to store a query stream in a struct with a static lifetime,
705
///  one can use this struct.
706
/// This struct owns the query processor and the query context and thus ensures that the query
707
/// has the lifetime dependencies it needs.
708
#[self_referencing]
8✔
709
pub struct OwnedQueryResultStream<Q>
710
where
711
    Q: QueryProcessor + 'static,
712
{
713
    processor: Q,
714
    ctx: Box<dyn QueryContext>,
715
    #[borrows(processor, ctx)]
716
    #[covariant]
717
    stream: BoxStream<'this, Result<Q::Output>>,
718
}
719

720
impl<Q> OwnedQueryResultStream<Q>
721
where
722
    Q: QueryProcessor + 'static,
723
{
724
    /// Stop/drop the current stream and return the query processor.
725
    pub fn into_query_processor(self) -> Q {
×
726
        self.into_heads().processor
×
727
    }
×
728
}
729

730
impl<Q> Stream for OwnedQueryResultStream<Q>
731
where
732
    Q: QueryProcessor + 'static,
733
{
734
    type Item = Result<Q::Output>;
735

736
    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
12✔
737
        self.with_stream_mut(|stream| Pin::new(stream).poll_next(cx))
12✔
738
    }
12✔
739
}
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