gitignore_template_generator/parser/
api.rs

1use std::ffi::OsString;
2
3use clap::ValueEnum;
4
5use crate::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    /// Sets new value for `template_names` field.
115    ///
116    /// It needs to be called on struct instance and effectively mutates it.
117    ///
118    /// # Arguments
119    ///
120    /// * `template_names` - The new value to be assigned to `template_names`
121    ///     field.
122    ///
123    /// # Returns
124    ///
125    /// The mutated borrowed instance.
126    pub fn with_template_names(mut self, template_names: Vec<String>) -> Self {
127        self.template_names = template_names;
128        self
129    }
130
131    /// Sets new value for `server_url` field.
132    ///
133    /// It needs to be called on struct instance and effectively mutates it.
134    ///
135    /// # Arguments
136    ///
137    /// * `server_url` - The new value to be assigned to `server_url`
138    ///     field.
139    ///
140    /// # Returns
141    ///
142    /// The mutated borrowed instance.
143    pub fn with_server_url(mut self, server_url: &str) -> Self {
144        self.server_url = server_url.to_string();
145        self
146    }
147
148    /// Sets new value for `generator_uri` field.
149    ///
150    /// It needs to be called on struct instance and effectively mutates it.
151    ///
152    /// # Arguments
153    ///
154    /// * `generator_uri` - The new value to be assigned to
155    ///     `generator_uri` field.
156    ///
157    /// # Returns
158    ///
159    /// The mutated borrowed instance.
160    pub fn with_generator_uri(mut self, generator_uri: &str) -> Self {
161        self.generator_uri = generator_uri.to_string();
162        self
163    }
164
165    /// Sets new value for `lister_uri` field.
166    ///
167    /// It needs to be called on struct instance and effectively mutates it.
168    ///
169    /// # Arguments
170    ///
171    /// * `lister_uri` - The new value to be assigned to `lister_uri` field.
172    ///
173    /// # Returns
174    ///
175    /// The mutated borrowed instance.
176    pub fn with_lister_uri(mut self, lister_uri: &str) -> Self {
177        self.lister_uri = lister_uri.to_string();
178        self
179    }
180
181    /// Sets new value for `show_list` field.
182    ///
183    /// It needs to be called on struct instance and effectively mutates it.
184    ///
185    /// # Arguments
186    ///
187    /// * `show_list` - The new value to be assigned to `show_list`
188    ///     field.
189    ///
190    /// # Returns
191    ///
192    /// The mutated borrowed instance.
193    pub fn with_show_list(mut self, show_list: bool) -> Self {
194        self.show_list = show_list;
195        self
196    }
197
198    /// Sets new value for `check_template_names` field.
199    ///
200    /// It needs to be called on struct instance and effectively mutates it.
201    ///
202    /// # Arguments
203    ///
204    /// * `check_template_names` - The new value to be assigned to
205    ///     `check_template_names` field.
206    ///
207    /// # Returns
208    ///
209    /// The mutated borrowed instance.
210    pub fn with_check_template_names(
211        mut self,
212        check_template_names: bool,
213    ) -> Self {
214        self.check_template_names = check_template_names;
215        self
216    }
217
218    /// Sets new value for `timeout` field.
219    ///
220    /// It needs to be called on struct instance and effectively mutates it.
221    ///
222    /// # Arguments
223    ///
224    /// * `timeout` - The new value to be assigned to `timeout` field.
225    ///
226    /// # Returns
227    ///
228    /// The mutated borrowed instance.
229    pub fn with_timeout(mut self, timeout: u64) -> Self {
230        self.timeout = timeout;
231        self
232    }
233
234    /// Sets new value for `timeout_unit` field.
235    ///
236    /// It needs to be called on struct instance and effectively mutates it.
237    ///
238    /// # Arguments
239    ///
240    /// * `timeout_unit` - The new value to be assigned to `timeout_unit` field.
241    ///
242    /// # Returns
243    ///
244    /// The mutated borrowed instance.
245    pub fn with_timeout_unit(mut self, timeout_unit: TimeoutUnit) -> Self {
246        self.timeout_unit = timeout_unit;
247        self
248    }
249}
250
251/// Cli args parser trait to parse CLI args and return them in an [`Args`].
252///
253/// The produced Args instance needs to comply with constraints of each
254/// one of its fields (see fields doc in [`Args`] for more infos).
255pub trait ArgsParser {
256    /// Parses given cli args and return them as an [`Args`] instance.
257    ///
258    /// * First CLI args should be the binary name
259    /// * Rely on [`ArgsParser::try_parse`] method but additionally wrap
260    ///     error handling logic
261    ///
262    /// # Arguments
263    ///
264    /// * `args` - The CLI args to be parsed. Typically retrieved from
265    ///     [`std::env::args_os`].
266    ///
267    /// # Returns
268    ///
269    /// An owned instance of [`Args`] containing parsing result of given args.
270    fn parse(&self, args: impl IntoIterator<Item = OsString>) -> Args;
271
272    /// Parses given cli args and return them as an [`Args`] instance if no
273    /// error or early exit occurred.
274    ///
275    /// * First CLI args should be the binary name
276    /// * Version, author and help options are considered as early program
277    ///     exit
278    /// * Returned Args complies with expected constraints (see fields doc
279    ///     in [`Args`] for more infos)
280    ///
281    /// # Arguments
282    ///
283    ///  * `args` - The CLI args to be parsed. Typically retrieved from
284    ///     [`std::env::args_os`].
285    ///
286    /// # Returns
287    ///
288    /// A result containing an owned instance of [`Args`] if successful parsing,
289    /// or a [`ProgramExit`] if any error or early exit occurred (e.g. version/
290    /// author/help infos printing, invalid cli args...)
291    fn try_parse(
292        &self,
293        args: impl IntoIterator<Item = OsString>,
294    ) -> Result<Args, ProgramExit>;
295}