Skip to main content

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!(
61            get_at(document.clone(), &["name"])
62                .expect("should find name")
63                .is_str()
64        );
65        assert!(
66            get_at(document.clone(), &["application", "redis"])
67                .expect("should find application.redis")
68                .is_table()
69        );
70        assert!(
71            get_at(document.clone(), &["application", "redis", "trigger"])
72                .expect("should find application.redis.trigger")
73                .is_table()
74        );
75        assert!(
76            get_at(document.clone(), &["trigger", "redis"])
77                .expect("should find trigger.redis.channel")
78                .is_array()
79        );
80    }
81}