argser/
lib.rs

1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4use std::collections::HashMap;
5
6pub use argser_macros::argser;
7
8pub mod provider;
9
10mod traits;
11pub use traits::*;
12
13/// The Error returned when attempting to Parse the Arguments
14#[derive(Debug, PartialEq)]
15pub enum ParseError {
16    /// Some Paramether was missing
17    MissingParam {
18        /// The Name of the Missing-Parameter
19        name: String,
20    },
21    /// This indicates that there was no Data to be used for parsing
22    MissingValue,
23    /// This simply indicates that the supplied value was malformed/in an
24    /// incorrect format
25    InvalidValue,
26    /// Some Custom-Error returned by custom implementations for [`ParseFromArgs`]
27    Custom(String),
28}
29
30/// Defines the interface that needs to be implemented by Argument-Providers,
31/// this enables users to source the arguments that should be used from
32/// different Parts, like CLI-Args, Environment-Variables, etc.
33pub trait ArgProvider {
34    /// Get the list of Argument-Pairs from the given Argument-Provider
35    fn get_args(&self) -> Vec<(String, String)>;
36}
37
38// TODO
39// Support command structures like -test.{name}.test
40// struct Cli {
41//   test: HashMap<String, SubCategory>,
42// }
43// struct SubCategory {
44//   test: String,
45// }
46
47/// This will load all the Arguments from the given Providers and then attempt
48/// to parse an instance of `T` from that Collection of Arguments
49pub fn parse_args_from_providers<T>(providers: &[&dyn ArgProvider]) -> Result<T, ParseError>
50where
51    T: FromArgs,
52{
53    let all_args: HashMap<String, Vec<String>> = {
54        let mut tmp: HashMap<String, Vec<String>> = HashMap::new();
55        for inner_vec in providers.iter().map(|p| p.get_args()) {
56            for (key, value) in inner_vec {
57                match tmp.get_mut(&key) {
58                    Some(previous) => {
59                        previous.push(value);
60                    }
61                    None => {
62                        tmp.insert(key, vec![value]);
63                    }
64                };
65            }
66        }
67        tmp
68    };
69
70    T::parse(all_args)
71}
72
73/// This is a simple Wrapper for [`parse_args_from_providers`] that
74/// automatically uses the [`Cli`](provider::Cli) ArgProvider to collect
75/// Arguments and then Parse them
76pub fn parse_cli<T>() -> Result<T, ParseError>
77where
78    T: FromArgs,
79{
80    let cli = provider::Cli::new();
81
82    parse_args_from_providers(&[&cli])
83}