rosu_map/util/
key_value.rs

1use std::str::FromStr;
2
3/// Auxiliary struct for parsing key-value pairs.
4pub struct KeyValue<'a, K> {
5    /// Should be of any type that implements [`FromStr`].
6    pub key: K,
7    /// The whitespace-trimmed content after the colon (`:`).
8    pub value: &'a str,
9}
10
11impl<'a, K: FromStr> KeyValue<'a, K> {
12    /// Create a new [`KeyValue`] pair by splitting on the first `:`
13    /// and parsing the key.
14    ///
15    /// # Example
16    ///
17    /// ```
18    /// use rosu_map::util::KeyValue;
19    /// use rosu_map::section::difficulty::DifficultyKey;
20    ///
21    /// let line = "ApproachRate: 9.3 // Some comment";
22    ///
23    /// let kv = KeyValue::<DifficultyKey>::parse(line).unwrap();
24    ///
25    /// assert_eq!(kv.key, DifficultyKey::ApproachRate);
26    /// assert_eq!(kv.value, "9.3 // Some comment");
27    /// ```
28    pub fn parse(s: &'a str) -> Result<Self, K::Err> {
29        let mut split = s.split(':').map(str::trim);
30
31        Ok(Self {
32            key: split.next().unwrap_or(s.trim()).parse()?,
33            value: split.next().unwrap_or_default(),
34        })
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[derive(Debug, PartialEq, Eq)]
43    struct Key;
44
45    impl FromStr for Key {
46        type Err = ();
47
48        fn from_str(s: &str) -> Result<Self, Self::Err> {
49            match s {
50                "key" => Ok(Self),
51                _ => Err(()),
52            }
53        }
54    }
55
56    #[test]
57    fn key_and_value() {
58        let kv = KeyValue::<Key>::parse("key:value").unwrap();
59        assert_eq!(kv.key, Key);
60        assert_eq!(kv.value, "value");
61
62        let kv = KeyValue::<Key>::parse("  key    :  value   ").unwrap();
63        assert_eq!(kv.key, Key);
64        assert_eq!(kv.value, "value");
65    }
66
67    #[test]
68    fn only_key() {
69        let kv = KeyValue::<Key>::parse("key:").unwrap();
70        assert_eq!(kv.key, Key);
71        assert_eq!(kv.value, "");
72
73        let kv = KeyValue::<Key>::parse("   key  :   ").unwrap();
74        assert_eq!(kv.key, Key);
75        assert_eq!(kv.value, "");
76    }
77
78    #[test]
79    fn only_value() {
80        assert!(KeyValue::<Key>::parse(":value").is_err());
81        assert!(KeyValue::<Key>::parse("  :  value     ").is_err());
82    }
83
84    #[test]
85    fn no_colon() {
86        assert!(KeyValue::<Key>::parse("key value").is_err());
87    }
88}