1use crate::error::ValueError;
2use std::{collections::HashMap, str::FromStr};
3
4#[derive(Clone, Debug, PartialEq)]
5pub enum Value {
6 Single(String),
7 Multi(Vec<String>),
8 Flag(bool),
9}
10
11#[derive(Debug, PartialEq)]
12pub struct Matches {
13 exec_name: String,
14 positional: Vec<String>,
15 named: HashMap<String, Value>,
16}
17
18impl Matches {
19 pub fn new(exec_name: String, positional: Vec<String>, named: HashMap<String, Value>) -> Self {
20 Self {
21 exec_name,
22 positional,
23 named,
24 }
25 }
26
27 pub fn flag(&self, name: &str) -> Result<Option<bool>, ValueError> {
28 match self.named.get(name) {
29 Some(Value::Flag(b)) => Ok(Some(*b)),
30 Some(_) => Err(ValueError::WrongOptionType),
31 None => Ok(None),
32 }
33 }
34
35 pub fn one<T: FromStr>(&self, name: &str) -> Result<Option<T>, ValueError> {
36 match self.named.get(name) {
37 Some(Value::Single(val)) => {
38 let v = T::from_str(val.as_str())
39 .map_err(|_| ValueError::ConversionError(val.clone()))?;
40 Ok(Some(v))
41 }
42 Some(_) => Err(ValueError::WrongOptionType),
43 None => Ok(None),
44 }
45 }
46
47 pub fn all<T: FromStr>(&self, name: &str) -> Result<Vec<T>, ValueError> {
48 match self.named.get(name) {
49 Some(Value::Multi(val)) => {
50 let r: Result<Vec<T>, _> = val.iter().map(|v| T::from_str(v.as_str())).collect();
51 r.map_err(|_| ValueError::ConversionError(format!("{:?}", val)))
52 }
53 Some(_) => Err(ValueError::WrongOptionType),
54 None => Ok(vec![]),
55 }
56 }
57
58 pub fn positional(&self) -> &[String] {
59 &self.positional
60 }
61}