gitignore_template_generator/parser/
api.rs

1use std::ffi::OsString;
2
3use clap::ValueEnum;
4
5use crate::core::ProgramExit;
6pub use crate::parser::impls::ClapArgsParser;
7
8#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Default)]
9pub enum TimeoutUnit {
10    MILLISECOND,
11    #[default]
12    SECOND,
13}
14
15/// Struct to gather cli args parsing result.
16///
17/// Used by [`crate::parser::ArgsParser`] implementations to store
18/// parsing result.
19#[derive(Debug, PartialEq, Default)]
20pub struct Args {
21    /// A non-empty list of gitignore template names.
22    ///
23    /// * Represented by the provided positional arguments, and required
24    ///   unless any of `author`, `version` or `help` options are given.
25    /// * This field does not allow commas in any of its field.
26    pub template_names: Vec<String>,
27
28    /// The gitignore template generator service url.
29    ///
30    /// * Optional value represented by the cli option
31    ///   [`crate::constant::cli_options::SERVER_URL`] that takes a string
32    ///   value, and falling back to
33    ///   [`crate::constant::template_manager::BASE_URL`] if not provided
34    ///   in cli args.
35    pub server_url: String,
36
37    /// The gitignore template generator service endpoint uri.
38    ///
39    /// * Optional value represented by the cli option
40    ///   [`crate::constant::cli_options::GENERATOR_URI`] that takes a string
41    ///   value, and falling back to
42    ///   [`crate::constant::template_manager::GENERATOR_URI`] if not provided in cli
43    ///   args.
44    pub generator_uri: String,
45
46    /// The gitignore template lister service endpoint uri.
47    ///
48    /// * Optional value represented by the cli option
49    ///   [`crate::constant::cli_options::LISTER_URI`] that takes a string
50    ///   value, and falling back to
51    ///   [`crate::constant::template_manager::LISTER_URI`] if not provided in cli
52    ///   args.
53    pub lister_uri: String,
54
55    /// The boolean indicator of whether to display help infos or not.
56    ///
57    /// * Optional value represented by the cli option
58    ///   [`crate::constant::cli_options::HELP`], and falling back to `false`
59    ///   if not provided in cli args.
60    /// * Has precedence over version and author options if multiple are given
61    pub show_help: bool,
62
63    /// The boolean indicator of whether to display version infos or not.
64    ///
65    /// * Optional value represented by the cli option
66    ///   [`crate::constant::cli_options::VERSION`], and falling back to
67    ///   `false` if not provided in cli args.
68    /// * Has precedence over author option if multiple are given
69    pub show_version: bool,
70
71    /// The boolean indicator of whether to display author infos or not.
72    ///
73    /// * Optional value represented by the cli option
74    ///   [`crate::constant::cli_options::AUTHOR`], and falling back to
75    ///   `false` if not provided in cli args.
76    pub show_author: bool,
77
78    /// The boolean indicator of whether to display list of available templates
79    /// or not.
80    ///
81    /// * Optional value represented by the cli option
82    ///   [`crate::constant::cli_options::LIST`], and falling back to
83    ///   `false` if not provided in cli args.
84    pub show_list: bool,
85
86    /// The boolean indicator of whether to enable robust template check or not.
87    ///
88    /// Robust template check allow the script to handle template existence
89    /// check without reaching the generator endpoint.
90    ///
91    /// * Optional value represented by the cli option
92    ///   [`crate::constant::cli_options::CHECK`], and falling back to
93    ///   `false` if not provided in cli args.
94    pub check_template_names: bool,
95
96    /// The service call timeout.
97    ///
98    /// * Optional value represented by the cli option
99    ///   [`crate::constant::cli_options::TIMEOUT`], and falling back to
100    ///   [`crate::constant::template_manager::TIMEOUT`] if not provided in
101    ///   cli args.
102    pub timeout: u64,
103
104    /// The timeout unit.
105    ///
106    /// * Optional value represented by the cli option
107    ///   [`crate::constant::cli_options::TIMEOUT_UNIT`], and falling back to
108    ///   [`crate::constant::template_manager::TIMEOUT_UNIT`] if not provided in
109    ///   cli args.
110    pub timeout_unit: TimeoutUnit,
111}
112
113impl Args {
114    pub fn new() -> Self {
115        Self {
116            template_names: Vec::new(),
117            server_url: crate::constant::template_manager::BASE_URL.to_string(),
118            generator_uri: crate::constant::template_manager::GENERATOR_URI
119                .to_string(),
120            lister_uri: crate::constant::template_manager::LISTER_URI
121                .to_string(),
122            show_help: false,
123            show_version: false,
124            show_author: false,
125            show_list: false,
126            check_template_names: false,
127            timeout: crate::constant::template_manager::TIMEOUT_INT,
128            timeout_unit: crate::constant::template_manager::TIMEOUT_UNIT_ENUM,
129        }
130    }
131
132    /// Sets new value for `template_names` field.
133    ///
134    /// It needs to be called on struct instance and effectively mutates it.
135    ///
136    /// # Arguments
137    ///
138    /// * `template_names` - The new value to be assigned to `template_names`
139    ///   field.
140    ///
141    /// # Returns
142    ///
143    /// The mutated borrowed instance.
144    pub fn with_template_names(mut self, template_names: Vec<String>) -> Self {
145        self.template_names = template_names;
146        self
147    }
148
149    /// Sets new value for `server_url` field.
150    ///
151    /// It needs to be called on struct instance and effectively mutates it.
152    ///
153    /// # Arguments
154    ///
155    /// * `server_url` - The new value to be assigned to `server_url`
156    ///   field.
157    ///
158    /// # Returns
159    ///
160    /// The mutated borrowed instance.
161    pub fn with_server_url(mut self, server_url: &str) -> Self {
162        self.server_url = server_url.to_string();
163        self
164    }
165
166    /// Sets new value for `generator_uri` field.
167    ///
168    /// It needs to be called on struct instance and effectively mutates it.
169    ///
170    /// # Arguments
171    ///
172    /// * `generator_uri` - The new value to be assigned to
173    ///   `generator_uri` field.
174    ///
175    /// # Returns
176    ///
177    /// The mutated borrowed instance.
178    pub fn with_generator_uri(mut self, generator_uri: &str) -> Self {
179        self.generator_uri = generator_uri.to_string();
180        self
181    }
182
183    /// Sets new value for `lister_uri` field.
184    ///
185    /// It needs to be called on struct instance and effectively mutates it.
186    ///
187    /// # Arguments
188    ///
189    /// * `lister_uri` - The new value to be assigned to `lister_uri` field.
190    ///
191    /// # Returns
192    ///
193    /// The mutated borrowed instance.
194    pub fn with_lister_uri(mut self, lister_uri: &str) -> Self {
195        self.lister_uri = lister_uri.to_string();
196        self
197    }
198
199    /// Sets new value for `show_list` field.
200    ///
201    /// It needs to be called on struct instance and effectively mutates it.
202    ///
203    /// # Arguments
204    ///
205    /// * `show_list` - The new value to be assigned to `show_list`
206    ///   field.
207    ///
208    /// # Returns
209    ///
210    /// The mutated borrowed instance.
211    pub fn with_show_list(mut self, show_list: bool) -> Self {
212        self.show_list = show_list;
213        self
214    }
215
216    /// Sets new value for `check_template_names` field.
217    ///
218    /// It needs to be called on struct instance and effectively mutates it.
219    ///
220    /// # Arguments
221    ///
222    /// * `check_template_names` - The new value to be assigned to
223    ///   `check_template_names` field.
224    ///
225    /// # Returns
226    ///
227    /// The mutated borrowed instance.
228    pub fn with_check_template_names(
229        mut self,
230        check_template_names: bool,
231    ) -> Self {
232        self.check_template_names = check_template_names;
233        self
234    }
235
236    /// Sets new value for `timeout` field.
237    ///
238    /// It needs to be called on struct instance and effectively mutates it.
239    ///
240    /// # Arguments
241    ///
242    /// * `timeout` - The new value to be assigned to `timeout` field.
243    ///
244    /// # Returns
245    ///
246    /// The mutated borrowed instance.
247    pub fn with_timeout(mut self, timeout: u64) -> Self {
248        self.timeout = timeout;
249        self
250    }
251
252    /// Sets new value for `timeout_unit` field.
253    ///
254    /// It needs to be called on struct instance and effectively mutates it.
255    ///
256    /// # Arguments
257    ///
258    /// * `timeout_unit` - The new value to be assigned to `timeout_unit` field.
259    ///
260    /// # Returns
261    ///
262    /// The mutated borrowed instance.
263    pub fn with_timeout_unit(mut self, timeout_unit: TimeoutUnit) -> Self {
264        self.timeout_unit = timeout_unit;
265        self
266    }
267}
268
269/// Cli args parser trait to parse CLI args and return them in an [`Args`].
270///
271/// The produced Args instance needs to comply with constraints of each
272/// one of its fields (see fields doc in [`Args`] for more infos).
273pub trait ArgsParser {
274    /// Parses given cli args and return them as an [`Args`] instance.
275    ///
276    /// * First CLI args should be the binary name
277    /// * Rely on [`ArgsParser::try_parse`] method but additionally wrap
278    ///   error handling logic
279    ///
280    /// # Arguments
281    ///
282    /// * `args` - The CLI args to be parsed. Typically retrieved from
283    ///   [`std::env::args_os`].
284    ///
285    /// # Returns
286    ///
287    /// An owned instance of [`Args`] containing parsing result of given args.
288    fn parse(&self, args: impl IntoIterator<Item = OsString>) -> Args;
289
290    /// Parses given cli args and return them as an [`Args`] instance if no
291    /// error or early exit occurred.
292    ///
293    /// * First CLI args should be the binary name
294    /// * Version, author and help options are considered as early program
295    ///   exit
296    /// * Returned Args complies with expected constraints (see fields doc
297    ///   in [`Args`] for more infos)
298    ///
299    /// # Arguments
300    ///
301    /// * `args` - The CLI args to be parsed. Typically retrieved from
302    ///   [`std::env::args_os`].
303    ///
304    /// # Returns
305    ///
306    /// A result containing an owned instance of [`Args`] if successful parsing,
307    /// or a [`ProgramExit`] if any error or early exit occurred (e.g. version/
308    /// author/help infos printing, invalid cli args...)
309    fn try_parse(
310        &self,
311        args: impl IntoIterator<Item = OsString>,
312    ) -> Result<Args, ProgramExit>;
313}