corosync_config_parser/
config.rs

1use std::iter;
2use std::slice;
3
4/// Represents a block in the config file or the document root
5#[derive(Debug, PartialEq, Eq)]
6pub struct ConfigBlock {
7    name: String,
8    params: Vec<String>,
9    inner: Vec<ConfigBlock>,
10}
11
12impl ConfigBlock {
13    pub fn new(name: String, params: Vec<String>, inner: Vec<ConfigBlock>) -> ConfigBlock {
14        ConfigBlock {
15            name: name,
16            params: params,
17            inner: inner,
18        }
19    }
20
21    /// Adds a new sub block. This probably isn't very useful for you
22    pub fn add_block(&mut self, block: ConfigBlock) {
23        self.inner.push(block);
24    }
25
26    /// Returns an iterator of all inner config options with the specified name
27    pub fn matching<'a>(&'a self, name: &'a str) -> ConfigIter<'a> {
28        ConfigIter {
29            it: self.inner.iter(),
30            name: name,
31        }
32    }
33
34    /// Returns the name of the option key
35    pub fn name(&self) -> &str {
36        &self.name
37    }
38
39    /// Returns all inner config options
40    pub fn inner<'a>(&'a self) -> &'a Vec<ConfigBlock> {
41        &self.inner
42    }
43
44    /// Returns the parameter count
45    pub fn len(&self) -> usize {
46        self.params.len()
47    }
48
49    /// Returns a parameter. Panics if the parameter index is too high
50    pub fn get(&self, i: usize) -> &str {
51        &self.params[i]
52    }
53
54    /// Returns a parameter. Returns None if the index is too high
55    pub fn get_opt(&self, i: usize) -> Option<&str> {
56        if i < self.params.len() {
57            Some(&self.params[i])
58        } else {
59            None
60        }
61    }
62
63    pub fn path<'a>(&'a self, keys: Vec<&'a str>) -> Option<&str> {
64        let last_config_block =
65            keys.iter()
66                .fold(Some(self), |accumulator, key| match accumulator {
67                    Some(config_block) => config_block.matching(key).nth(0),
68                    None => None,
69                });
70
71        match last_config_block {
72            Some(config_block) => Some(config_block.get(0)),
73            None => None,
74        }
75    }
76}
77
78pub struct ConfigIter<'a> {
79    it: slice::Iter<'a, ConfigBlock>,
80    name: &'a str,
81}
82
83impl<'a> iter::Iterator for ConfigIter<'a> {
84    type Item = &'a ConfigBlock;
85    fn next(&mut self) -> Option<&'a ConfigBlock> {
86        loop {
87            match self.it.next() {
88                Some(c) if c.name() == self.name => return Some(c),
89                Some(_) => {}
90                None => return None,
91            }
92        }
93    }
94
95    fn size_hint(&self) -> (usize, Option<usize>) {
96        (0, self.it.size_hint().1)
97    }
98}