mddd_std/
cli_params.rs

1#[derive(Debug)]
2pub enum CliParamsError {
3    TooManyValues,
4    KeyRequiresValue,
5}
6
7pub struct CliParams<'a> {
8    params: Vec<&'a str>,
9}
10
11impl<'a> CliParams<'a> {
12    pub fn new(params: Vec<&'a str>) -> Self {
13        Self { params }
14    }
15
16    pub fn pop_bool_flag(
17        &mut self,
18        short: Option<&str>,
19        long: Option<&str>,
20    ) -> Result<bool, CliParamsError> {
21        let indexes = self.get_key_indexes(short, long);
22        match indexes.len() {
23            0 => Ok(false),
24            1 => {
25                self.params.remove(indexes[0]);
26                Ok(true)
27            }
28            _ => Err(CliParamsError::TooManyValues),
29        }
30    }
31
32    pub fn pop_key_value(
33        &mut self,
34        short: Option<&str>,
35        long: Option<&str>,
36    ) -> Result<Option<&'a str>, CliParamsError> {
37        let indexes = self.get_key_indexes(short, long);
38        match indexes.len() {
39            0 => Ok(None),
40            1 if indexes[0] == self.params.len() - 1 => Err(CliParamsError::KeyRequiresValue),
41            1 => {
42                let index = indexes[0];
43                let val = self.params.remove(index + 1);
44                self.params.remove(index);
45                Ok(Some(val))
46            }
47            _ => Err(CliParamsError::TooManyValues),
48        }
49    }
50
51    pub fn pop_key_values(
52        &mut self,
53        short: Option<&str>,
54        long: Option<&str>,
55    ) -> Result<Vec<&'a str>, CliParamsError> {
56        let indexes = self.get_key_indexes(short, long);
57        if indexes.is_empty() {
58            return Ok(Vec::new());
59        }
60        if indexes.last().unwrap() + 1 == self.params.len() {
61            return Err(CliParamsError::KeyRequiresValue);
62        }
63        let mut result = Vec::new();
64        for index in indexes.into_iter().rev() {
65            result.push(self.params.remove(index + 1));
66            self.params.remove(index);
67        }
68        result.reverse();
69        Ok(result)
70    }
71
72    pub fn pop_position_value(&mut self) -> Option<&'a str> {
73        if self.params.is_empty() {
74            return None;
75        }
76        Some(self.params.remove(0))
77    }
78
79    pub fn pop_position_values(&mut self) -> Vec<&'a str> {
80        std::mem::take(&mut self.params)
81    }
82
83    fn get_key_indexes(&self, short: Option<&str>, long: Option<&str>) -> Vec<usize> {
84        let mut result = Vec::new();
85        for (i, key) in self.params.iter().enumerate() {
86            if short == Some(key) || long == Some(key) {
87                result.push(i);
88            }
89        }
90        result
91    }
92}