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