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

geo-engine / geoengine / 6709775090

31 Oct 2023 03:43PM UTC coverage: 89.483% (-0.02%) from 89.498%
6709775090

push

github

web-flow
Merge pull request #882 from geo-engine/API-docs

Api docs

493 of 493 new or added lines in 15 files covered. (100.0%)

109476 of 122343 relevant lines covered (89.48%)

59359.13 hits per line

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

51.33
/services/src/api/model/operators.rs
1
use super::datatypes::{
2
    BoundingBox2D, FeatureDataType, Measurement, RasterDataType, SpatialPartition2D,
3
    SpatialReferenceOption, TimeInterval, VectorDataType,
4
};
5
use crate::api::model::datatypes::{
6
    CacheTtlSeconds, Coordinate2D, DateTimeParseFormat, GdalConfigOption, MultiLineString,
7
    MultiPoint, MultiPolygon, NoGeometry, QueryRectangle, RasterPropertiesEntryType,
8
    RasterPropertiesKey, SpatialResolution, TimeInstance, TimeStep, VectorQueryRectangle,
9
};
10
use async_trait::async_trait;
11
use geoengine_operators::{
12
    engine::{MetaData, ResultDescriptor},
13
    util::input::float_option_with_nan,
14
};
15
use serde::{Deserialize, Serialize};
16
use std::collections::HashMap;
17
use std::fmt::Debug;
18
use std::marker::PhantomData;
19
use std::path::PathBuf;
20
use utoipa::ToSchema;
21

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

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

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

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

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

110
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
42✔
111
#[serde(rename_all = "camelCase")]
112
pub struct VectorResultDescriptor {
113
    pub data_type: VectorDataType,
114
    #[schema(value_type = String)]
115
    pub spatial_reference: SpatialReferenceOption,
116
    pub columns: HashMap<String, VectorColumnInfo>,
117
    pub time: Option<TimeInterval>,
118
    pub bbox: Option<BoundingBox2D>,
119
}
120

121
impl From<geoengine_operators::engine::VectorResultDescriptor> for VectorResultDescriptor {
122
    fn from(value: geoengine_operators::engine::VectorResultDescriptor) -> Self {
1✔
123
        Self {
1✔
124
            data_type: value.data_type.into(),
1✔
125
            spatial_reference: value.spatial_reference.into(),
1✔
126
            columns: value
1✔
127
                .columns
1✔
128
                .into_iter()
1✔
129
                .map(|(key, value)| (key, value.into()))
2✔
130
                .collect(),
1✔
131
            time: value.time.map(Into::into),
1✔
132
            bbox: value.bbox.map(Into::into),
1✔
133
        }
1✔
134
    }
1✔
135
}
136

137
impl From<VectorResultDescriptor> for geoengine_operators::engine::VectorResultDescriptor {
138
    fn from(value: VectorResultDescriptor) -> Self {
4✔
139
        Self {
4✔
140
            data_type: value.data_type.into(),
4✔
141
            spatial_reference: value.spatial_reference.into(),
4✔
142
            columns: value
4✔
143
                .columns
4✔
144
                .into_iter()
4✔
145
                .map(|(key, value)| (key, value.into()))
20✔
146
                .collect(),
4✔
147
            time: value.time.map(Into::into),
4✔
148
            bbox: value.bbox.map(Into::into),
4✔
149
        }
4✔
150
    }
4✔
151
}
152

153
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ToSchema)]
105✔
154
#[serde(rename_all = "camelCase")]
155
pub struct VectorColumnInfo {
156
    pub data_type: FeatureDataType,
157
    pub measurement: Measurement,
158
}
159

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

169
impl From<VectorColumnInfo> for geoengine_operators::engine::VectorColumnInfo {
170
    fn from(value: VectorColumnInfo) -> Self {
20✔
171
        Self {
20✔
172
            data_type: value.data_type.into(),
20✔
173
            measurement: value.measurement.into(),
20✔
174
        }
20✔
175
    }
20✔
176
}
177

178
/// A `ResultDescriptor` for plot queries
179
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
2✔
180
#[serde(rename_all = "camelCase")]
181
pub struct PlotResultDescriptor {
182
    #[schema(value_type = String)]
183
    pub spatial_reference: SpatialReferenceOption,
184
    pub time: Option<TimeInterval>,
185
    pub bbox: Option<BoundingBox2D>,
186
}
187

188
impl From<geoengine_operators::engine::PlotResultDescriptor> for PlotResultDescriptor {
189
    fn from(value: geoengine_operators::engine::PlotResultDescriptor) -> Self {
×
190
        Self {
×
191
            spatial_reference: value.spatial_reference.into(),
×
192
            time: value.time.map(Into::into),
×
193
            bbox: value.bbox.map(Into::into),
×
194
        }
×
195
    }
×
196
}
197

198
impl From<PlotResultDescriptor> for geoengine_operators::engine::PlotResultDescriptor {
199
    fn from(value: PlotResultDescriptor) -> Self {
×
200
        Self {
×
201
            spatial_reference: value.spatial_reference.into(),
×
202
            time: value.time.map(Into::into),
×
203
            bbox: value.bbox.map(Into::into),
×
204
        }
×
205
    }
×
206
}
207

208
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
2✔
209
#[serde(rename_all = "camelCase", tag = "type")]
210
pub enum TypedResultDescriptor {
211
    Plot(PlotResultDescriptor),
212
    Raster(RasterResultDescriptor),
213
    Vector(VectorResultDescriptor),
214
}
215

216
impl From<geoengine_operators::engine::TypedResultDescriptor> for TypedResultDescriptor {
217
    fn from(value: geoengine_operators::engine::TypedResultDescriptor) -> Self {
×
218
        match value {
×
219
            geoengine_operators::engine::TypedResultDescriptor::Plot(p) => Self::Plot(p.into()),
×
220
            geoengine_operators::engine::TypedResultDescriptor::Raster(r) => Self::Raster(r.into()),
×
221
            geoengine_operators::engine::TypedResultDescriptor::Vector(v) => Self::Vector(v.into()),
×
222
        }
223
    }
×
224
}
225

226
impl From<geoengine_operators::engine::PlotResultDescriptor> for TypedResultDescriptor {
227
    fn from(value: geoengine_operators::engine::PlotResultDescriptor) -> Self {
×
228
        Self::Plot(value.into())
×
229
    }
×
230
}
231

232
impl From<PlotResultDescriptor> for TypedResultDescriptor {
233
    fn from(value: PlotResultDescriptor) -> Self {
×
234
        Self::Plot(value)
×
235
    }
×
236
}
237

238
impl From<geoengine_operators::engine::RasterResultDescriptor> for TypedResultDescriptor {
239
    fn from(value: geoengine_operators::engine::RasterResultDescriptor) -> Self {
×
240
        Self::Raster(value.into())
×
241
    }
×
242
}
243

244
impl From<RasterResultDescriptor> for TypedResultDescriptor {
245
    fn from(value: RasterResultDescriptor) -> Self {
×
246
        Self::Raster(value)
×
247
    }
×
248
}
249

250
impl From<geoengine_operators::engine::VectorResultDescriptor> for TypedResultDescriptor {
251
    fn from(value: geoengine_operators::engine::VectorResultDescriptor) -> Self {
×
252
        Self::Vector(value.into())
×
253
    }
×
254
}
255

256
impl From<VectorResultDescriptor> for TypedResultDescriptor {
257
    fn from(value: VectorResultDescriptor) -> Self {
×
258
        Self::Vector(value)
×
259
    }
×
260
}
261

262
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize, ToSchema)]
2✔
263
pub struct MockDatasetDataSourceLoadingInfo {
264
    pub points: Vec<Coordinate2D>,
265
}
266

267
impl From<geoengine_operators::mock::MockDatasetDataSourceLoadingInfo>
268
    for MockDatasetDataSourceLoadingInfo
269
{
270
    fn from(value: geoengine_operators::mock::MockDatasetDataSourceLoadingInfo) -> Self {
×
271
        Self {
×
272
            points: value.points.into_iter().map(Into::into).collect(),
×
273
        }
×
274
    }
×
275
}
276

277
impl From<MockDatasetDataSourceLoadingInfo>
278
    for geoengine_operators::mock::MockDatasetDataSourceLoadingInfo
279
{
280
    fn from(value: MockDatasetDataSourceLoadingInfo) -> Self {
×
281
        Self {
×
282
            points: value.points.into_iter().map(Into::into).collect(),
×
283
        }
×
284
    }
×
285
}
286

287
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, ToSchema)]
30✔
288
#[aliases(
289
    MockMetaData = StaticMetaData<MockDatasetDataSourceLoadingInfo, VectorResultDescriptor, VectorQueryRectangle>,
290
    OgrMetaData = StaticMetaData<OgrSourceDataset, VectorResultDescriptor, VectorQueryRectangle>
291
)]
292
#[serde(rename_all = "camelCase")]
293
pub struct StaticMetaData<L, R, Q> {
294
    pub loading_info: L,
295
    pub result_descriptor: R,
296
    #[serde(skip)]
297
    pub phantom: PhantomData<Q>,
298
}
299

300
impl
301
    From<
302
        geoengine_operators::engine::StaticMetaData<
303
            geoengine_operators::mock::MockDatasetDataSourceLoadingInfo,
304
            geoengine_operators::engine::VectorResultDescriptor,
305
            geoengine_datatypes::primitives::QueryRectangle<
306
                geoengine_datatypes::primitives::BoundingBox2D,
307
            >,
308
        >,
309
    >
310
    for StaticMetaData<
311
        MockDatasetDataSourceLoadingInfo,
312
        VectorResultDescriptor,
313
        QueryRectangle<BoundingBox2D>,
314
    >
315
{
316
    fn from(
×
317
        value: geoengine_operators::engine::StaticMetaData<
×
318
            geoengine_operators::mock::MockDatasetDataSourceLoadingInfo,
×
319
            geoengine_operators::engine::VectorResultDescriptor,
×
320
            geoengine_datatypes::primitives::QueryRectangle<
×
321
                geoengine_datatypes::primitives::BoundingBox2D,
×
322
            >,
×
323
        >,
×
324
    ) -> Self {
×
325
        Self {
×
326
            loading_info: value.loading_info.into(),
×
327
            result_descriptor: value.result_descriptor.into(),
×
328
            phantom: Default::default(),
×
329
        }
×
330
    }
×
331
}
332

333
impl
334
    From<
335
        geoengine_operators::engine::StaticMetaData<
336
            geoengine_operators::source::OgrSourceDataset,
337
            geoengine_operators::engine::VectorResultDescriptor,
338
            geoengine_datatypes::primitives::QueryRectangle<
339
                geoengine_datatypes::primitives::BoundingBox2D,
340
            >,
341
        >,
342
    > for StaticMetaData<OgrSourceDataset, VectorResultDescriptor, QueryRectangle<BoundingBox2D>>
343
{
344
    fn from(
1✔
345
        value: geoengine_operators::engine::StaticMetaData<
1✔
346
            geoengine_operators::source::OgrSourceDataset,
1✔
347
            geoengine_operators::engine::VectorResultDescriptor,
1✔
348
            geoengine_datatypes::primitives::QueryRectangle<
1✔
349
                geoengine_datatypes::primitives::BoundingBox2D,
1✔
350
            >,
1✔
351
        >,
1✔
352
    ) -> Self {
1✔
353
        Self {
1✔
354
            loading_info: value.loading_info.into(),
1✔
355
            result_descriptor: value.result_descriptor.into(),
1✔
356
            phantom: Default::default(),
1✔
357
        }
1✔
358
    }
1✔
359
}
360

361
#[async_trait]
362
impl<L, R, Q> MetaData<L, R, Q> for StaticMetaData<L, R, Q>
363
where
364
    L: Debug + Clone + Send + Sync + 'static,
365
    R: Debug + Send + Sync + 'static + ResultDescriptor,
366
    Q: Debug + Clone + Send + Sync + 'static,
367
{
368
    async fn loading_info(&self, _query: Q) -> geoengine_operators::util::Result<L> {
×
369
        Ok(self.loading_info.clone())
×
370
    }
×
371

372
    async fn result_descriptor(&self) -> geoengine_operators::util::Result<R> {
×
373
        Ok(self.result_descriptor.clone())
×
374
    }
×
375

376
    fn box_clone(&self) -> Box<dyn MetaData<L, R, Q>> {
×
377
        Box::new(self.clone())
×
378
    }
×
379
}
380

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

399
impl From<OgrMetaData>
400
    for geoengine_operators::engine::StaticMetaData<
401
        geoengine_operators::source::OgrSourceDataset,
402
        geoengine_operators::engine::VectorResultDescriptor,
403
        geoengine_datatypes::primitives::QueryRectangle<
404
            geoengine_datatypes::primitives::BoundingBox2D,
405
        >,
406
    >
407
{
408
    fn from(value: OgrMetaData) -> Self {
4✔
409
        Self {
4✔
410
            loading_info: value.loading_info.into(),
4✔
411
            result_descriptor: value.result_descriptor.into(),
4✔
412
            phantom: Default::default(),
4✔
413
        }
4✔
414
    }
4✔
415
}
416

417
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
2✔
418
#[serde(rename_all = "camelCase")]
419
pub struct GdalMetaDataStatic {
420
    pub time: Option<TimeInterval>,
421
    pub params: GdalDatasetParameters,
422
    pub result_descriptor: RasterResultDescriptor,
423
    #[serde(default)]
424
    pub cache_ttl: CacheTtlSeconds,
425
}
426

427
impl From<geoengine_operators::source::GdalMetaDataStatic> for GdalMetaDataStatic {
428
    fn from(value: geoengine_operators::source::GdalMetaDataStatic) -> Self {
×
429
        Self {
×
430
            time: value.time.map(Into::into),
×
431
            params: value.params.into(),
×
432
            result_descriptor: value.result_descriptor.into(),
×
433
            cache_ttl: value.cache_ttl.into(),
×
434
        }
×
435
    }
×
436
}
437

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

449
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, ToSchema)]
90✔
450
#[serde(rename_all = "camelCase")]
451
pub struct OgrSourceDataset {
452
    #[schema(value_type = String)]
453
    pub file_name: PathBuf,
454
    pub layer_name: String,
455
    pub data_type: Option<VectorDataType>,
456
    #[serde(default)]
457
    pub time: OgrSourceDatasetTimeType,
458
    pub default_geometry: Option<TypedGeometry>,
459
    pub columns: Option<OgrSourceColumnSpec>,
460
    #[serde(default)]
461
    pub force_ogr_time_filter: bool,
462
    #[serde(default)]
463
    pub force_ogr_spatial_filter: bool,
464
    pub on_error: OgrSourceErrorSpec,
465
    pub sql_query: Option<String>,
466
    pub attribute_query: Option<String>,
467
    #[serde(default)]
468
    pub cache_ttl: CacheTtlSeconds,
469
}
470

471
impl From<geoengine_operators::source::OgrSourceDataset> for OgrSourceDataset {
472
    fn from(value: geoengine_operators::source::OgrSourceDataset) -> Self {
1✔
473
        Self {
1✔
474
            file_name: value.file_name,
1✔
475
            layer_name: value.layer_name,
1✔
476
            data_type: value.data_type.map(Into::into),
1✔
477
            time: value.time.into(),
1✔
478
            default_geometry: value.default_geometry.map(Into::into),
1✔
479
            columns: value.columns.map(Into::into),
1✔
480
            force_ogr_time_filter: value.force_ogr_time_filter,
1✔
481
            force_ogr_spatial_filter: value.force_ogr_spatial_filter,
1✔
482
            on_error: value.on_error.into(),
1✔
483
            sql_query: value.sql_query,
1✔
484
            attribute_query: value.attribute_query,
1✔
485
            cache_ttl: value.cache_ttl.into(),
1✔
486
        }
1✔
487
    }
1✔
488
}
489

490
impl From<OgrSourceDataset> for geoengine_operators::source::OgrSourceDataset {
491
    fn from(value: OgrSourceDataset) -> Self {
4✔
492
        Self {
4✔
493
            file_name: value.file_name,
4✔
494
            layer_name: value.layer_name,
4✔
495
            data_type: value.data_type.map(Into::into),
4✔
496
            time: value.time.into(),
4✔
497
            default_geometry: value.default_geometry.map(Into::into),
4✔
498
            columns: value.columns.map(Into::into),
4✔
499
            force_ogr_time_filter: value.force_ogr_time_filter,
4✔
500
            force_ogr_spatial_filter: value.force_ogr_spatial_filter,
4✔
501
            on_error: value.on_error.into(),
4✔
502
            sql_query: value.sql_query,
4✔
503
            attribute_query: value.attribute_query,
4✔
504
            cache_ttl: value.cache_ttl.into(),
4✔
505
        }
4✔
506
    }
4✔
507
}
508

509
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug, ToSchema)]
2✔
510
#[serde(tag = "format")]
511
#[serde(rename_all = "camelCase")]
512
pub enum OgrSourceTimeFormat {
513
    #[serde(rename_all = "camelCase")]
514
    Custom {
515
        custom_format: DateTimeParseFormat,
516
    },
517
    #[serde(rename_all = "camelCase")]
518
    UnixTimeStamp {
519
        timestamp_type: UnixTimeStampType,
520
        #[serde(skip)]
521
        #[serde(default = "DateTimeParseFormat::unix")]
522
        fmt: DateTimeParseFormat,
523
    },
524
    Auto,
525
}
526

527
impl From<geoengine_operators::source::OgrSourceTimeFormat> for OgrSourceTimeFormat {
528
    fn from(value: geoengine_operators::source::OgrSourceTimeFormat) -> Self {
×
529
        match value {
×
530
            geoengine_operators::source::OgrSourceTimeFormat::Custom { custom_format } => {
×
531
                Self::Custom {
×
532
                    custom_format: custom_format.into(),
×
533
                }
×
534
            }
535
            geoengine_operators::source::OgrSourceTimeFormat::UnixTimeStamp {
536
                timestamp_type,
×
537
                fmt,
×
538
            } => Self::UnixTimeStamp {
×
539
                timestamp_type: timestamp_type.into(),
×
540
                fmt: fmt.into(),
×
541
            },
×
542
            geoengine_operators::source::OgrSourceTimeFormat::Auto => Self::Auto,
×
543
        }
544
    }
×
545
}
546

547
impl From<OgrSourceTimeFormat> for geoengine_operators::source::OgrSourceTimeFormat {
548
    fn from(value: OgrSourceTimeFormat) -> Self {
×
549
        match value {
×
550
            OgrSourceTimeFormat::Custom { custom_format } => Self::Custom {
×
551
                custom_format: custom_format.into(),
×
552
            },
×
553
            OgrSourceTimeFormat::UnixTimeStamp {
554
                timestamp_type,
×
555
                fmt,
×
556
            } => Self::UnixTimeStamp {
×
557
                timestamp_type: timestamp_type.into(),
×
558
                fmt: fmt.into(),
×
559
            },
×
560
            OgrSourceTimeFormat::Auto => Self::Auto,
×
561
        }
562
    }
×
563
}
564

565
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
2✔
566
#[serde(rename_all = "camelCase")]
567
pub enum UnixTimeStampType {
568
    EpochSeconds,
569
    EpochMilliseconds,
570
}
571

572
impl From<geoengine_operators::source::UnixTimeStampType> for UnixTimeStampType {
573
    fn from(value: geoengine_operators::source::UnixTimeStampType) -> Self {
×
574
        match value {
×
575
            geoengine_operators::source::UnixTimeStampType::EpochSeconds => Self::EpochSeconds,
×
576
            geoengine_operators::source::UnixTimeStampType::EpochMilliseconds => {
577
                Self::EpochMilliseconds
×
578
            }
579
        }
580
    }
×
581
}
582

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

592
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
12✔
593
#[serde(rename_all = "lowercase")]
594
pub enum OgrSourceErrorSpec {
595
    Ignore,
596
    Abort,
597
}
598

599
impl From<geoengine_operators::source::OgrSourceErrorSpec> for OgrSourceErrorSpec {
600
    fn from(value: geoengine_operators::source::OgrSourceErrorSpec) -> Self {
1✔
601
        match value {
1✔
602
            geoengine_operators::source::OgrSourceErrorSpec::Ignore => Self::Ignore,
1✔
603
            geoengine_operators::source::OgrSourceErrorSpec::Abort => Self::Abort,
×
604
        }
605
    }
1✔
606
}
607

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

617
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, ToSchema)]
12✔
618
#[serde(rename_all = "camelCase", tag = "type")]
619
pub enum OgrSourceDatasetTimeType {
620
    None,
621
    #[serde(rename_all = "camelCase")]
622
    Start {
623
        start_field: String,
624
        start_format: OgrSourceTimeFormat,
625
        duration: OgrSourceDurationSpec,
626
    },
627
    #[serde(rename_all = "camelCase")]
628
    StartEnd {
629
        start_field: String,
630
        start_format: OgrSourceTimeFormat,
631
        end_field: String,
632
        end_format: OgrSourceTimeFormat,
633
    },
634
    #[serde(rename_all = "camelCase")]
635
    StartDuration {
636
        start_field: String,
637
        start_format: OgrSourceTimeFormat,
638
        duration_field: String,
639
    },
640
}
641

642
impl From<geoengine_operators::source::OgrSourceDatasetTimeType> for OgrSourceDatasetTimeType {
643
    fn from(value: geoengine_operators::source::OgrSourceDatasetTimeType) -> Self {
1✔
644
        match value {
1✔
645
            geoengine_operators::source::OgrSourceDatasetTimeType::None => Self::None,
1✔
646
            geoengine_operators::source::OgrSourceDatasetTimeType::Start {
647
                start_field,
×
648
                start_format,
×
649
                duration,
×
650
            } => Self::Start {
×
651
                start_field,
×
652
                start_format: start_format.into(),
×
653
                duration: duration.into(),
×
654
            },
×
655
            geoengine_operators::source::OgrSourceDatasetTimeType::StartEnd {
656
                start_field,
×
657
                start_format,
×
658
                end_field,
×
659
                end_format,
×
660
            } => Self::StartEnd {
×
661
                start_field,
×
662
                start_format: start_format.into(),
×
663
                end_field,
×
664
                end_format: end_format.into(),
×
665
            },
×
666
            geoengine_operators::source::OgrSourceDatasetTimeType::StartDuration {
667
                start_field,
×
668
                start_format,
×
669
                duration_field,
×
670
            } => Self::StartDuration {
×
671
                start_field,
×
672
                start_format: start_format.into(),
×
673
                duration_field,
×
674
            },
×
675
        }
676
    }
1✔
677
}
678

679
impl From<OgrSourceDatasetTimeType> for geoengine_operators::source::OgrSourceDatasetTimeType {
680
    fn from(value: OgrSourceDatasetTimeType) -> Self {
4✔
681
        match value {
4✔
682
            OgrSourceDatasetTimeType::None => Self::None,
4✔
683
            OgrSourceDatasetTimeType::Start {
684
                start_field,
×
685
                start_format,
×
686
                duration,
×
687
            } => Self::Start {
×
688
                start_field,
×
689
                start_format: start_format.into(),
×
690
                duration: duration.into(),
×
691
            },
×
692
            OgrSourceDatasetTimeType::StartEnd {
693
                start_field,
×
694
                start_format,
×
695
                end_field,
×
696
                end_format,
×
697
            } => Self::StartEnd {
×
698
                start_field,
×
699
                start_format: start_format.into(),
×
700
                end_field,
×
701
                end_format: end_format.into(),
×
702
            },
×
703
            OgrSourceDatasetTimeType::StartDuration {
704
                start_field,
×
705
                start_format,
×
706
                duration_field,
×
707
            } => Self::StartDuration {
×
708
                start_field,
×
709
                start_format: start_format.into(),
×
710
                duration_field,
×
711
            },
×
712
        }
713
    }
4✔
714
}
715

716
/// If no time is specified, expect to parse none
717
impl Default for OgrSourceDatasetTimeType {
718
    fn default() -> Self {
×
719
        Self::None
×
720
    }
×
721
}
722

723
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
2✔
724
#[serde(rename_all = "camelCase", tag = "type")]
725
pub enum OgrSourceDurationSpec {
726
    Infinite,
727
    Zero,
728
    Value(TimeStep),
729
}
730

731
impl From<geoengine_operators::source::OgrSourceDurationSpec> for OgrSourceDurationSpec {
732
    fn from(value: geoengine_operators::source::OgrSourceDurationSpec) -> Self {
×
733
        match value {
×
734
            geoengine_operators::source::OgrSourceDurationSpec::Infinite => Self::Infinite,
×
735
            geoengine_operators::source::OgrSourceDurationSpec::Zero => Self::Zero,
×
736
            geoengine_operators::source::OgrSourceDurationSpec::Value(v) => Self::Value(v.into()),
×
737
        }
738
    }
×
739
}
740

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

751
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema)]
2✔
752
pub enum TypedGeometry {
753
    Data(NoGeometry),
754
    MultiPoint(MultiPoint),
755
    MultiLineString(MultiLineString),
756
    MultiPolygon(MultiPolygon),
757
}
758

759
impl From<geoengine_datatypes::primitives::TypedGeometry> for TypedGeometry {
760
    fn from(value: geoengine_datatypes::primitives::TypedGeometry) -> Self {
×
761
        match value {
×
762
            geoengine_datatypes::primitives::TypedGeometry::Data(x) => Self::Data(x.into()),
×
763
            geoengine_datatypes::primitives::TypedGeometry::MultiPoint(x) => {
×
764
                Self::MultiPoint(x.into())
×
765
            }
766
            geoengine_datatypes::primitives::TypedGeometry::MultiLineString(x) => {
×
767
                Self::MultiLineString(x.into())
×
768
            }
769
            geoengine_datatypes::primitives::TypedGeometry::MultiPolygon(x) => {
×
770
                Self::MultiPolygon(x.into())
×
771
            }
772
        }
773
    }
×
774
}
775

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

787
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
86✔
788
#[serde(rename_all = "camelCase")]
789
pub struct OgrSourceColumnSpec {
790
    pub format_specifics: Option<FormatSpecifics>,
791
    pub x: String,
792
    pub y: Option<String>,
793
    #[serde(default)]
794
    pub int: Vec<String>,
795
    #[serde(default)]
796
    pub float: Vec<String>,
797
    #[serde(default)]
798
    pub text: Vec<String>,
799
    #[serde(default)]
800
    pub bool: Vec<String>,
801
    #[serde(default)]
802
    pub datetime: Vec<String>,
803
    pub rename: Option<HashMap<String, String>>,
804
}
805

806
impl From<geoengine_operators::source::OgrSourceColumnSpec> for OgrSourceColumnSpec {
807
    fn from(value: geoengine_operators::source::OgrSourceColumnSpec) -> Self {
1✔
808
        Self {
1✔
809
            format_specifics: value.format_specifics.map(Into::into),
1✔
810
            x: value.x,
1✔
811
            y: value.y,
1✔
812
            int: value.int,
1✔
813
            float: value.float,
1✔
814
            text: value.text,
1✔
815
            bool: value.bool,
1✔
816
            datetime: value.datetime,
1✔
817
            rename: value.rename,
1✔
818
        }
1✔
819
    }
1✔
820
}
821

822
impl From<OgrSourceColumnSpec> for geoengine_operators::source::OgrSourceColumnSpec {
823
    fn from(value: OgrSourceColumnSpec) -> Self {
4✔
824
        Self {
4✔
825
            format_specifics: value.format_specifics.map(Into::into),
4✔
826
            x: value.x,
4✔
827
            y: value.y,
4✔
828
            int: value.int,
4✔
829
            float: value.float,
4✔
830
            text: value.text,
4✔
831
            bool: value.bool,
4✔
832
            datetime: value.datetime,
4✔
833
            rename: value.rename,
4✔
834
        }
4✔
835
    }
4✔
836
}
837

838
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema, PartialEq)]
52✔
839
#[serde(rename_all = "camelCase")]
840
pub struct GdalMetaDataRegular {
841
    pub result_descriptor: RasterResultDescriptor,
842
    pub params: GdalDatasetParameters,
843
    pub time_placeholders: HashMap<String, GdalSourceTimePlaceholder>,
844
    pub data_time: TimeInterval,
845
    pub step: TimeStep,
846
    #[serde(default)]
847
    pub cache_ttl: CacheTtlSeconds,
848
}
849

850
impl From<geoengine_operators::source::GdalMetaDataRegular> for GdalMetaDataRegular {
851
    fn from(value: geoengine_operators::source::GdalMetaDataRegular) -> Self {
4✔
852
        Self {
4✔
853
            result_descriptor: value.result_descriptor.into(),
4✔
854
            params: value.params.into(),
4✔
855
            time_placeholders: value
4✔
856
                .time_placeholders
4✔
857
                .into_iter()
4✔
858
                .map(|(k, v)| (k, v.into()))
4✔
859
                .collect(),
4✔
860
            data_time: value.data_time.into(),
4✔
861
            step: value.step.into(),
4✔
862
            cache_ttl: value.cache_ttl.into(),
4✔
863
        }
4✔
864
    }
4✔
865
}
866

867
impl From<GdalMetaDataRegular> for geoengine_operators::source::GdalMetaDataRegular {
868
    fn from(value: GdalMetaDataRegular) -> Self {
4✔
869
        Self {
4✔
870
            result_descriptor: value.result_descriptor.into(),
4✔
871
            params: value.params.into(),
4✔
872
            time_placeholders: value
4✔
873
                .time_placeholders
4✔
874
                .into_iter()
4✔
875
                .map(|(k, v)| (k, v.into()))
4✔
876
                .collect(),
4✔
877
            data_time: value.data_time.into(),
4✔
878
            step: value.step.into(),
4✔
879
            cache_ttl: value.cache_ttl.into(),
4✔
880
        }
4✔
881
    }
4✔
882
}
883

884
/// Parameters for loading data using Gdal
885
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
96✔
886
#[serde(rename_all = "camelCase")]
887
pub struct GdalDatasetParameters {
888
    #[schema(value_type = String)]
889
    pub file_path: PathBuf,
890
    pub rasterband_channel: usize,
891
    pub geo_transform: GdalDatasetGeoTransform, // TODO: discuss if we need this at all
892
    pub width: usize,
893
    pub height: usize,
894
    pub file_not_found_handling: FileNotFoundHandling,
895
    #[serde(with = "float_option_with_nan")]
896
    #[serde(default)]
897
    pub no_data_value: Option<f64>,
898
    pub properties_mapping: Option<Vec<GdalMetadataMapping>>,
899
    // Dataset open option as strings, e.g. `vec!["UserPwd=geoengine:pwd".to_owned(), "HttpAuth=BASIC".to_owned()]`
900
    pub gdal_open_options: Option<Vec<String>>,
901
    // Configs as key, value pairs that will be set as thread local config options, e.g.
902
    // `vec!["AWS_REGION".to_owned(), "eu-central-1".to_owned()]` and unset afterwards
903
    // TODO: validate the config options: only allow specific keys and specific values
904
    pub gdal_config_options: Option<Vec<GdalConfigOption>>,
905
    #[serde(default)]
906
    pub allow_alphaband_as_mask: bool,
907
}
908

909
impl From<geoengine_operators::source::GdalDatasetParameters> for GdalDatasetParameters {
910
    fn from(value: geoengine_operators::source::GdalDatasetParameters) -> Self {
4✔
911
        Self {
4✔
912
            file_path: value.file_path,
4✔
913
            rasterband_channel: value.rasterband_channel,
4✔
914
            geo_transform: value.geo_transform.into(),
4✔
915
            width: value.width,
4✔
916
            height: value.height,
4✔
917
            file_not_found_handling: value.file_not_found_handling.into(),
4✔
918
            no_data_value: value.no_data_value,
4✔
919
            properties_mapping: value
4✔
920
                .properties_mapping
4✔
921
                .map(|x| x.into_iter().map(Into::into).collect()),
4✔
922
            gdal_open_options: value.gdal_open_options,
4✔
923
            gdal_config_options: value
4✔
924
                .gdal_config_options
4✔
925
                .map(|x| x.into_iter().map(Into::into).collect()),
4✔
926
            allow_alphaband_as_mask: value.allow_alphaband_as_mask,
4✔
927
        }
4✔
928
    }
4✔
929
}
930

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

954
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, ToSchema)]
20✔
955
pub struct GdalSourceTimePlaceholder {
956
    pub format: DateTimeParseFormat,
957
    pub reference: TimeReference,
958
}
959

960
impl From<geoengine_operators::source::GdalSourceTimePlaceholder> for GdalSourceTimePlaceholder {
961
    fn from(value: geoengine_operators::source::GdalSourceTimePlaceholder) -> Self {
4✔
962
        Self {
4✔
963
            format: value.format.into(),
4✔
964
            reference: value.reference.into(),
4✔
965
        }
4✔
966
    }
4✔
967
}
968

969
impl From<GdalSourceTimePlaceholder> for geoengine_operators::source::GdalSourceTimePlaceholder {
970
    fn from(value: GdalSourceTimePlaceholder) -> Self {
4✔
971
        Self {
4✔
972
            format: value.format.into(),
4✔
973
            reference: value.reference.into(),
4✔
974
        }
4✔
975
    }
4✔
976
}
977

978
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, ToSchema)]
28✔
979
#[serde(rename_all = "camelCase")]
980
pub struct GdalDatasetGeoTransform {
981
    pub origin_coordinate: Coordinate2D,
982
    pub x_pixel_size: f64,
983
    pub y_pixel_size: f64,
984
}
985

986
impl From<geoengine_operators::source::GdalDatasetGeoTransform> for GdalDatasetGeoTransform {
987
    fn from(value: geoengine_operators::source::GdalDatasetGeoTransform) -> Self {
4✔
988
        Self {
4✔
989
            origin_coordinate: value.origin_coordinate.into(),
4✔
990
            x_pixel_size: value.x_pixel_size,
4✔
991
            y_pixel_size: value.y_pixel_size,
4✔
992
        }
4✔
993
    }
4✔
994
}
995

996
impl From<GdalDatasetGeoTransform> for geoengine_operators::source::GdalDatasetGeoTransform {
997
    fn from(value: GdalDatasetGeoTransform) -> Self {
4✔
998
        Self {
4✔
999
            origin_coordinate: value.origin_coordinate.into(),
4✔
1000
            x_pixel_size: value.x_pixel_size,
4✔
1001
            y_pixel_size: value.y_pixel_size,
4✔
1002
        }
4✔
1003
    }
4✔
1004
}
1005

1006
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, ToSchema)]
8✔
1007
pub enum FileNotFoundHandling {
1008
    NoData, // output tiles filled with nodata
1009
    Error,  // return error tile
1010
}
1011

1012
impl From<geoengine_operators::source::FileNotFoundHandling> for FileNotFoundHandling {
1013
    fn from(value: geoengine_operators::source::FileNotFoundHandling) -> Self {
4✔
1014
        match value {
4✔
1015
            geoengine_operators::source::FileNotFoundHandling::NoData => Self::NoData,
4✔
1016
            geoengine_operators::source::FileNotFoundHandling::Error => Self::Error,
×
1017
        }
1018
    }
4✔
1019
}
1020

1021
impl From<FileNotFoundHandling> for geoengine_operators::source::FileNotFoundHandling {
1022
    fn from(value: FileNotFoundHandling) -> Self {
4✔
1023
        match value {
4✔
1024
            FileNotFoundHandling::NoData => Self::NoData,
4✔
1025
            FileNotFoundHandling::Error => Self::Error,
×
1026
        }
1027
    }
4✔
1028
}
1029

1030
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
2✔
1031
pub struct GdalMetadataMapping {
1032
    pub source_key: RasterPropertiesKey,
1033
    pub target_key: RasterPropertiesKey,
1034
    pub target_type: RasterPropertiesEntryType,
1035
}
1036

1037
impl From<geoengine_operators::source::GdalMetadataMapping> for GdalMetadataMapping {
1038
    fn from(value: geoengine_operators::source::GdalMetadataMapping) -> Self {
×
1039
        Self {
×
1040
            source_key: value.source_key.into(),
×
1041
            target_key: value.target_key.into(),
×
1042
            target_type: value.target_type.into(),
×
1043
        }
×
1044
    }
×
1045
}
1046

1047
impl From<GdalMetadataMapping> for geoengine_operators::source::GdalMetadataMapping {
1048
    fn from(value: GdalMetadataMapping) -> Self {
×
1049
        Self {
×
1050
            source_key: value.source_key.into(),
×
1051
            target_key: value.target_key.into(),
×
1052
            target_type: value.target_type.into(),
×
1053
        }
×
1054
    }
×
1055
}
1056

1057
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
8✔
1058
#[serde(rename_all = "camelCase")]
1059
pub enum TimeReference {
1060
    Start,
1061
    End,
1062
}
1063

1064
impl From<geoengine_operators::source::TimeReference> for TimeReference {
1065
    fn from(value: geoengine_operators::source::TimeReference) -> Self {
4✔
1066
        match value {
4✔
1067
            geoengine_operators::source::TimeReference::Start => Self::Start,
4✔
1068
            geoengine_operators::source::TimeReference::End => Self::End,
×
1069
        }
1070
    }
4✔
1071
}
1072

1073
impl From<TimeReference> for geoengine_operators::source::TimeReference {
1074
    fn from(value: TimeReference) -> Self {
4✔
1075
        match value {
4✔
1076
            TimeReference::Start => Self::Start,
4✔
1077
            TimeReference::End => Self::End,
×
1078
        }
1079
    }
4✔
1080
}
1081

1082
/// Meta data for 4D `NetCDF` CF datasets
1083
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
2✔
1084
#[serde(rename_all = "camelCase")]
1085
pub struct GdalMetadataNetCdfCf {
1086
    pub result_descriptor: RasterResultDescriptor,
1087
    pub params: GdalDatasetParameters,
1088
    pub start: TimeInstance,
1089
    /// We use the end to specify the last, non-inclusive valid time point.
1090
    /// Queries behind this point return no data.
1091
    /// TODO: Alternatively, we could think about using the number of possible time steps in the future.
1092
    pub end: TimeInstance,
1093
    pub step: TimeStep,
1094
    /// A band offset specifies the first band index to use for the first point in time.
1095
    /// All other time steps are added to this offset.
1096
    pub band_offset: usize,
1097
    #[serde(default)]
1098
    pub cache_ttl: CacheTtlSeconds,
1099
}
1100

1101
impl From<geoengine_operators::source::GdalMetadataNetCdfCf> for GdalMetadataNetCdfCf {
1102
    fn from(value: geoengine_operators::source::GdalMetadataNetCdfCf) -> Self {
×
1103
        Self {
×
1104
            result_descriptor: value.result_descriptor.into(),
×
1105
            params: value.params.into(),
×
1106
            start: value.start.into(),
×
1107
            end: value.end.into(),
×
1108
            step: value.step.into(),
×
1109
            band_offset: value.band_offset,
×
1110
            cache_ttl: value.cache_ttl.into(),
×
1111
        }
×
1112
    }
×
1113
}
1114

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

1129
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
2✔
1130
#[serde(rename_all = "camelCase")]
1131
pub struct GdalMetaDataList {
1132
    pub result_descriptor: RasterResultDescriptor,
1133
    pub params: Vec<GdalLoadingInfoTemporalSlice>,
1134
}
1135

1136
impl From<geoengine_operators::source::GdalMetaDataList> for GdalMetaDataList {
1137
    fn from(value: geoengine_operators::source::GdalMetaDataList) -> Self {
×
1138
        Self {
×
1139
            result_descriptor: value.result_descriptor.into(),
×
1140
            params: value.params.into_iter().map(Into::into).collect(),
×
1141
        }
×
1142
    }
×
1143
}
1144

1145
impl From<GdalMetaDataList> for geoengine_operators::source::GdalMetaDataList {
1146
    fn from(value: GdalMetaDataList) -> Self {
×
1147
        Self {
×
1148
            result_descriptor: value.result_descriptor.into(),
×
1149
            params: value.params.into_iter().map(Into::into).collect(),
×
1150
        }
×
1151
    }
×
1152
}
1153

1154
/// one temporal slice of the dataset that requires reading from exactly one Gdal dataset
1155
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone, ToSchema)]
2✔
1156
#[serde(rename_all = "camelCase")]
1157
pub struct GdalLoadingInfoTemporalSlice {
1158
    pub time: TimeInterval,
1159
    pub params: Option<GdalDatasetParameters>,
1160
    #[serde(default)]
1161
    pub cache_ttl: CacheTtlSeconds,
1162
}
1163

1164
impl From<geoengine_operators::source::GdalLoadingInfoTemporalSlice>
1165
    for GdalLoadingInfoTemporalSlice
1166
{
1167
    fn from(value: geoengine_operators::source::GdalLoadingInfoTemporalSlice) -> Self {
×
1168
        Self {
×
1169
            time: value.time.into(),
×
1170
            params: value.params.map(Into::into),
×
1171
            cache_ttl: value.cache_ttl.into(),
×
1172
        }
×
1173
    }
×
1174
}
1175

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

1188
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
2✔
1189
#[serde(rename_all = "lowercase")]
1190
pub enum CsvHeader {
1191
    Yes,
1192
    No,
1193
    Auto,
1194
}
1195

1196
impl From<geoengine_operators::source::CsvHeader> for CsvHeader {
1197
    fn from(value: geoengine_operators::source::CsvHeader) -> Self {
×
1198
        match value {
×
1199
            geoengine_operators::source::CsvHeader::Yes => Self::Yes,
×
1200
            geoengine_operators::source::CsvHeader::No => Self::No,
×
1201
            geoengine_operators::source::CsvHeader::Auto => Self::Auto,
×
1202
        }
1203
    }
×
1204
}
1205

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

1216
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ToSchema)]
2✔
1217
#[serde(rename_all = "camelCase")]
1218
pub enum FormatSpecifics {
1219
    Csv { header: CsvHeader },
1220
}
1221

1222
impl From<geoengine_operators::source::FormatSpecifics> for FormatSpecifics {
1223
    fn from(value: geoengine_operators::source::FormatSpecifics) -> Self {
×
1224
        match value {
×
1225
            geoengine_operators::source::FormatSpecifics::Csv { header } => Self::Csv {
×
1226
                header: header.into(),
×
1227
            },
×
1228
        }
×
1229
    }
×
1230
}
1231

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