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

geo-engine / geoengine / 12915178431

22 Jan 2025 07:00PM UTC coverage: 90.037% (-0.02%) from 90.061%
12915178431

Pull #1007

github

web-flow
Merge ae013e750 into df8c694c8
Pull Request #1007: Add ml permissions

30 of 71 new or added lines in 5 files covered. (42.25%)

72 existing lines in 7 files now uncovered.

127252 of 141333 relevant lines covered (90.04%)

56954.61 hits per line

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

13.64
/datatypes/src/machine_learning.rs
1
use std::path::PathBuf;
2

3
use serde::{de::Visitor, Deserialize, Serialize};
4

5
use crate::{
6
    dataset::{is_invalid_name_char, SYSTEM_NAMESPACE},
7
    raster::RasterDataType,
8
};
9

10
const NAME_DELIMITER: char = ':';
11

12
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
13
pub struct MlModelName {
14
    pub namespace: Option<String>,
15
    pub name: String,
16
}
17

18
impl MlModelName {
19
    /// Canonicalize a name that reflects the system namespace and model.
20
    fn canonicalize<S: Into<String> + PartialEq<&'static str>>(
×
21
        name: S,
×
22
        system_name: &'static str,
×
23
    ) -> Option<String> {
×
24
        if name == system_name {
×
25
            None
×
26
        } else {
27
            Some(name.into())
×
28
        }
29
    }
×
30

UNCOV
31
    pub fn new<S: Into<String>>(namespace: Option<String>, name: S) -> Self {
×
UNCOV
32
        Self {
×
33
            namespace,
×
34
            name: name.into(),
×
35
        }
×
36
    }
×
37
}
38

39
impl Serialize for MlModelName {
40
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2✔
41
    where
2✔
42
        S: serde::Serializer,
2✔
43
    {
2✔
44
        let d = NAME_DELIMITER;
2✔
45
        let serialized = match (&self.namespace, &self.name) {
2✔
46
            (None, name) => name.to_string(),
2✔
47
            (Some(namespace), name) => {
×
48
                format!("{namespace}{d}{name}")
×
49
            }
50
        };
51

52
        serializer.serialize_str(&serialized)
2✔
53
    }
2✔
54
}
55

56
impl<'de> Deserialize<'de> for MlModelName {
UNCOV
57
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
×
UNCOV
58
    where
×
UNCOV
59
        D: serde::Deserializer<'de>,
×
60
    {
×
61
        deserializer.deserialize_str(MlModelNameDeserializeVisitor)
×
UNCOV
62
    }
×
63
}
64

65
struct MlModelNameDeserializeVisitor;
66

67
impl Visitor<'_> for MlModelNameDeserializeVisitor {
68
    type Value = MlModelName;
69

70
    /// always keep in sync with [`is_allowed_name_char`]
71
    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
×
72
        write!(
×
73
            formatter,
×
74
            "a string consisting of a namespace and name name, separated by a colon, only using alphanumeric characters, underscores & dashes"
×
75
        )
×
UNCOV
76
    }
×
77

78
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
×
79
    where
×
80
        E: serde::de::Error,
×
81
    {
×
82
        let mut strings = [None, None];
×
83
        let mut split = s.split(NAME_DELIMITER);
×
84

85
        for (buffer, part) in strings.iter_mut().zip(&mut split) {
×
86
            if part.is_empty() {
×
87
                return Err(E::custom("empty part in named data"));
×
88
            }
×
89

90
            if let Some(c) = part.matches(is_invalid_name_char).next() {
×
91
                return Err(E::custom(format!("invalid character '{c}' in named model")));
×
92
            }
×
93

×
94
            *buffer = Some(part.to_string());
×
95
        }
96

UNCOV
97
        if split.next().is_some() {
×
UNCOV
98
            return Err(E::custom("named model must consist of at most two parts"));
×
99
        }
×
100

101
        match strings {
×
UNCOV
102
            [Some(namespace), Some(name)] => Ok(MlModelName {
×
103
                namespace: MlModelName::canonicalize(namespace, SYSTEM_NAMESPACE),
×
104
                name,
×
105
            }),
×
106
            [Some(name), None] => Ok(MlModelName {
×
107
                namespace: None,
×
108
                name,
×
109
            }),
×
110
            _ => Err(E::custom("empty named data")),
×
111
        }
112
    }
×
113
}
114

115
// For now we assume all models are pixel-wise, i.e., they take a single pixel with multiple bands as input and produce a single output value.
116
// To support different inputs, we would need a more sophisticated logic to produce the inputs for the model.
117
#[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize, Serialize)]
118
pub struct MlModelMetadata {
119
    pub file_path: PathBuf,
120
    pub input_type: RasterDataType,
121
    pub num_input_bands: u32, // number of features per sample (bands per pixel)
122
    pub output_type: RasterDataType, // TODO: support multiple outputs, e.g. one band for the probability of prediction
123
                                     // TODO: output measurement, e.g. classification or regression, label names for classification. This would have to be provided by the model creator along the model file as it cannot be extracted from the model file(?)
124
}
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