Skip to main content

hfx_core/
raster.rs

1//! Raster-related domain types.
2
3/// D8 flow direction encoding convention.
4///
5/// Declares which encoding convention a `flow_dir.tif` raster uses.
6/// The engine normalizes to its internal convention at read time.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum FlowDirEncoding {
9    /// ESRI convention: powers of 2 (1, 2, 4, 8, 16, 32, 64, 128).
10    Esri,
11    /// TauDEM convention: 1-8, east origin, counter-clockwise.
12    Taudem,
13}
14
15impl std::fmt::Display for FlowDirEncoding {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            FlowDirEncoding::Esri => write!(f, "esri"),
19            FlowDirEncoding::Taudem => write!(f, "taudem"),
20        }
21    }
22}
23
24/// Error returned when parsing an unknown flow direction encoding string.
25#[derive(Debug, thiserror::Error)]
26#[error("unknown flow direction encoding: {value:?}, expected \"esri\" or \"taudem\"")]
27pub struct FlowDirEncodingError {
28    /// The unrecognized string.
29    pub value: String,
30}
31
32impl std::str::FromStr for FlowDirEncoding {
33    type Err = FlowDirEncodingError;
34    fn from_str(s: &str) -> Result<Self, Self::Err> {
35        match s {
36            "esri" => Ok(FlowDirEncoding::Esri),
37            "taudem" => Ok(FlowDirEncoding::Taudem),
38            _ => Err(FlowDirEncodingError { value: s.to_owned() }),
39        }
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn flow_dir_encoding_variants_are_not_equal() {
49        assert_ne!(FlowDirEncoding::Esri, FlowDirEncoding::Taudem);
50    }
51
52    #[test]
53    fn flow_dir_encoding_clone_and_copy() {
54        let original = FlowDirEncoding::Esri;
55        let cloned = original.clone();
56        // Copy: bind by value into a second variable.
57        let copied = original;
58        assert_eq!(original, cloned);
59        assert_eq!(original, copied);
60    }
61
62    #[test]
63    fn flow_dir_encoding_usable_as_hash_map_key() {
64        use std::collections::HashMap;
65        let mut map: HashMap<FlowDirEncoding, &str> = HashMap::new();
66        map.insert(FlowDirEncoding::Esri, "esri");
67        map.insert(FlowDirEncoding::Taudem, "taudem");
68        assert_eq!(map[&FlowDirEncoding::Esri], "esri");
69        assert_eq!(map[&FlowDirEncoding::Taudem], "taudem");
70    }
71
72    #[test]
73    fn flow_dir_encoding_display() {
74        assert_eq!(FlowDirEncoding::Esri.to_string(), "esri");
75        assert_eq!(FlowDirEncoding::Taudem.to_string(), "taudem");
76    }
77
78    #[test]
79    fn flow_dir_encoding_fromstr_valid() {
80        assert_eq!("esri".parse::<FlowDirEncoding>().unwrap(), FlowDirEncoding::Esri);
81        assert_eq!("taudem".parse::<FlowDirEncoding>().unwrap(), FlowDirEncoding::Taudem);
82    }
83
84    #[test]
85    fn flow_dir_encoding_fromstr_invalid() {
86        assert!("invalid".parse::<FlowDirEncoding>().is_err());
87        assert!("ESRI".parse::<FlowDirEncoding>().is_err());
88    }
89}