Skip to main content

ruclif_parser_clap/string/
impls.rs

1use clap::{Arg, ArgMatches};
2use ruclif_core::{
3    builder::{Builder, HasBuilder},
4    common::IntoFrom,
5};
6
7use crate::{
8    string::{builder_state, error_message, StringClapArg, StringClapArgBuilder, StringClapArgData, ValueParserFunc},
9    ClapArgData,
10};
11
12impl HasBuilder for StringClapArg {
13    type Builder = StringClapArgBuilder;
14
15    fn builder() -> Self::Builder {
16        StringClapArgBuilder::default()
17    }
18}
19
20impl StringClapArgBuilder {
21    pub fn name(mut self, name: &'static str) -> Self {
22        self.name = Some(name);
23        self.state |= builder_state::NAME as u8;
24        self
25    }
26
27    pub fn short(mut self, short: char) -> Self {
28        self.short = Some(short);
29        self.state |= builder_state::SHORT as u8;
30        self
31    }
32
33    pub fn long(mut self, long: &'static str) -> Self {
34        self.long = Some(long);
35        self.state |= builder_state::LONG as u8;
36        self
37    }
38
39    pub fn description(mut self, description: &'static str) -> Self {
40        self.description = Some(description);
41        self.state |= builder_state::DESCRIPTION as u8;
42        self
43    }
44
45    pub fn default_value(mut self, default_value: &'static str) -> Self {
46        self.default_value = Some(default_value);
47        self
48    }
49
50    pub fn value_parser(mut self, value_parser: ValueParserFunc) -> Self {
51        self.value_parser = Some(value_parser);
52        self
53    }
54}
55
56impl StringClapArgBuilder {
57    fn is_name_set(&self) -> bool {
58        self.state & builder_state::NAME as u8 != 0
59    }
60
61    fn is_short_set(&self) -> bool {
62        self.state & builder_state::SHORT as u8 != 0
63    }
64
65    fn is_long_set(&self) -> bool {
66        self.state & builder_state::LONG as u8 != 0
67    }
68
69    fn is_description_set(&self) -> bool {
70        self.state & builder_state::DESCRIPTION as u8 != 0
71    }
72}
73
74impl Builder for StringClapArgBuilder {
75    type Result = StringClapArg;
76
77    fn build(self) -> Result<StringClapArg, String> {
78        if self.state != builder_state::EXPECTED {
79            let map = [
80                ("name", !self.is_name_set()),
81                ("short", !self.is_short_set()),
82                ("long", !self.is_long_set()),
83                ("description", !self.is_description_set()),
84            ];
85
86            let missing_fields: Vec<&str> = map.iter().filter_map(|entry| entry.1.then_some(entry.0)).collect();
87
88            Err(error_message::MANDATORY_FIELDS_MISSING.replace("{fields}", &missing_fields.join(", ")))
89        } else {
90            let data = StringClapArgData {
91                common: ClapArgData {
92                    name: self.name.unwrap(),
93                    short: self.short.unwrap(),
94                    long: self.long.unwrap(),
95                    description: self.description.unwrap(),
96                },
97                default_value: self.default_value,
98                value_parser: self.value_parser,
99            };
100
101            Ok(StringClapArg { data })
102        }
103    }
104}
105
106impl StringClapArg {
107    fn name(&self) -> &'static str {
108        self.data.common.name
109    }
110
111    fn short(&self) -> char {
112        self.data.common.short
113    }
114
115    fn long(&self) -> &'static str {
116        self.data.common.long
117    }
118
119    fn description(&self) -> &'static str {
120        self.data.common.description
121    }
122
123    fn default_value(&self) -> Option<&'static str> {
124        self.data.default_value
125    }
126
127    fn value_parser(&self) -> Option<ValueParserFunc> {
128        self.data.value_parser
129    }
130}
131
132impl From<&StringClapArg> for Arg {
133    fn from(arg: &StringClapArg) -> Self {
134        let mut result = Self::new(arg.name())
135            .short(arg.short())
136            .long(arg.long())
137            .help(arg.description());
138
139        if let Some(default_value) = arg.default_value() {
140            result = result.default_value(default_value);
141        }
142        if let Some(value_parser) = arg.value_parser() {
143            result = result.value_parser(value_parser);
144        }
145
146        result
147    }
148}
149
150impl IntoFrom<&ArgMatches, String> for StringClapArg {
151    fn into_from(self, parsing_result: &ArgMatches) -> String {
152        parsing_result.get_one::<String>(self.name()).unwrap().to_owned()
153    }
154}