spin_templates/
toml.rs

1pub(crate) fn get_at<S: AsRef<str>>(value: toml::Value, path: &[S]) -> Option<toml::Value> {
2    match path.split_first() {
3        None => Some(value), // we are at the end of the path and we have a thing
4        Some((first, rest)) => {
5            match value.as_table() {
6                None => None, // we need to key into it and we can't
7                Some(t) => {
8                    match t.get(first.as_ref()) {
9                        None => None,                       // we tried to key into it and no match
10                        Some(v) => get_at(v.clone(), rest), // we pathed into it! keep pathing
11                    }
12                }
13            }
14        }
15    }
16}
17
18#[cfg(test)]
19mod test {
20    use super::*;
21
22    #[test]
23    fn if_path_does_not_exist_then_get_at_is_none() {
24        let document: toml::Value = toml::toml! {
25            name = "test"
26
27            [application.redis.trigger]
28            address = "test-address"
29
30            [[trigger.redis]]
31            channel = "messages"
32        }
33        .into();
34
35        assert!(get_at(document.clone(), &["name", "snort"]).is_none());
36        assert!(get_at(document.clone(), &["snort", "fie"]).is_none());
37        assert!(get_at(document.clone(), &["application", "snort"]).is_none());
38        assert!(get_at(document.clone(), &["application", "redis", "snort"]).is_none());
39        assert!(get_at(document.clone(), &["trigger", "redis", "snort"]).is_none());
40
41        // We have not yet needed to define a behaviour for seeking into table arrays, but
42        // presumably it will need some sort of disambiguation for array element.
43        // For now, we assume that eithout disambiguation it will report no result.
44        assert!(get_at(document.clone(), &["trigger", "redis", "channel"]).is_none());
45    }
46
47    #[test]
48    fn if_path_does_exist_then_get_at_finds_it() {
49        let document: toml::Value = toml::toml! {
50            name = "test"
51
52            [application.redis.trigger]
53            address = "test-address"
54
55            [[trigger.redis]]
56            channel = "messages"
57        }
58        .into();
59
60        assert!(get_at(document.clone(), &["name"])
61            .expect("should find name")
62            .is_str());
63        assert!(get_at(document.clone(), &["application", "redis"])
64            .expect("should find application.redis")
65            .is_table());
66        assert!(
67            get_at(document.clone(), &["application", "redis", "trigger"])
68                .expect("should find application.redis.trigger")
69                .is_table()
70        );
71        assert!(get_at(document.clone(), &["trigger", "redis"])
72            .expect("should find trigger.redis.channel")
73            .is_array());
74    }
75}