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

geo-engine / geoengine / 24391614752

14 Apr 2026 09:30AM UTC coverage: 87.527% (+0.1%) from 87.39%
24391614752

push

github

web-flow
fix: openapi enum variant names (#1139)

* fix openapi enum variant names

* fix degenerated openapi enum names OneOf

263 of 267 new or added lines in 4 files covered. (98.5%)

6 existing lines in 3 files now uncovered.

114087 of 130345 relevant lines covered (87.53%)

496692.92 hits per line

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

97.76
/geoengine/services/src/api/model/processing_graphs/source.rs
1
use crate::api::model::{
2
    datatypes::Coordinate2D, processing_graphs::parameters::SpatialBoundsDerive,
3
};
4
use geoengine_datatypes::dataset::NamedData;
5
use geoengine_macros::{api_operator, type_tag};
6
use geoengine_operators::{
7
    mock::{
8
        MockPointSource as OperatorsMockPointSource,
9
        MockPointSourceParams as OperatorsMockPointSourceParameters,
10
    },
11
    source::{
12
        GdalSource as OperatorsGdalSource, GdalSourceParameters as OperatorsGdalSourceParameters,
13
        MultiBandGdalSource as OperatorsMultiBandGdalSource,
14
        MultiBandGdalSourceParameters as OperatorsMultiBandGdalSourceParameters,
15
        OgrSource as OperatorsOgrSource,
16
    },
17
};
18
use serde::{Deserialize, Serialize};
19
use utoipa::ToSchema;
20

21
/// The [`GdalSource`] is a source operator that reads raster data using GDAL.
22
/// The counterpart for vector data is the [`OgrSource`].
23
///
24
/// ## Errors
25
///
26
/// If the given dataset does not exist or is not readable, an error is thrown.
27
///
28
#[api_operator(
90✔
29
    title = "GDAL Source",
90✔
30
    examples(json!({
90✔
31
        "type": "GdalSource",
32
        "params": {
33
            "data": "ndvi",
34
            "overviewLevel": null
35
        }
36
    }))
37
)]
38
pub struct GdalSource {
39
    pub params: GdalSourceParameters,
40
}
41

42
/// Parameters for the [`GdalSource`] operator.
43
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
44
#[serde(rename_all = "camelCase")]
45
pub struct GdalSourceParameters {
46
    /// Dataset name or identifier to be loaded.
47
    #[schema(examples("ndvi"))]
48
    pub data: String,
49

50
    /// *Optional*: overview level to use.
51
    ///
52
    /// If not provided, the data source will determine the resolution, i.e., uses its native resolution.
53
    #[schema(examples(3))]
54
    pub overview_level: Option<u32>,
55
}
56

57
impl TryFrom<GdalSource> for OperatorsGdalSource {
58
    type Error = anyhow::Error;
59
    fn try_from(value: GdalSource) -> Result<Self, Self::Error> {
44✔
60
        Ok(OperatorsGdalSource {
61
            params: OperatorsGdalSourceParameters {
62
                data: serde_json::from_str::<NamedData>(&serde_json::to_string(
44✔
63
                    &value.params.data,
44✔
64
                )?)?,
×
65
                overview_level: value.params.overview_level,
44✔
66
            },
67
        })
68
    }
44✔
69
}
70

71
/// The [`MultiBandGdalSource`] is a source operator that reads multi-band raster data using GDAL.
72
#[api_operator(
90✔
73
    title = "Multi Band GDAL Source",
90✔
74
    examples(json!({
90✔
75
        "type": "MultiBandGdalSource",
76
        "params": {
77
            "data": "sentinel-2-l2a_EPSG32632_U16_10",
78
            "overviewLevel": null
79
        }
80
    }))
81
)]
82
pub struct MultiBandGdalSource {
83
    pub params: GdalSourceParameters,
84
}
85

86
impl TryFrom<MultiBandGdalSource> for OperatorsMultiBandGdalSource {
87
    type Error = anyhow::Error;
88

89
    fn try_from(value: MultiBandGdalSource) -> Result<Self, Self::Error> {
5✔
90
        Ok(OperatorsMultiBandGdalSource {
91
            params: OperatorsMultiBandGdalSourceParameters {
92
                data: serde_json::from_str::<NamedData>(&serde_json::to_string(
5✔
93
                    &value.params.data,
5✔
94
                )?)?,
×
95
                overview_level: value.params.overview_level,
5✔
96
            },
97
        })
98
    }
5✔
99
}
100

101
/// The [`MockPointSource`] is a source operator that provides mock vector point data for testing and development purposes.
102
///
103
#[api_operator(
90✔
104
    title = "Mock Point Source",
90✔
105
    examples(json!({
90✔
106
        "type": "MockPointSource",
107
        "params": {
108
            "points": [ { "x": 1.0, "y": 2.0 }, { "x": 3.0, "y": 4.0 } ],
109
            "spatialBounds": { "type": "derive" }
110
        }
111
    }))
112
)]
113
pub struct MockPointSource {
114
    pub params: MockPointSourceParameters,
115
}
116

117
/// Parameters for the [`MockPointSource`] operator.
118
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
119
#[serde(rename_all = "camelCase")]
120
pub struct MockPointSourceParameters {
121
    /// Points to be output by the mock point source.
122
    ///
123
    #[schema(examples(json!([
124
        { "x": 1.0, "y": 2.0 },
125
        { "x": 3.0, "y": 4.0 }
126
    ])))]
127
    pub points: Vec<Coordinate2D>,
128

129
    /// Defines how the spatial bounds of the source are derived.
130
    ///
131
    /// Defaults to `None`.
132
    #[schema(examples(json!({ "type": "derive" })))]
133
    pub spatial_bounds: SpatialBoundsDerive,
134
}
135

136
impl TryFrom<MockPointSource> for OperatorsMockPointSource {
137
    type Error = anyhow::Error;
138
    fn try_from(value: MockPointSource) -> Result<Self, Self::Error> {
9✔
139
        Ok(OperatorsMockPointSource {
140
            params: OperatorsMockPointSourceParameters {
141
                points: value.params.points.into_iter().map(Into::into).collect(),
9✔
142
                spatial_bounds: value.params.spatial_bounds.try_into()?,
9✔
143
            },
144
        })
145
    }
9✔
146
}
147

148
/// The [`OgrSource`] is a source operator that reads vector data using OGR (part of GDAL).
149
/// The counterpart for raster data is the [`GdalSource`].
150
///
151
/// ## Errors
152
///
153
/// If the given dataset does not exist or is not readable, an error is thrown.
154
///
155
#[api_operator(
90✔
156
    title = "OGR Source",
90✔
157
    examples(json!({
90✔
158
        "type": "OgrSource",
159
        "params": {
160
            "data": "ndvi"
161
        }
162
    }))
163
)]
164
pub struct OgrSource {
165
    pub params: OgrSourceParameters,
166
}
167

168
/// Parameters for the [`OgrSource`] operator.
169
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, ToSchema)]
170
#[serde(rename_all = "camelCase")]
171
pub struct OgrSourceParameters {
172
    /// Dataset name or identifier to be loaded.
173
    #[schema(examples("ndvi"))]
174
    pub data: String,
175

176
    /// *Optional*: list of attributes to include. When `None`, all attributes are included.
177
    pub attribute_projection: Option<Vec<String>>,
178
}
179

180
impl TryFrom<OgrSource> for OperatorsOgrSource {
181
    type Error = anyhow::Error;
182
    fn try_from(value: OgrSource) -> Result<Self, Self::Error> {
6✔
183
        Ok(OperatorsOgrSource {
184
            params: geoengine_operators::source::OgrSourceParameters {
185
                data: serde_json::from_str::<NamedData>(&serde_json::to_string(
6✔
186
                    &value.params.data,
6✔
NEW
187
                )?)?,
×
188
                attribute_projection: value.params.attribute_projection,
6✔
189
                attribute_filters: None,
6✔
190
            },
191
        })
192
    }
6✔
193
}
194

195
#[cfg(test)]
196
mod tests {
197
    use super::*;
198
    use crate::api::model::processing_graphs::{RasterOperator, TypedOperator, VectorOperator};
199
    use geoengine_operators::engine::TypedOperator as OperatorsTypedOperator;
200

201
    #[test]
202
    fn it_converts_into_gdal_source() {
1✔
203
        let api_operator = GdalSource {
1✔
204
            r#type: Default::default(),
1✔
205
            params: GdalSourceParameters {
1✔
206
                data: "example_dataset".to_string(),
1✔
207
                overview_level: None,
1✔
208
            },
1✔
209
        };
1✔
210

211
        let operators_operator: OperatorsGdalSource =
1✔
212
            api_operator.try_into().expect("it should convert");
1✔
213

214
        assert_eq!(
1✔
215
            operators_operator.params.data,
216
            NamedData::with_system_name("example_dataset")
1✔
217
        );
218

219
        let typed_operator = TypedOperator::Raster(RasterOperator::GdalSource(GdalSource {
1✔
220
            r#type: Default::default(),
1✔
221
            params: GdalSourceParameters {
1✔
222
                data: "example_dataset".to_string(),
1✔
223
                overview_level: None,
1✔
224
            },
1✔
225
        }));
1✔
226

227
        OperatorsTypedOperator::try_from(typed_operator).expect("it should convert");
1✔
228
    }
1✔
229

230
    #[test]
231
    fn it_converts_into_multi_band_gdal_source() {
1✔
232
        let api_operator = MultiBandGdalSource {
1✔
233
            r#type: Default::default(),
1✔
234
            params: GdalSourceParameters {
1✔
235
                data: "example_dataset".to_string(),
1✔
236
                overview_level: None,
1✔
237
            },
1✔
238
        };
1✔
239

240
        let operators_operator: OperatorsMultiBandGdalSource =
1✔
241
            api_operator.try_into().expect("it should convert");
1✔
242

243
        assert_eq!(
1✔
244
            operators_operator.params.data,
245
            NamedData::with_system_name("example_dataset")
1✔
246
        );
247

248
        let typed_operator =
1✔
249
            TypedOperator::Raster(RasterOperator::MultiBandGdalSource(MultiBandGdalSource {
1✔
250
                r#type: Default::default(),
1✔
251
                params: GdalSourceParameters {
1✔
252
                    data: "example_dataset".to_string(),
1✔
253
                    overview_level: None,
1✔
254
                },
1✔
255
            }));
1✔
256

257
        OperatorsTypedOperator::try_from(typed_operator).expect("it should convert");
1✔
258
    }
1✔
259

260
    #[test]
261
    fn it_converts_mock_point_source() {
1✔
262
        let api_operator = MockPointSource {
1✔
263
            r#type: Default::default(),
1✔
264
            params: MockPointSourceParameters {
1✔
265
                points: vec![
1✔
266
                    Coordinate2D { x: 1.0, y: 2.0 },
1✔
267
                    Coordinate2D { x: 3.0, y: 4.0 },
1✔
268
                ],
1✔
269
                spatial_bounds: SpatialBoundsDerive::Derive(Default::default()),
1✔
270
            },
1✔
271
        };
1✔
272

273
        let operators_operator: OperatorsMockPointSource =
1✔
274
            api_operator.try_into().expect("it should convert");
1✔
275

276
        assert_eq!(
1✔
277
            operators_operator.params.points,
278
            vec![
1✔
279
                geoengine_datatypes::primitives::Coordinate2D { x: 1.0, y: 2.0 },
1✔
280
                geoengine_datatypes::primitives::Coordinate2D { x: 3.0, y: 4.0 }
1✔
281
            ]
282
        );
283

284
        let typed_operator =
1✔
285
            TypedOperator::Vector(VectorOperator::MockPointSource(MockPointSource {
1✔
286
                r#type: Default::default(),
1✔
287
                params: MockPointSourceParameters {
1✔
288
                    points: vec![Coordinate2D { x: 1.0, y: 2.0 }],
1✔
289
                    spatial_bounds: SpatialBoundsDerive::Derive(Default::default()),
1✔
290
                },
1✔
291
            }));
1✔
292

293
        OperatorsTypedOperator::try_from(typed_operator).expect("it should convert");
1✔
294
    }
1✔
295

296
    #[test]
297
    fn it_parses_ogr_source_api_example() {
1✔
298
        let example = serde_json::json!({
1✔
299
            "type": "OgrSource",
1✔
300
            "params": {
1✔
301
                "data": "ndvi"
1✔
302
            }
303
        });
304

305
        let parsed: OgrSource = serde_json::from_value(example).expect("example must parse");
1✔
306

307
        assert_eq!(parsed.params.data, "ndvi");
1✔
308
    }
1✔
309

310
    #[test]
311
    fn it_converts_ogr_source() {
1✔
312
        let api_operator = OgrSource {
1✔
313
            r#type: Default::default(),
1✔
314
            params: OgrSourceParameters {
1✔
315
                data: "ndvi".to_string(),
1✔
316
                attribute_projection: None,
1✔
317
            },
1✔
318
        };
1✔
319

320
        let operators_operator: OperatorsOgrSource =
1✔
321
            api_operator.try_into().expect("it should convert");
1✔
322

323
        assert_eq!(
1✔
324
            operators_operator.params.data,
325
            NamedData::with_system_name("ndvi")
1✔
326
        );
327

328
        let typed_operator = TypedOperator::Vector(VectorOperator::OgrSource(OgrSource {
1✔
329
            r#type: Default::default(),
1✔
330
            params: OgrSourceParameters {
1✔
331
                data: "ndvi".to_string(),
1✔
332
                attribute_projection: None,
1✔
333
            },
1✔
334
        }));
1✔
335

336
        OperatorsTypedOperator::try_from(typed_operator).expect("it should convert");
1✔
337
    }
1✔
338
}
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