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}