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

geo-engine / geoengine / 3929938005

pending completion
3929938005

push

github

GitHub
Merge #713

84930 of 96741 relevant lines covered (87.79%)

79640.1 hits per line

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

44.04
/services/src/api/model/operators.rs
1
use crate::api::model::datatypes::{
2
    Coordinate2D, DateTimeParseFormat, MultiLineString, MultiPoint, MultiPolygon, NoGeometry,
3
    QueryRectangle, RasterPropertiesEntryType, RasterPropertiesKey, SpatialResolution,
4
    TimeInstance, TimeStep, VectorQueryRectangle,
5
};
6
use async_trait::async_trait;
7
use geoengine_operators::engine::{MetaData, ResultDescriptor};
8
use serde::{Deserialize, Serialize};
9
use std::collections::HashMap;
10
use std::fmt::Debug;
11
use std::marker::PhantomData;
12
use std::path::PathBuf;
13
use utoipa::ToSchema;
14

15
use super::datatypes::{
16
    BoundingBox2D, FeatureDataType, Measurement, RasterDataType, SpatialPartition2D,
17
    SpatialReferenceOption, TimeInterval, VectorDataType,
18
};
19

20
/// A `ResultDescriptor` for raster queries
21
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
26✔
22
#[serde(rename_all = "camelCase")]
23
pub struct RasterResultDescriptor {
24
    pub data_type: RasterDataType,
25
    pub spatial_reference: SpatialReferenceOption,
26
    pub measurement: Measurement,
27
    pub time: Option<TimeInterval>,
28
    pub bbox: Option<SpatialPartition2D>,
29
    pub resolution: Option<SpatialResolution>,
30
}
31

32
impl From<geoengine_operators::engine::RasterResultDescriptor> for RasterResultDescriptor {
33
    fn from(value: geoengine_operators::engine::RasterResultDescriptor) -> Self {
50✔
34
        Self {
50✔
35
            data_type: value.data_type.into(),
50✔
36
            spatial_reference: value.spatial_reference.into(),
50✔
37
            measurement: value.measurement.into(),
50✔
38
            time: value.time.map(Into::into),
50✔
39
            bbox: value.bbox.map(Into::into),
50✔
40
            resolution: value.resolution.map(Into::into),
50✔
41
        }
50✔
42
    }
50✔
43
}
44

45
impl From<RasterResultDescriptor> for geoengine_operators::engine::RasterResultDescriptor {
46
    fn from(value: RasterResultDescriptor) -> Self {
3✔
47
        Self {
3✔
48
            data_type: value.data_type.into(),
3✔
49
            spatial_reference: value.spatial_reference.into(),
3✔
50
            measurement: value.measurement.into(),
3✔
51
            time: value.time.map(Into::into),
3✔
52
            bbox: value.bbox.map(Into::into),
3✔
53
            resolution: value.resolution.map(Into::into),
3✔
54
        }
3✔
55
    }
3✔
56
}
57

58
/// An enum to differentiate between `Operator` variants
59
#[derive(Clone, Debug, Serialize, Deserialize)]
×
60
#[serde(tag = "type", content = "operator")]
61
pub enum TypedOperator {
62
    Vector(Box<dyn geoengine_operators::engine::VectorOperator>),
63
    Raster(Box<dyn geoengine_operators::engine::RasterOperator>),
64
    Plot(Box<dyn geoengine_operators::engine::PlotOperator>),
65
}
66

67
impl ToSchema for TypedOperator {
68
    fn schema() -> utoipa::openapi::Schema {
×
69
        use utoipa::openapi::*;
×
70
        ObjectBuilder::new()
×
71
            .property(
×
72
                "type",
×
73
                ObjectBuilder::new()
×
74
                    .schema_type(SchemaType::String)
×
75
                    .enum_values(Some(vec!["Vector", "Raster", "Plot"]))
×
76
            )
×
77
            .required("type")
×
78
            .property(
×
79
                "operator",
×
80
                ObjectBuilder::new()
×
81
                    .property(
×
82
                        "type",
×
83
                        Object::with_type(SchemaType::String)
×
84
                    )
×
85
                    .required("type")
×
86
                    .property(
×
87
                        "params",
×
88
                        Object::with_type(SchemaType::Object)
×
89
                    )
×
90
                    .property(
×
91
                        "sources",
×
92
                        Object::with_type(SchemaType::Object)
×
93
                    )
×
94
            )
×
95
            .required("operator")
×
96
            .example(Some(serde_json::json!(
×
97
                {"type": "MockPointSource", "params": {"points": [{"x": 0.0, "y": 0.1}, {"x": 1.0, "y": 1.1}]}
×
98
            })))
×
99
            .description(Some("An enum to differentiate between `Operator` variants"))
×
100
            .into()
×
101
    }
×
102
}
103

104
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
80✔
105
#[serde(rename_all = "camelCase")]
106
pub struct VectorResultDescriptor {
107
    pub data_type: VectorDataType,
108
    pub spatial_reference: SpatialReferenceOption,
109
    pub columns: HashMap<String, VectorColumnInfo>,
110
    pub time: Option<TimeInterval>,
111
    pub bbox: Option<BoundingBox2D>,
112
}
113

114
impl From<geoengine_operators::engine::VectorResultDescriptor> for VectorResultDescriptor {
115
    fn from(value: geoengine_operators::engine::VectorResultDescriptor) -> Self {
17✔
116
        Self {
17✔
117
            data_type: value.data_type.into(),
17✔
118
            spatial_reference: value.spatial_reference.into(),
17✔
119
            columns: value
17✔
120
                .columns
17✔
121
                .into_iter()
17✔
122
                .map(|(key, value)| (key, value.into()))
17✔
123
                .collect(),
17✔
124
            time: value.time.map(Into::into),
17✔
125
            bbox: value.bbox.map(Into::into),
17✔
126
        }
17✔
127
    }
17✔
128
}
129

130
impl From<VectorResultDescriptor> for geoengine_operators::engine::VectorResultDescriptor {
131
    fn from(value: VectorResultDescriptor) -> Self {
2✔
132
        Self {
2✔
133
            data_type: value.data_type.into(),
2✔
134
            spatial_reference: value.spatial_reference.into(),
2✔
135
            columns: value
2✔
136
                .columns
2✔
137
                .into_iter()
2✔
138
                .map(|(key, value)| (key, value.into()))
10✔
139
                .collect(),
2✔
140
            time: value.time.map(Into::into),
2✔
141
            bbox: value.bbox.map(Into::into),
2✔
142
        }
2✔
143
    }
2✔
144
}
145

146
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
55✔
147
#[serde(rename_all = "camelCase")]
148
pub struct VectorColumnInfo {
149
    pub data_type: FeatureDataType,
150
    pub measurement: Measurement,
151
}
152

153
impl From<geoengine_operators::engine::VectorColumnInfo> for VectorColumnInfo {
154
    fn from(value: geoengine_operators::engine::VectorColumnInfo) -> Self {
13✔
155
        Self {
13✔
156
            data_type: value.data_type.into(),
13✔
157
            measurement: value.measurement.into(),
13✔
158
        }
13✔
159
    }
13✔
160
}
161

162
impl From<VectorColumnInfo> for geoengine_operators::engine::VectorColumnInfo {
163
    fn from(value: VectorColumnInfo) -> Self {
10✔
164
        Self {
10✔
165
            data_type: value.data_type.into(),
10✔
166
            measurement: value.measurement.into(),
10✔
167
        }
10✔
168
    }
10✔
169
}
170

171
/// A `ResultDescriptor` for plot queries
172
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
×
173
#[serde(rename_all = "camelCase")]
174
pub struct PlotResultDescriptor {
175
    pub spatial_reference: SpatialReferenceOption,
176
    pub time: Option<TimeInterval>,
177
    pub bbox: Option<BoundingBox2D>,
178
}
179

180
impl From<geoengine_operators::engine::PlotResultDescriptor> for PlotResultDescriptor {
181
    fn from(value: geoengine_operators::engine::PlotResultDescriptor) -> Self {
×
182
        Self {
×
183
            spatial_reference: value.spatial_reference.into(),
×
184
            time: value.time.map(Into::into),
×
185
            bbox: value.bbox.map(Into::into),
×
186
        }
×
187
    }
×
188
}
189

190
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
12✔
191
#[serde(rename_all = "camelCase", tag = "type")]
192
pub enum TypedResultDescriptor {
193
    Plot(PlotResultDescriptor),
194
    Raster(RasterResultDescriptor),
195
    Vector(VectorResultDescriptor),
196
}
197

198
impl From<geoengine_operators::engine::TypedResultDescriptor> for TypedResultDescriptor {
199
    fn from(value: geoengine_operators::engine::TypedResultDescriptor) -> Self {
62✔
200
        match value {
62✔
201
            geoengine_operators::engine::TypedResultDescriptor::Plot(p) => Self::Plot(p.into()),
×
202
            geoengine_operators::engine::TypedResultDescriptor::Raster(r) => Self::Raster(r.into()),
48✔
203
            geoengine_operators::engine::TypedResultDescriptor::Vector(v) => Self::Vector(v.into()),
14✔
204
        }
205
    }
62✔
206
}
207

208
impl From<geoengine_operators::engine::PlotResultDescriptor> for TypedResultDescriptor {
209
    fn from(value: geoengine_operators::engine::PlotResultDescriptor) -> Self {
×
210
        Self::Plot(value.into())
×
211
    }
×
212
}
213

214
impl From<PlotResultDescriptor> for TypedResultDescriptor {
215
    fn from(value: PlotResultDescriptor) -> Self {
×
216
        Self::Plot(value)
×
217
    }
×
218
}
219

220
impl From<geoengine_operators::engine::RasterResultDescriptor> for TypedResultDescriptor {
221
    fn from(value: geoengine_operators::engine::RasterResultDescriptor) -> Self {
×
222
        Self::Raster(value.into())
×
223
    }
×
224
}
225

226
impl From<RasterResultDescriptor> for TypedResultDescriptor {
227
    fn from(value: RasterResultDescriptor) -> Self {
×
228
        Self::Raster(value)
×
229
    }
×
230
}
231

232
impl From<geoengine_operators::engine::VectorResultDescriptor> for TypedResultDescriptor {
233
    fn from(value: geoengine_operators::engine::VectorResultDescriptor) -> Self {
2✔
234
        Self::Vector(value.into())
2✔
235
    }
2✔
236
}
237

238
impl From<VectorResultDescriptor> for TypedResultDescriptor {
239
    fn from(value: VectorResultDescriptor) -> Self {
×
240
        Self::Vector(value)
×
241
    }
×
242
}
243

244
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, ToSchema)]
×
245
pub struct MockDatasetDataSourceLoadingInfo {
246
    pub points: Vec<Coordinate2D>,
247
}
248

249
impl From<geoengine_operators::mock::MockDatasetDataSourceLoadingInfo>
250
    for MockDatasetDataSourceLoadingInfo
251
{
252
    fn from(value: geoengine_operators::mock::MockDatasetDataSourceLoadingInfo) -> Self {
×
253
        Self {
×
254
            points: value.points.into_iter().map(Into::into).collect(),
×
255
        }
×
256
    }
×
257
}
258

259
impl From<MockDatasetDataSourceLoadingInfo>
260
    for geoengine_operators::mock::MockDatasetDataSourceLoadingInfo
261
{
262
    fn from(value: MockDatasetDataSourceLoadingInfo) -> Self {
×
263
        Self {
×
264
            points: value.points.into_iter().map(Into::into).collect(),
×
265
        }
×
266
    }
×
267
}
268

269
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
10✔
270
#[serde(rename_all = "camelCase")]
271
pub struct StaticMetaData<L, R, Q> {
272
    pub loading_info: L,
273
    pub result_descriptor: R,
274
    #[serde(skip)]
275
    pub phantom: PhantomData<Q>,
276
}
277

278
impl
279
    From<
280
        geoengine_operators::engine::StaticMetaData<
281
            geoengine_operators::mock::MockDatasetDataSourceLoadingInfo,
282
            geoengine_operators::engine::VectorResultDescriptor,
283
            geoengine_datatypes::primitives::QueryRectangle<
284
                geoengine_datatypes::primitives::BoundingBox2D,
285
            >,
286
        >,
287
    >
288
    for StaticMetaData<
289
        MockDatasetDataSourceLoadingInfo,
290
        VectorResultDescriptor,
291
        QueryRectangle<BoundingBox2D>,
292
    >
293
{
294
    fn from(
×
295
        value: geoengine_operators::engine::StaticMetaData<
×
296
            geoengine_operators::mock::MockDatasetDataSourceLoadingInfo,
×
297
            geoengine_operators::engine::VectorResultDescriptor,
×
298
            geoengine_datatypes::primitives::QueryRectangle<
×
299
                geoengine_datatypes::primitives::BoundingBox2D,
×
300
            >,
×
301
        >,
×
302
    ) -> Self {
×
303
        Self {
×
304
            loading_info: value.loading_info.into(),
×
305
            result_descriptor: value.result_descriptor.into(),
×
306
            phantom: Default::default(),
×
307
        }
×
308
    }
×
309
}
310

311
impl
312
    From<
313
        geoengine_operators::engine::StaticMetaData<
314
            geoengine_operators::source::OgrSourceDataset,
315
            geoengine_operators::engine::VectorResultDescriptor,
316
            geoengine_datatypes::primitives::QueryRectangle<
317
                geoengine_datatypes::primitives::BoundingBox2D,
318
            >,
319
        >,
320
    > for StaticMetaData<OgrSourceDataset, VectorResultDescriptor, QueryRectangle<BoundingBox2D>>
321
{
322
    fn from(
1✔
323
        value: geoengine_operators::engine::StaticMetaData<
1✔
324
            geoengine_operators::source::OgrSourceDataset,
1✔
325
            geoengine_operators::engine::VectorResultDescriptor,
1✔
326
            geoengine_datatypes::primitives::QueryRectangle<
1✔
327
                geoengine_datatypes::primitives::BoundingBox2D,
1✔
328
            >,
1✔
329
        >,
1✔
330
    ) -> Self {
1✔
331
        Self {
1✔
332
            loading_info: value.loading_info.into(),
1✔
333
            result_descriptor: value.result_descriptor.into(),
1✔
334
            phantom: Default::default(),
1✔
335
        }
1✔
336
    }
1✔
337
}
338

339
#[async_trait]
340
impl<L, R, Q> MetaData<L, R, Q> for StaticMetaData<L, R, Q>
341
where
342
    L: Debug + Clone + Send + Sync + 'static,
343
    R: Debug + Send + Sync + 'static + ResultDescriptor,
344
    Q: Debug + Clone + Send + Sync + 'static,
345
{
346
    async fn loading_info(&self, _query: Q) -> geoengine_operators::util::Result<L> {
×
347
        Ok(self.loading_info.clone())
×
348
    }
×
349

350
    async fn result_descriptor(&self) -> geoengine_operators::util::Result<R> {
×
351
        Ok(self.result_descriptor.clone())
×
352
    }
×
353

354
    fn box_clone(&self) -> Box<dyn MetaData<L, R, Q>> {
×
355
        Box::new(self.clone())
×
356
    }
×
357
}
358

359
pub type MockMetaData =
360
    StaticMetaData<MockDatasetDataSourceLoadingInfo, VectorResultDescriptor, VectorQueryRectangle>;
361
pub type OgrMetaData =
362
    StaticMetaData<OgrSourceDataset, VectorResultDescriptor, VectorQueryRectangle>;
363

364
impl From<MockMetaData>
365
    for geoengine_operators::engine::StaticMetaData<
366
        geoengine_operators::mock::MockDatasetDataSourceLoadingInfo,
367
        geoengine_operators::engine::VectorResultDescriptor,
368
        geoengine_datatypes::primitives::QueryRectangle<
369
            geoengine_datatypes::primitives::BoundingBox2D,
370
        >,
371
    >
372
{
373
    fn from(value: MockMetaData) -> Self {
×
374
        Self {
×
375
            loading_info: value.loading_info.into(),
×
376
            result_descriptor: value.result_descriptor.into(),
×
377
            phantom: Default::default(),
×
378
        }
×
379
    }
×
380
}
381

382
impl From<OgrMetaData>
383
    for geoengine_operators::engine::StaticMetaData<
384
        geoengine_operators::source::OgrSourceDataset,
385
        geoengine_operators::engine::VectorResultDescriptor,
386
        geoengine_datatypes::primitives::QueryRectangle<
387
            geoengine_datatypes::primitives::BoundingBox2D,
388
        >,
389
    >
390
{
391
    fn from(value: OgrMetaData) -> Self {
2✔
392
        Self {
2✔
393
            loading_info: value.loading_info.into(),
2✔
394
            result_descriptor: value.result_descriptor.into(),
2✔
395
            phantom: Default::default(),
2✔
396
        }
2✔
397
    }
2✔
398
}
399

400
impl ToSchema for MockMetaData {
401
    fn schema() -> utoipa::openapi::Schema {
×
402
        use utoipa::openapi::*;
×
403
        ObjectBuilder::new()
×
404
            .property(
×
405
                "loadingInfo",
×
406
                Ref::from_schema_name("MockDatasetDataSourceLoadingInfo"),
×
407
            )
×
408
            .required("loadingInfo")
×
409
            .property(
×
410
                "resultDescriptor",
×
411
                Ref::from_schema_name("VectorResultDescriptor"),
×
412
            )
×
413
            .required("resultDescriptor")
×
414
            .into()
×
415
    }
×
416
}
417

418
impl ToSchema for OgrMetaData {
419
    fn schema() -> utoipa::openapi::Schema {
×
420
        use utoipa::openapi::*;
×
421
        ObjectBuilder::new()
×
422
            .property("loadingInfo", Ref::from_schema_name("OgrSourceDataset"))
×
423
            .required("loadingInfo")
×
424
            .property(
×
425
                "resultDescriptor",
×
426
                Ref::from_schema_name("VectorResultDescriptor"),
×
427
            )
×
428
            .required("resultDescriptor")
×
429
            .into()
×
430
    }
×
431
}
432

433
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
×
434
#[serde(rename_all = "camelCase")]
435
pub struct GdalMetaDataStatic {
436
    pub time: Option<TimeInterval>,
437
    pub params: GdalDatasetParameters,
438
    pub result_descriptor: RasterResultDescriptor,
439
}
440

441
impl From<geoengine_operators::source::GdalMetaDataStatic> for GdalMetaDataStatic {
442
    fn from(value: geoengine_operators::source::GdalMetaDataStatic) -> Self {
×
443
        Self {
×
444
            time: value.time.map(Into::into),
×
445
            params: value.params.into(),
×
446
            result_descriptor: value.result_descriptor.into(),
×
447
        }
×
448
    }
×
449
}
450

451
impl From<GdalMetaDataStatic> for geoengine_operators::source::GdalMetaDataStatic {
452
    fn from(value: GdalMetaDataStatic) -> Self {
1✔
453
        Self {
1✔
454
            time: value.time.map(Into::into),
1✔
455
            params: value.params.into(),
1✔
456
            result_descriptor: value.result_descriptor.into(),
1✔
457
        }
1✔
458
    }
1✔
459
}
460

461
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, ToSchema)]
30✔
462
#[serde(rename_all = "camelCase")]
463
pub struct OgrSourceDataset {
464
    #[schema(value_type = String)]
465
    pub file_name: PathBuf,
466
    pub layer_name: String,
467
    pub data_type: Option<VectorDataType>,
468
    #[serde(default)]
469
    pub time: OgrSourceDatasetTimeType,
470
    pub default_geometry: Option<TypedGeometry>,
471
    pub columns: Option<OgrSourceColumnSpec>,
472
    #[serde(default)]
473
    pub force_ogr_time_filter: bool,
474
    #[serde(default)]
475
    pub force_ogr_spatial_filter: bool,
476
    pub on_error: OgrSourceErrorSpec,
477
    pub sql_query: Option<String>,
478
    pub attribute_query: Option<String>,
479
}
480

481
impl From<geoengine_operators::source::OgrSourceDataset> for OgrSourceDataset {
482
    fn from(value: geoengine_operators::source::OgrSourceDataset) -> Self {
1✔
483
        Self {
1✔
484
            file_name: value.file_name,
1✔
485
            layer_name: value.layer_name,
1✔
486
            data_type: value.data_type.map(Into::into),
1✔
487
            time: value.time.into(),
1✔
488
            default_geometry: value.default_geometry.map(Into::into),
1✔
489
            columns: value.columns.map(Into::into),
1✔
490
            force_ogr_time_filter: value.force_ogr_time_filter,
1✔
491
            force_ogr_spatial_filter: value.force_ogr_spatial_filter,
1✔
492
            on_error: value.on_error.into(),
1✔
493
            sql_query: value.sql_query,
1✔
494
            attribute_query: value.attribute_query,
1✔
495
        }
1✔
496
    }
1✔
497
}
498

499
impl From<OgrSourceDataset> for geoengine_operators::source::OgrSourceDataset {
500
    fn from(value: OgrSourceDataset) -> Self {
2✔
501
        Self {
2✔
502
            file_name: value.file_name,
2✔
503
            layer_name: value.layer_name,
2✔
504
            data_type: value.data_type.map(Into::into),
2✔
505
            time: value.time.into(),
2✔
506
            default_geometry: value.default_geometry.map(Into::into),
2✔
507
            columns: value.columns.map(Into::into),
2✔
508
            force_ogr_time_filter: value.force_ogr_time_filter,
2✔
509
            force_ogr_spatial_filter: value.force_ogr_spatial_filter,
2✔
510
            on_error: value.on_error.into(),
2✔
511
            sql_query: value.sql_query,
2✔
512
            attribute_query: value.attribute_query,
2✔
513
        }
2✔
514
    }
2✔
515
}
516

517
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug, ToSchema)]
×
518
#[serde(tag = "format")]
519
#[serde(rename_all = "camelCase")]
520
pub enum OgrSourceTimeFormat {
521
    #[serde(rename_all = "camelCase")]
522
    Custom {
523
        custom_format: DateTimeParseFormat,
524
    },
525
    #[serde(rename_all = "camelCase")]
526
    UnixTimeStamp {
527
        timestamp_type: UnixTimeStampType,
528
        #[serde(skip)]
529
        #[serde(default = "DateTimeParseFormat::unix")]
530
        fmt: DateTimeParseFormat,
531
    },
532
    Auto,
533
}
534

535
impl From<geoengine_operators::source::OgrSourceTimeFormat> for OgrSourceTimeFormat {
536
    fn from(value: geoengine_operators::source::OgrSourceTimeFormat) -> Self {
×
537
        match value {
×
538
            geoengine_operators::source::OgrSourceTimeFormat::Custom { custom_format } => {
×
539
                Self::Custom {
×
540
                    custom_format: custom_format.into(),
×
541
                }
×
542
            }
543
            geoengine_operators::source::OgrSourceTimeFormat::UnixTimeStamp {
544
                timestamp_type,
×
545
                fmt,
×
546
            } => Self::UnixTimeStamp {
×
547
                timestamp_type: timestamp_type.into(),
×
548
                fmt: fmt.into(),
×
549
            },
×
550
            geoengine_operators::source::OgrSourceTimeFormat::Auto => Self::Auto,
×
551
        }
552
    }
×
553
}
554

555
impl From<OgrSourceTimeFormat> for geoengine_operators::source::OgrSourceTimeFormat {
556
    fn from(value: OgrSourceTimeFormat) -> Self {
×
557
        match value {
×
558
            OgrSourceTimeFormat::Custom { custom_format } => Self::Custom {
×
559
                custom_format: custom_format.into(),
×
560
            },
×
561
            OgrSourceTimeFormat::UnixTimeStamp {
562
                timestamp_type,
×
563
                fmt,
×
564
            } => Self::UnixTimeStamp {
×
565
                timestamp_type: timestamp_type.into(),
×
566
                fmt: fmt.into(),
×
567
            },
×
568
            OgrSourceTimeFormat::Auto => Self::Auto,
×
569
        }
570
    }
×
571
}
572

573
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
×
574
#[serde(rename_all = "camelCase")]
575
pub enum UnixTimeStampType {
576
    EpochSeconds,
577
    EpochMilliseconds,
578
}
579

580
impl From<geoengine_operators::source::UnixTimeStampType> for UnixTimeStampType {
581
    fn from(value: geoengine_operators::source::UnixTimeStampType) -> Self {
×
582
        match value {
×
583
            geoengine_operators::source::UnixTimeStampType::EpochSeconds => Self::EpochSeconds,
×
584
            geoengine_operators::source::UnixTimeStampType::EpochMilliseconds => {
585
                Self::EpochMilliseconds
×
586
            }
587
        }
588
    }
×
589
}
590

591
impl From<UnixTimeStampType> for geoengine_operators::source::UnixTimeStampType {
592
    fn from(value: UnixTimeStampType) -> Self {
×
593
        match value {
×
594
            UnixTimeStampType::EpochSeconds => Self::EpochSeconds,
×
595
            UnixTimeStampType::EpochMilliseconds => Self::EpochMilliseconds,
×
596
        }
597
    }
×
598
}
599

600
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
4✔
601
#[serde(rename_all = "lowercase")]
602
pub enum OgrSourceErrorSpec {
603
    Ignore,
604
    Abort,
605
}
606

607
impl From<geoengine_operators::source::OgrSourceErrorSpec> for OgrSourceErrorSpec {
608
    fn from(value: geoengine_operators::source::OgrSourceErrorSpec) -> Self {
1✔
609
        match value {
1✔
610
            geoengine_operators::source::OgrSourceErrorSpec::Ignore => Self::Ignore,
1✔
611
            geoengine_operators::source::OgrSourceErrorSpec::Abort => Self::Abort,
×
612
        }
613
    }
1✔
614
}
615

616
impl From<OgrSourceErrorSpec> for geoengine_operators::source::OgrSourceErrorSpec {
617
    fn from(value: OgrSourceErrorSpec) -> Self {
2✔
618
        match value {
2✔
619
            OgrSourceErrorSpec::Ignore => Self::Ignore,
2✔
620
            OgrSourceErrorSpec::Abort => Self::Abort,
×
621
        }
622
    }
2✔
623
}
624

625
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, ToSchema)]
4✔
626
#[serde(rename_all = "camelCase", tag = "type")]
627
pub enum OgrSourceDatasetTimeType {
628
    None,
629
    #[serde(rename_all = "camelCase")]
630
    Start {
631
        start_field: String,
632
        start_format: OgrSourceTimeFormat,
633
        duration: OgrSourceDurationSpec,
634
    },
635
    #[serde(rename = "start+end")]
636
    #[serde(rename_all = "camelCase")]
637
    StartEnd {
638
        start_field: String,
639
        start_format: OgrSourceTimeFormat,
640
        end_field: String,
641
        end_format: OgrSourceTimeFormat,
642
    },
643
    #[serde(rename = "start+duration")]
644
    #[serde(rename_all = "camelCase")]
645
    StartDuration {
646
        start_field: String,
647
        start_format: OgrSourceTimeFormat,
648
        duration_field: String,
649
    },
650
}
651

652
impl From<geoengine_operators::source::OgrSourceDatasetTimeType> for OgrSourceDatasetTimeType {
653
    fn from(value: geoengine_operators::source::OgrSourceDatasetTimeType) -> Self {
1✔
654
        match value {
1✔
655
            geoengine_operators::source::OgrSourceDatasetTimeType::None => Self::None,
1✔
656
            geoengine_operators::source::OgrSourceDatasetTimeType::Start {
657
                start_field,
×
658
                start_format,
×
659
                duration,
×
660
            } => Self::Start {
×
661
                start_field,
×
662
                start_format: start_format.into(),
×
663
                duration: duration.into(),
×
664
            },
×
665
            geoengine_operators::source::OgrSourceDatasetTimeType::StartEnd {
666
                start_field,
×
667
                start_format,
×
668
                end_field,
×
669
                end_format,
×
670
            } => Self::StartEnd {
×
671
                start_field,
×
672
                start_format: start_format.into(),
×
673
                end_field,
×
674
                end_format: end_format.into(),
×
675
            },
×
676
            geoengine_operators::source::OgrSourceDatasetTimeType::StartDuration {
677
                start_field,
×
678
                start_format,
×
679
                duration_field,
×
680
            } => Self::StartDuration {
×
681
                start_field,
×
682
                start_format: start_format.into(),
×
683
                duration_field,
×
684
            },
×
685
        }
686
    }
1✔
687
}
688

689
impl From<OgrSourceDatasetTimeType> for geoengine_operators::source::OgrSourceDatasetTimeType {
690
    fn from(value: OgrSourceDatasetTimeType) -> Self {
2✔
691
        match value {
2✔
692
            OgrSourceDatasetTimeType::None => Self::None,
2✔
693
            OgrSourceDatasetTimeType::Start {
694
                start_field,
×
695
                start_format,
×
696
                duration,
×
697
            } => Self::Start {
×
698
                start_field,
×
699
                start_format: start_format.into(),
×
700
                duration: duration.into(),
×
701
            },
×
702
            OgrSourceDatasetTimeType::StartEnd {
703
                start_field,
×
704
                start_format,
×
705
                end_field,
×
706
                end_format,
×
707
            } => Self::StartEnd {
×
708
                start_field,
×
709
                start_format: start_format.into(),
×
710
                end_field,
×
711
                end_format: end_format.into(),
×
712
            },
×
713
            OgrSourceDatasetTimeType::StartDuration {
714
                start_field,
×
715
                start_format,
×
716
                duration_field,
×
717
            } => Self::StartDuration {
×
718
                start_field,
×
719
                start_format: start_format.into(),
×
720
                duration_field,
×
721
            },
×
722
        }
723
    }
2✔
724
}
725

726
/// If no time is specified, expect to parse none
727
impl Default for OgrSourceDatasetTimeType {
728
    fn default() -> Self {
×
729
        Self::None
×
730
    }
×
731
}
732

733
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
×
734
#[serde(rename_all = "camelCase", tag = "type")]
735
pub enum OgrSourceDurationSpec {
736
    Infinite,
737
    Zero,
738
    Value(TimeStep),
739
}
740

741
impl From<geoengine_operators::source::OgrSourceDurationSpec> for OgrSourceDurationSpec {
742
    fn from(value: geoengine_operators::source::OgrSourceDurationSpec) -> Self {
×
743
        match value {
×
744
            geoengine_operators::source::OgrSourceDurationSpec::Infinite => Self::Infinite,
×
745
            geoengine_operators::source::OgrSourceDurationSpec::Zero => Self::Zero,
×
746
            geoengine_operators::source::OgrSourceDurationSpec::Value(v) => Self::Value(v.into()),
×
747
        }
748
    }
×
749
}
750

751
impl From<OgrSourceDurationSpec> for geoengine_operators::source::OgrSourceDurationSpec {
752
    fn from(value: OgrSourceDurationSpec) -> Self {
×
753
        match value {
×
754
            OgrSourceDurationSpec::Infinite => Self::Infinite,
×
755
            OgrSourceDurationSpec::Zero => Self::Zero,
×
756
            OgrSourceDurationSpec::Value(v) => Self::Value(v.into()),
×
757
        }
758
    }
×
759
}
760

761
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema)]
×
762
pub enum TypedGeometry {
763
    Data(NoGeometry),
764
    MultiPoint(MultiPoint),
765
    MultiLineString(MultiLineString),
766
    MultiPolygon(MultiPolygon),
767
}
768

769
impl From<geoengine_datatypes::primitives::TypedGeometry> for TypedGeometry {
770
    fn from(value: geoengine_datatypes::primitives::TypedGeometry) -> Self {
×
771
        match value {
×
772
            geoengine_datatypes::primitives::TypedGeometry::Data(x) => Self::Data(x.into()),
×
773
            geoengine_datatypes::primitives::TypedGeometry::MultiPoint(x) => {
×
774
                Self::MultiPoint(x.into())
×
775
            }
776
            geoengine_datatypes::primitives::TypedGeometry::MultiLineString(x) => {
×
777
                Self::MultiLineString(x.into())
×
778
            }
779
            geoengine_datatypes::primitives::TypedGeometry::MultiPolygon(x) => {
×
780
                Self::MultiPolygon(x.into())
×
781
            }
782
        }
783
    }
×
784
}
785

786
impl From<TypedGeometry> for geoengine_datatypes::primitives::TypedGeometry {
787
    fn from(value: TypedGeometry) -> Self {
×
788
        match value {
×
789
            TypedGeometry::Data(x) => Self::Data(x.into()),
×
790
            TypedGeometry::MultiPoint(x) => Self::MultiPoint(x.into()),
×
791
            TypedGeometry::MultiLineString(x) => Self::MultiLineString(x.into()),
×
792
            TypedGeometry::MultiPolygon(x) => Self::MultiPolygon(x.into()),
×
793
        }
794
    }
×
795
}
796

797
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
30✔
798
#[serde(rename_all = "camelCase")]
799
pub struct OgrSourceColumnSpec {
800
    pub format_specifics: Option<FormatSpecifics>,
801
    pub x: String,
802
    pub y: Option<String>,
803
    #[serde(default)]
804
    pub int: Vec<String>,
805
    #[serde(default)]
806
    pub float: Vec<String>,
807
    #[serde(default)]
808
    pub text: Vec<String>,
809
    #[serde(default)]
810
    pub bool: Vec<String>,
811
    #[serde(default)]
812
    pub datetime: Vec<String>,
813
    pub rename: Option<HashMap<String, String>>,
814
}
815

816
impl From<geoengine_operators::source::OgrSourceColumnSpec> for OgrSourceColumnSpec {
817
    fn from(value: geoengine_operators::source::OgrSourceColumnSpec) -> Self {
1✔
818
        Self {
1✔
819
            format_specifics: value.format_specifics.map(Into::into),
1✔
820
            x: value.x,
1✔
821
            y: value.y,
1✔
822
            int: value.int,
1✔
823
            float: value.float,
1✔
824
            text: value.text,
1✔
825
            bool: value.bool,
1✔
826
            datetime: value.datetime,
1✔
827
            rename: value.rename,
1✔
828
        }
1✔
829
    }
1✔
830
}
831

832
impl From<OgrSourceColumnSpec> for geoengine_operators::source::OgrSourceColumnSpec {
833
    fn from(value: OgrSourceColumnSpec) -> Self {
2✔
834
        Self {
2✔
835
            format_specifics: value.format_specifics.map(Into::into),
2✔
836
            x: value.x,
2✔
837
            y: value.y,
2✔
838
            int: value.int,
2✔
839
            float: value.float,
2✔
840
            text: value.text,
2✔
841
            bool: value.bool,
2✔
842
            datetime: value.datetime,
2✔
843
            rename: value.rename,
2✔
844
        }
2✔
845
    }
2✔
846
}
847

848
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
22✔
849
#[serde(rename_all = "camelCase")]
850
pub struct GdalMetaDataRegular {
851
    pub result_descriptor: RasterResultDescriptor,
852
    pub params: GdalDatasetParameters,
853
    pub time_placeholders: HashMap<String, GdalSourceTimePlaceholder>,
854
    pub data_time: TimeInterval,
855
    pub step: TimeStep,
856
}
857

858
impl From<geoengine_operators::source::GdalMetaDataRegular> for GdalMetaDataRegular {
859
    fn from(value: geoengine_operators::source::GdalMetaDataRegular) -> Self {
2✔
860
        Self {
2✔
861
            result_descriptor: value.result_descriptor.into(),
2✔
862
            params: value.params.into(),
2✔
863
            time_placeholders: value
2✔
864
                .time_placeholders
2✔
865
                .into_iter()
2✔
866
                .map(|(k, v)| (k, v.into()))
2✔
867
                .collect(),
2✔
868
            data_time: value.data_time.into(),
2✔
869
            step: value.step.into(),
2✔
870
        }
2✔
871
    }
2✔
872
}
873

874
impl From<GdalMetaDataRegular> for geoengine_operators::source::GdalMetaDataRegular {
875
    fn from(value: GdalMetaDataRegular) -> Self {
2✔
876
        Self {
2✔
877
            result_descriptor: value.result_descriptor.into(),
2✔
878
            params: value.params.into(),
2✔
879
            time_placeholders: value
2✔
880
                .time_placeholders
2✔
881
                .into_iter()
2✔
882
                .map(|(k, v)| (k, v.into()))
2✔
883
                .collect(),
2✔
884
            data_time: value.data_time.into(),
2✔
885
            step: value.step.into(),
2✔
886
        }
2✔
887
    }
2✔
888
}
889

890
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
×
891
pub struct GdalConfigOption((String, String));
892

893
impl ToSchema for GdalConfigOption {
894
    fn schema() -> utoipa::openapi::Schema {
×
895
        use utoipa::openapi::*;
×
896
        ArrayBuilder::new()
×
897
            .items(Object::with_type(SchemaType::String))
×
898
            .min_items(Some(2))
×
899
            .max_items(Some(2))
×
900
            .into()
×
901
    }
×
902
}
903

904
/// Parameters for loading data using Gdal
905
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
46✔
906
#[serde(rename_all = "camelCase")]
907
pub struct GdalDatasetParameters {
908
    #[schema(value_type = String)]
909
    pub file_path: PathBuf,
910
    pub rasterband_channel: usize,
911
    pub geo_transform: GdalDatasetGeoTransform, // TODO: discuss if we need this at all
912
    pub width: usize,
913
    pub height: usize,
914
    pub file_not_found_handling: FileNotFoundHandling,
915
    #[serde(default)]
916
    //#[serde(with = "float_option_with_nan")]
917
    pub no_data_value: Option<f64>,
918
    pub properties_mapping: Option<Vec<GdalMetadataMapping>>,
919
    // Dataset open option as strings, e.g. `vec!["UserPwd=geoengine:pwd".to_owned(), "HttpAuth=BASIC".to_owned()]`
920
    pub gdal_open_options: Option<Vec<String>>,
921
    // Configs as key, value pairs that will be set as thread local config options, e.g.
922
    // `vec!["AWS_REGION".to_owned(), "eu-central-1".to_owned()]` and unset afterwards
923
    // TODO: validate the config options: only allow specific keys and specific values
924
    pub gdal_config_options: Option<Vec<GdalConfigOption>>,
925
    #[serde(default)]
926
    pub allow_alphaband_as_mask: bool,
927
}
928

929
impl From<geoengine_operators::source::GdalDatasetParameters> for GdalDatasetParameters {
930
    fn from(value: geoengine_operators::source::GdalDatasetParameters) -> Self {
2✔
931
        Self {
2✔
932
            file_path: value.file_path,
2✔
933
            rasterband_channel: value.rasterband_channel,
2✔
934
            geo_transform: value.geo_transform.into(),
2✔
935
            width: value.width,
2✔
936
            height: value.height,
2✔
937
            file_not_found_handling: value.file_not_found_handling.into(),
2✔
938
            no_data_value: value.no_data_value,
2✔
939
            properties_mapping: value
2✔
940
                .properties_mapping
2✔
941
                .map(|x| x.into_iter().map(Into::into).collect()),
2✔
942
            gdal_open_options: value.gdal_open_options,
2✔
943
            gdal_config_options: value
2✔
944
                .gdal_config_options
2✔
945
                .map(|x| x.into_iter().map(GdalConfigOption).collect()),
2✔
946
            allow_alphaband_as_mask: value.allow_alphaband_as_mask,
2✔
947
        }
2✔
948
    }
2✔
949
}
950

951
impl From<GdalDatasetParameters> for geoengine_operators::source::GdalDatasetParameters {
952
    fn from(value: GdalDatasetParameters) -> Self {
3✔
953
        Self {
3✔
954
            file_path: value.file_path,
3✔
955
            rasterband_channel: value.rasterband_channel,
3✔
956
            geo_transform: value.geo_transform.into(),
3✔
957
            width: value.width,
3✔
958
            height: value.height,
3✔
959
            file_not_found_handling: value.file_not_found_handling.into(),
3✔
960
            no_data_value: value.no_data_value,
3✔
961
            properties_mapping: value
3✔
962
                .properties_mapping
3✔
963
                .map(|x| x.into_iter().map(Into::into).collect()),
3✔
964
            gdal_open_options: value.gdal_open_options,
3✔
965
            gdal_config_options: value
3✔
966
                .gdal_config_options
3✔
967
                .map(|x| x.into_iter().map(|y| y.0).collect()),
3✔
968
            allow_alphaband_as_mask: value.allow_alphaband_as_mask,
3✔
969
        }
3✔
970
    }
3✔
971
}
972

973
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
10✔
974
pub struct GdalSourceTimePlaceholder {
975
    pub format: DateTimeParseFormat,
976
    pub reference: TimeReference,
977
}
978

979
impl From<geoengine_operators::source::GdalSourceTimePlaceholder> for GdalSourceTimePlaceholder {
980
    fn from(value: geoengine_operators::source::GdalSourceTimePlaceholder) -> Self {
2✔
981
        Self {
2✔
982
            format: value.format.into(),
2✔
983
            reference: value.reference.into(),
2✔
984
        }
2✔
985
    }
2✔
986
}
987

988
impl From<GdalSourceTimePlaceholder> for geoengine_operators::source::GdalSourceTimePlaceholder {
989
    fn from(value: GdalSourceTimePlaceholder) -> Self {
2✔
990
        Self {
2✔
991
            format: value.format.into(),
2✔
992
            reference: value.reference.into(),
2✔
993
        }
2✔
994
    }
2✔
995
}
996

997
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, ToSchema)]
14✔
998
#[serde(rename_all = "camelCase")]
999
pub struct GdalDatasetGeoTransform {
1000
    pub origin_coordinate: Coordinate2D,
1001
    pub x_pixel_size: f64,
1002
    pub y_pixel_size: f64,
1003
}
1004

1005
impl From<geoengine_operators::source::GdalDatasetGeoTransform> for GdalDatasetGeoTransform {
1006
    fn from(value: geoengine_operators::source::GdalDatasetGeoTransform) -> Self {
2✔
1007
        Self {
2✔
1008
            origin_coordinate: value.origin_coordinate.into(),
2✔
1009
            x_pixel_size: value.x_pixel_size,
2✔
1010
            y_pixel_size: value.y_pixel_size,
2✔
1011
        }
2✔
1012
    }
2✔
1013
}
1014

1015
impl From<GdalDatasetGeoTransform> for geoengine_operators::source::GdalDatasetGeoTransform {
1016
    fn from(value: GdalDatasetGeoTransform) -> Self {
3✔
1017
        Self {
3✔
1018
            origin_coordinate: value.origin_coordinate.into(),
3✔
1019
            x_pixel_size: value.x_pixel_size,
3✔
1020
            y_pixel_size: value.y_pixel_size,
3✔
1021
        }
3✔
1022
    }
3✔
1023
}
1024

1025
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, ToSchema)]
4✔
1026
pub enum FileNotFoundHandling {
1027
    NoData, // output tiles filled with nodata
1028
    Error,  // return error tile
1029
}
1030

1031
impl From<geoengine_operators::source::FileNotFoundHandling> for FileNotFoundHandling {
1032
    fn from(value: geoengine_operators::source::FileNotFoundHandling) -> Self {
2✔
1033
        match value {
2✔
1034
            geoengine_operators::source::FileNotFoundHandling::NoData => Self::NoData,
2✔
1035
            geoengine_operators::source::FileNotFoundHandling::Error => Self::Error,
×
1036
        }
1037
    }
2✔
1038
}
1039

1040
impl From<FileNotFoundHandling> for geoengine_operators::source::FileNotFoundHandling {
1041
    fn from(value: FileNotFoundHandling) -> Self {
3✔
1042
        match value {
3✔
1043
            FileNotFoundHandling::NoData => Self::NoData,
3✔
1044
            FileNotFoundHandling::Error => Self::Error,
×
1045
        }
1046
    }
3✔
1047
}
1048

1049
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
×
1050
pub struct GdalMetadataMapping {
1051
    pub source_key: RasterPropertiesKey,
1052
    pub target_key: RasterPropertiesKey,
1053
    pub target_type: RasterPropertiesEntryType,
1054
}
1055

1056
impl From<geoengine_operators::source::GdalMetadataMapping> for GdalMetadataMapping {
1057
    fn from(value: geoengine_operators::source::GdalMetadataMapping) -> Self {
×
1058
        Self {
×
1059
            source_key: value.source_key.into(),
×
1060
            target_key: value.target_key.into(),
×
1061
            target_type: value.target_type.into(),
×
1062
        }
×
1063
    }
×
1064
}
1065

1066
impl From<GdalMetadataMapping> for geoengine_operators::source::GdalMetadataMapping {
1067
    fn from(value: GdalMetadataMapping) -> Self {
×
1068
        Self {
×
1069
            source_key: value.source_key.into(),
×
1070
            target_key: value.target_key.into(),
×
1071
            target_type: value.target_type.into(),
×
1072
        }
×
1073
    }
×
1074
}
1075

1076
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
4✔
1077
#[serde(rename_all = "camelCase")]
1078
pub enum TimeReference {
1079
    Start,
1080
    End,
1081
}
1082

1083
impl From<geoengine_operators::source::TimeReference> for TimeReference {
1084
    fn from(value: geoengine_operators::source::TimeReference) -> Self {
2✔
1085
        match value {
2✔
1086
            geoengine_operators::source::TimeReference::Start => Self::Start,
2✔
1087
            geoengine_operators::source::TimeReference::End => Self::End,
×
1088
        }
1089
    }
2✔
1090
}
1091

1092
impl From<TimeReference> for geoengine_operators::source::TimeReference {
1093
    fn from(value: TimeReference) -> Self {
2✔
1094
        match value {
2✔
1095
            TimeReference::Start => Self::Start,
2✔
1096
            TimeReference::End => Self::End,
×
1097
        }
1098
    }
2✔
1099
}
1100

1101
/// Meta data for 4D `NetCDF` CF datasets
1102
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
×
1103
#[serde(rename_all = "camelCase")]
1104
pub struct GdalMetadataNetCdfCf {
1105
    pub result_descriptor: RasterResultDescriptor,
1106
    pub params: GdalDatasetParameters,
1107
    pub start: TimeInstance,
1108
    /// We use the end to specify the last, non-inclusive valid time point.
1109
    /// Queries behind this point return no data.
1110
    /// TODO: Alternatively, we could think about using the number of possible time steps in the future.
1111
    pub end: TimeInstance,
1112
    pub step: TimeStep,
1113
    /// A band offset specifies the first band index to use for the first point in time.
1114
    /// All other time steps are added to this offset.
1115
    pub band_offset: usize,
1116
}
1117

1118
impl From<geoengine_operators::source::GdalMetadataNetCdfCf> for GdalMetadataNetCdfCf {
1119
    fn from(value: geoengine_operators::source::GdalMetadataNetCdfCf) -> Self {
×
1120
        Self {
×
1121
            result_descriptor: value.result_descriptor.into(),
×
1122
            params: value.params.into(),
×
1123
            start: value.start.into(),
×
1124
            end: value.end.into(),
×
1125
            step: value.step.into(),
×
1126
            band_offset: value.band_offset,
×
1127
        }
×
1128
    }
×
1129
}
1130

1131
impl From<GdalMetadataNetCdfCf> for geoengine_operators::source::GdalMetadataNetCdfCf {
1132
    fn from(value: GdalMetadataNetCdfCf) -> Self {
×
1133
        Self {
×
1134
            result_descriptor: value.result_descriptor.into(),
×
1135
            params: value.params.into(),
×
1136
            start: value.start.into(),
×
1137
            end: value.end.into(),
×
1138
            step: value.step.into(),
×
1139
            band_offset: value.band_offset,
×
1140
        }
×
1141
    }
×
1142
}
1143

1144
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
×
1145
#[serde(rename_all = "camelCase")]
1146
pub struct GdalMetaDataList {
1147
    pub result_descriptor: RasterResultDescriptor,
1148
    pub params: Vec<GdalLoadingInfoTemporalSlice>,
1149
}
1150

1151
impl From<geoengine_operators::source::GdalMetaDataList> for GdalMetaDataList {
1152
    fn from(value: geoengine_operators::source::GdalMetaDataList) -> Self {
×
1153
        Self {
×
1154
            result_descriptor: value.result_descriptor.into(),
×
1155
            params: value.params.into_iter().map(Into::into).collect(),
×
1156
        }
×
1157
    }
×
1158
}
1159

1160
impl From<GdalMetaDataList> for geoengine_operators::source::GdalMetaDataList {
1161
    fn from(value: GdalMetaDataList) -> Self {
×
1162
        Self {
×
1163
            result_descriptor: value.result_descriptor.into(),
×
1164
            params: value.params.into_iter().map(Into::into).collect(),
×
1165
        }
×
1166
    }
×
1167
}
1168

1169
/// one temporal slice of the dataset that requires reading from exactly one Gdal dataset
1170
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
×
1171
#[serde(rename_all = "camelCase")]
1172
pub struct GdalLoadingInfoTemporalSlice {
1173
    pub time: TimeInterval,
1174
    pub params: Option<GdalDatasetParameters>,
1175
}
1176

1177
impl From<geoengine_operators::source::GdalLoadingInfoTemporalSlice>
1178
    for GdalLoadingInfoTemporalSlice
1179
{
1180
    fn from(value: geoengine_operators::source::GdalLoadingInfoTemporalSlice) -> Self {
×
1181
        Self {
×
1182
            time: value.time.into(),
×
1183
            params: value.params.map(Into::into),
×
1184
        }
×
1185
    }
×
1186
}
1187

1188
impl From<GdalLoadingInfoTemporalSlice>
1189
    for geoengine_operators::source::GdalLoadingInfoTemporalSlice
1190
{
1191
    fn from(value: GdalLoadingInfoTemporalSlice) -> Self {
×
1192
        Self {
×
1193
            time: value.time.into(),
×
1194
            params: value.params.map(Into::into),
×
1195
        }
×
1196
    }
×
1197
}
1198

1199
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
×
1200
#[serde(rename_all = "lowercase")]
1201
pub enum CsvHeader {
1202
    Yes,
1203
    No,
1204
    Auto,
1205
}
1206

1207
impl From<geoengine_operators::source::CsvHeader> for CsvHeader {
1208
    fn from(value: geoengine_operators::source::CsvHeader) -> Self {
×
1209
        match value {
×
1210
            geoengine_operators::source::CsvHeader::Yes => Self::Yes,
×
1211
            geoengine_operators::source::CsvHeader::No => Self::No,
×
1212
            geoengine_operators::source::CsvHeader::Auto => Self::Auto,
×
1213
        }
1214
    }
×
1215
}
1216

1217
impl From<CsvHeader> for geoengine_operators::source::CsvHeader {
1218
    fn from(value: CsvHeader) -> Self {
×
1219
        match value {
×
1220
            CsvHeader::Yes => Self::Yes,
×
1221
            CsvHeader::No => Self::No,
×
1222
            CsvHeader::Auto => Self::Auto,
×
1223
        }
1224
    }
×
1225
}
1226

1227
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
×
1228
#[serde(rename_all = "camelCase")]
1229
pub enum FormatSpecifics {
1230
    Csv { header: CsvHeader },
1231
}
1232

1233
impl From<geoengine_operators::source::FormatSpecifics> for FormatSpecifics {
1234
    fn from(value: geoengine_operators::source::FormatSpecifics) -> Self {
×
1235
        match value {
×
1236
            geoengine_operators::source::FormatSpecifics::Csv { header } => Self::Csv {
×
1237
                header: header.into(),
×
1238
            },
×
1239
        }
×
1240
    }
×
1241
}
1242

1243
impl From<FormatSpecifics> for geoengine_operators::source::FormatSpecifics {
1244
    fn from(value: FormatSpecifics) -> Self {
×
1245
        match value {
×
1246
            FormatSpecifics::Csv { header } => Self::Csv {
×
1247
                header: header.into(),
×
1248
            },
×
1249
        }
×
1250
    }
×
1251
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc