trivial_argument_parser/argument/
legacy_argument.rs

1use std::iter::Peekable;
2
3/**
4Enum allowing to choose the type of argument.
5*/
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub enum ArgType {
8    Flag,
9    Value,
10    ValueList,
11}
12
13/**
14ArgResult enum is similar to ArgType enum but contains data generated through parsing
15*/
16#[derive(Debug, PartialEq)]
17pub enum ArgResult {
18    Flag,
19    Value(String),
20    ValueList(Vec<String>),
21}
22
23///
24/// Argument struct allows to specify type of expected argument, its names and after parsing contains results.
25/// This is the legacy method of defining arguments. Currently using ParsableValueArgument is preffered.
26///
27/// # Examples
28/// ```
29/// use trivial_argument_parser::argument::legacy_argument::*;
30/// let mut example_argument = Argument::new(Some('l'), Some("an-list"), ArgType::ValueList).unwrap();
31/// ```
32
33#[derive(Debug)]
34pub struct Argument {
35    short: Option<char>,
36    long: Option<String>,
37    arg_type: ArgType,
38    pub arg_result: Option<ArgResult>,
39}
40
41impl Argument {
42    /**
43    Create new Argument. You need to specify at least one name (short or long) or you can specify both. Parameter arg_type changes how the parsing will treat the argument.
44    */
45    pub fn new(
46        short: Option<char>,
47        long: Option<&str>,
48        arg_type: ArgType,
49    ) -> Result<Argument, String> {
50        // Check if at least 1 name is specified
51        if let (Option::None, Option::None) = (short, long) {
52            return Err(String::from(
53                "At least one name of argument must be specified (short or long or both)",
54            ));
55        }
56
57        // Check if long name is defined, if so use it
58        let long_owned: Option<String> = if let Some(text) = long {
59            Option::Some(String::from(text))
60        } else {
61            None
62        };
63
64        Ok(Argument {
65            short,
66            long: long_owned,
67            arg_type,
68            arg_result: None,
69        })
70    }
71
72    pub fn new_short(name: char, arg_type: ArgType) -> Argument {
73        Argument::new(Option::Some(name), Option::None, arg_type).unwrap()
74    }
75
76    pub fn new_long(name: &str, arg_type: ArgType) -> Argument {
77        Argument::new(Option::None, Option::Some(name), arg_type).unwrap()
78    }
79
80    ///
81    /// Method allowing to simplify reading values of a single value type arguments.
82    ///
83    ///# Examples
84    ///```
85    /// use trivial_argument_parser::argument::legacy_argument::*;
86    /// use trivial_argument_parser::ArgumentList;
87    /// let mut args_list = ArgumentList::new();
88    /// args_list.append_arg(Argument::new(Some('v'), None, ArgType::Value).unwrap());
89    /// args_list.parse_args(vec![String::from("-v"), String::from("VALUE")]).unwrap();
90    /// let value = args_list.search_by_short_name('v').unwrap().get_value().unwrap();
91    /// println!("Value: {}", value);
92    ///```
93
94    pub fn get_value(&self) -> Result<&str, &'static str> {
95        if let ArgType::Value = self.arg_type {
96            if let Some(result) = &self.arg_result {
97                if let ArgResult::Value(ref value) = result {
98                    return Ok(value);
99                } else {
100                    return Err("Wrong type of result. Something really bad has happened");
101                }
102            } else {
103                return Err("No value assigned to result");
104            }
105        } else {
106            return Err("This argument is not an value");
107        }
108    }
109    ///
110    /// Method allowing to simplify reading values of a value list type argument.
111    ///
112    ///# Examples
113    ///```
114    /// use trivial_argument_parser::{argument::legacy_argument::*, ArgumentList};
115    /// let mut args_list = ArgumentList::new();
116    /// args_list.append_arg(Argument::new(Some('l'), None, ArgType::ValueList).unwrap());
117    /// args_list.parse_args(vec![String::from("-l"), String::from("cos")]).unwrap();
118    /// let list = args_list.search_by_short_name('l').unwrap().get_values().unwrap();
119    /// for e in list
120    /// {
121    ///     println!("Value: {}", e);
122    /// }
123    ///```
124
125    pub fn get_values(&self) -> Result<&Vec<String>, &'static str> {
126        if let ArgType::ValueList = self.arg_type {
127            if let Some(result) = &self.arg_result {
128                if let ArgResult::ValueList(ref list) = result {
129                    return Ok(list);
130                } else {
131                    return Err("Wrong type of result. Something really bad happened");
132                }
133            } else {
134                return Err("No result specified");
135            }
136        } else {
137            return Err("This argument is not an value list");
138        }
139    }
140
141    ///
142    /// Method allowing to simplify reading values of a flag type argument.
143    ///
144    ///# Examples
145    ///```
146    /// use trivial_argument_parser::{ArgumentList, args_to_string_vector, argument::legacy_argument::*};
147    /// let mut args_list = ArgumentList::new();
148    /// args_list.append_arg(Argument::new(Some('d'), None, ArgType::Flag).unwrap());
149    /// args_list.parse_args(args_to_string_vector(std::env::args())).unwrap();
150    /// if(args_list.search_by_short_name('d').unwrap().get_flag().unwrap())
151    /// {
152    ///     println!("Flag was set");
153    /// }
154    ///```
155
156    pub fn get_flag(&self) -> Result<bool, &'static str> {
157        if let ArgType::Flag = self.arg_type {
158            return Ok(if let Some(_) = self.arg_result {
159                true
160            } else {
161                false
162            });
163        } else {
164            return Err("Argument is not an flag type");
165        }
166    }
167
168    pub fn add_value(
169        &mut self,
170        input_iter: &mut Peekable<&mut std::slice::Iter<'_, String>>,
171    ) -> Result<(), String> {
172        match self.arg_type {
173            ArgType::Flag => {
174                match self.arg_result {
175                    Some(_) => return Err(String::from("Flag already set")),
176                    _ => (),
177                }
178                self.arg_result = Some(ArgResult::Flag);
179            }
180            ArgType::Value => {
181                match self.arg_result {
182                    Some(_) => return Err(String::from("Value already assigned")),
183                    _ => (),
184                }
185                match input_iter.next() {
186                    Some(word) => self.arg_result = Some(ArgResult::Value(String::from(word))),
187                    None => return Err(String::from("Expected value")),
188                }
189            }
190            ArgType::ValueList => {
191                let mut new_result = false;
192                match self.arg_result {
193                    Some(_) => (),
194                    None => new_result = true,
195                }
196
197                if new_result {
198                    self.arg_result = Some(ArgResult::ValueList(Vec::new()));
199                }
200
201                match input_iter.next() {
202                    Some(word) => match self.arg_result.as_mut().expect("as mut") {
203                        ArgResult::ValueList(ref mut values) => values.push(String::from(word)),
204                        _ => return Err(String::from("WTF")),
205                    },
206                    None => return Err(String::from("Expected value")),
207                }
208            }
209        }
210
211        Ok(())
212    }
213
214    pub fn short(&self) -> &Option<char> {
215        &self.short
216    }
217
218    pub fn long(&self) -> &Option<String> {
219        &self.long
220    }
221
222    pub fn arg_type(&self) -> &ArgType {
223        &self.arg_type
224    }
225}
226
227#[cfg(test)]
228mod test {
229    use std::borrow::BorrowMut;
230
231    use crate::argument::legacy_argument::{ArgType, Argument};
232
233    #[test]
234    fn new_works() {
235        assert!(Argument::new(Option::None, Option::Some("parameter"), ArgType::Flag).is_ok());
236        assert!(Argument::new(Option::Some('x'), Option::None, ArgType::Flag).is_ok());
237        assert!(Argument::new(Option::Some('x'), Option::Some("parameter"), ArgType::Flag).is_ok());
238    }
239
240    #[test]
241    fn new_fails() {
242        assert!(Argument::new(Option::None, Option::None, ArgType::Flag).is_err())
243    }
244
245    #[test]
246    fn value_works() {
247        let mut arg =
248            Argument::new(Option::None, Option::Some("parameter"), ArgType::Value).unwrap();
249        arg.add_value(
250            &mut vec![String::from("my value")]
251                .iter()
252                .borrow_mut()
253                .peekable(),
254        )
255        .unwrap();
256        let val = arg.get_value();
257        assert!(val.is_ok());
258        assert_eq!(val.unwrap(), "my value");
259    }
260
261    #[test]
262    fn value_fails_too_many_calls() {
263        let mut arg =
264            Argument::new(Option::None, Option::Some("parameter"), ArgType::Value).unwrap();
265        let inputs_vec = vec![String::from("my value"), String::from("second_value")];
266        let mut inputs_iter = inputs_vec.iter();
267        let mut inputs = inputs_iter.borrow_mut().peekable();
268        arg.add_value(&mut inputs).unwrap();
269        assert!(arg.add_value(&mut inputs).is_err());
270    }
271
272    #[test]
273    fn value_list_works() {
274        let mut arg =
275            Argument::new(Option::None, Option::Some("parameter"), ArgType::ValueList).unwrap();
276        let inputs_vec = vec![String::from("my value"), String::from("My second value")];
277        let mut inputs_iter = inputs_vec.iter();
278        let mut inputs = inputs_iter.borrow_mut().peekable();
279        arg.add_value(&mut inputs).unwrap();
280        arg.add_value(&mut inputs).unwrap();
281        let val = arg.get_values();
282        assert!(val.is_ok());
283        assert_eq!(val.unwrap().len(), 2);
284        assert_eq!(val.unwrap().get(0).unwrap(), "my value");
285        assert_eq!(val.unwrap().get(1).unwrap(), "My second value");
286    }
287
288    #[test]
289    fn flag_works() {
290        let mut arg =
291            Argument::new(Option::None, Option::Some("parameter"), ArgType::Flag).unwrap();
292        arg.add_value(
293            &mut vec![String::from("my value")]
294                .iter()
295                .borrow_mut()
296                .peekable(),
297        )
298        .unwrap();
299        let val = arg.get_flag();
300        assert!(val.is_ok());
301        assert_eq!(val.unwrap(), true);
302    }
303}