cliargs/parse/
parse_for.rs

1// Copyright (C) 2024 Takayuki Sato. All Rights Reserved.
2// This program is free software under MIT License.
3// See the file LICENSE in this distribution for more details.
4
5use crate::errors::InvalidOption;
6use crate::Cmd;
7use crate::OptCfg;
8use std::collections::HashMap;
9
10/// Requires the method to make a [OptCfg] vector from the struct instance which implements this
11/// trait.
12pub trait OptStore {
13    /// Makes a vector of [OptCfg] struct instances from the field definitions and `opt` field
14    /// attributes of the struct instance.
15    fn make_opt_cfgs(&self) -> Vec<OptCfg>;
16
17    /// Sets the values in the argument map to the fields in this struct
18    /// The key in the map is a store key of [OptCfg].
19    fn set_field_values(&mut self, m: &HashMap<&str, Vec<&str>>) -> Result<(), InvalidOption>;
20}
21
22/// Makes a vector of [OptCfg] struct instances from the field definitions and `opt` field
23/// attributes of the struct instnace of which type is `T`.
24///
25/// One [OptCfg] struct instance is made for each field.
26/// The field name is set to `store_key`.
27/// If the field's data type is `bool`, `has_arg` is set to `false`, otherwise, it is set to
28/// `true`.
29/// If the field is a vector type, `is_array` is set to `true`; otherwise, it is set to
30/// `false`.
31///
32/// Additionally, `names`, `defaults`, `desc`, and `arg_in_help` are set with extracted from
33/// the `opt` attribute attached to the field.
34///
35/// For `validator`, if the field's data type is numeric, it is set to the `validate_number`
36/// function pointer corresponding to the data type.
37pub fn make_opt_cfgs_for<T: OptStore>(opt_store: &mut T) -> Vec<OptCfg> {
38    opt_store.make_opt_cfgs()
39}
40
41impl<'b> Cmd<'_> {
42    /// Parses command line arguments and set their option values to the fields of the option store
43    /// which is passed as the argument of this method.
44    ///
45    /// This method divides command line arguments to command arguments and options, then sets
46    /// each option value to a corresponding field of the option store.
47    ///
48    /// Within this method, a vector of [OptCfg] is made from the fields of the option store.
49    /// This [OptCfg] vector is set into this [Cmd] instance.
50    /// If you want to access this option configurations, get them by `opt_cfgs` method.
51    ///
52    /// An option configuration corresponding to each field of an option store is determined by
53    /// its type and `opt` field attribute.
54    /// If the type is bool, the option takes no argument.
55    /// If the type is integer, floating point number or string, the option can takes single option
56    /// argument, therefore it can appear once in command line arguments.
57    /// If the type is a vector, the option can takes multiple option arguments, therefore it can
58    /// appear multiple times in command line arguments.
59    ///
60    /// A `opt` field attribute can have the following pairs of name and value: one is `cfg` to
61    /// specify `names` and `defaults` fields of [OptCfg] struct, another is `desc` to specify
62    /// `desc` field, and yet another is `arg` to specify `arg_in_help` field.
63    ///
64    /// The format of `cfg` is like `cfg="f,foo=123"`.
65    /// The left side of the equal sign is the option name(s), and the right side is the default
66    /// value(s).
67    /// If there is no equal sign, it is determined that only the option name is specified.
68    /// If you want to specify multiple option names, separate them with commas.
69    /// If you want to specify multiple default values, separate them with commas and round them
70    /// with square brackets, like `[1,2,3]`.
71    /// If you want to use your favorite character as a separator, you can use it by putting it
72    /// on the left side of the open square bracket, like `/[1/2/3]`.
73    ///
74    /// NOTE: A default value of empty string array option in a field attribute is `[]`, like
75    /// `#[opt(cfg="=[]")]`, but it doesn't represent an array which contains only one empty
76    /// string.
77    /// If you want to specify an array which contains only one emtpy string, write nothing after
78    /// `=` symbol, like `#[opt(cfg="=")]`.
79    ///
80    /// ```
81    /// use cliargs::Cmd;
82    /// use cliargs::errors::InvalidOption;
83    ///
84    /// #[derive(cliargs::OptStore)]
85    /// struct MyOptions {
86    ///     #[opt(cfg = "f,foo-bar", desc="The description of foo_bar.")]
87    ///     foo_bar: bool,
88    ///     #[opt(cfg = "b,baz", desc="The description of baz.", arg="<s>")]
89    ///     baz: String,
90    /// }
91    /// let mut my_options = MyOptions::with_defaults();
92    ///
93    /// let mut cmd = Cmd::with_strings(vec![ /* ... */ ]);
94    ///
95    /// match cmd.parse_for(&mut my_options) {
96    ///     Ok(_) => { /* ... */ },
97    ///     Err(InvalidOption::OptionContainsInvalidChar { option }) => { /* ... */ },
98    ///     Err(InvalidOption::UnconfiguredOption { option }) => { /* ... */ },
99    ///     Err(InvalidOption::OptionNeedsArg { option, .. }) => { /* ... */ },
100    ///     Err(InvalidOption::OptionTakesNoArg { option, .. }) => { /* ... */ },
101    ///     Err(InvalidOption::OptionIsNotArray { option, .. }) => { /* ... */ },
102    ///     Err(InvalidOption::OptionArgIsInvalid { option, opt_arg, details, .. }) => { /* ... */ },
103    ///     Err(err) => panic!("Invalid option: {}", err.option()),
104    /// }
105    ///
106    /// let cfgs = cmd.opt_cfgs();
107    /// ```
108    pub fn parse_for<T: OptStore>(&mut self, opt_store: &mut T) -> Result<(), InvalidOption> {
109        let cfgs = opt_store.make_opt_cfgs();
110        match self.parse_with(cfgs) {
111            Ok(_) => {}
112            Err(err) => return Err(err),
113        }
114        opt_store.set_field_values(&self.opts)
115    }
116
117    /// Parses command line arguments until the first command argument and set their option values
118    /// to the option store which is passed as an argument.
119    ///
120    /// This method creates and returns a new [Cmd] instance that holds the command line arguments
121    /// starting from the first command argument.
122    ///
123    /// This method parses command line arguments in the same way as the [Cmd::parse_for] method,
124    /// except that it only parses the command line arguments before the first command argument.
125    ///
126    /// ```
127    /// use cliargs::Cmd;
128    /// use cliargs::errors::InvalidOption;
129    ///
130    /// #[derive(cliargs::OptStore)]
131    /// struct MyOptions {
132    ///     #[opt(cfg = "f,foo-bar", desc="The description of foo_bar.")]
133    ///     foo_bar: bool,
134    ///     #[opt(cfg = "b,baz", desc="The description of baz.", arg="<s>")]
135    ///     baz: String,
136    /// }
137    /// let mut my_options = MyOptions::with_defaults();
138    ///
139    /// let mut cmd = Cmd::with_strings(vec![ /* ... */ ]);
140    ///
141    /// match cmd.parse_until_sub_cmd_for(&mut my_options) {
142    ///     Ok(Some(mut sub_cmd)) => {
143    ///         let sub_cmd_name = sub_cmd.name();
144    ///         match sub_cmd.parse() {
145    ///             Ok(_) => { /* ... */ },
146    ///             Err(err) => panic!("Invalid option: {}", err.option()),
147    ///         }
148    ///     },
149    ///     Ok(None) => { /* ... */ },
150    ///     Err(InvalidOption::OptionContainsInvalidChar { option }) => { /* ... */ },
151    ///     Err(InvalidOption::UnconfiguredOption { option }) => { /* ... */ },
152    ///     Err(InvalidOption::OptionNeedsArg { option, .. }) => { /* ... */ },
153    ///     Err(InvalidOption::OptionTakesNoArg { option, .. }) => { /* ... */ },
154    ///     Err(InvalidOption::OptionIsNotArray { option, .. }) => { /* ... */ },
155    ///     Err(InvalidOption::OptionArgIsInvalid { option, opt_arg, details, .. }) => { /* ... */ },
156    ///     Err(err) => panic!("Invalid option: {}", err.option()),
157    /// }
158    ///
159    /// let cfgs = cmd.opt_cfgs();
160    /// ```
161    pub fn parse_until_sub_cmd_for<T: OptStore>(
162        &mut self,
163        opt_store: &mut T,
164    ) -> Result<Option<Cmd<'b>>, InvalidOption> {
165        let cfgs = opt_store.make_opt_cfgs();
166        match self.parse_until_sub_cmd_with(cfgs) {
167            Ok(None) => {
168                opt_store.set_field_values(&self.opts)?;
169                return Ok(None);
170            }
171            Ok(Some(sub_cmd)) => {
172                opt_store.set_field_values(&self.opts)?;
173                return Ok(Some(sub_cmd));
174            }
175            Err(err) => return Err(err),
176        }
177    }
178}
179
180#[cfg(test)]
181mod tests_of_make_opt_cfgs_for {
182    use super::*;
183    use crate as cliargs;
184    extern crate cliargs_derive;
185    pub use cliargs_derive::OptStore;
186
187    //#[derive(OptStore)]
188    //enum MyEnum {}  // -> error
189
190    //#[derive(OptStore)]
191    //struct MyTuple(u8, u8); // -> error
192
193    //#[derive(OptStore)]
194    //struct MyStruct {
195    //    foo: std::time::Duration, // -> error
196    //}
197
198    //#[derive(OptStore)]
199    //struct WithAttrOptions {
200    //    //#[opt(cfg)] // -> error
201    //    //#[opt(aaa = "a")] // -> error
202    //    //#[opt(cfg=aaa)] // -> error
203    //    //#[opt(cfg = 123)] // -> error
204    //    //#[opt(desc = 123)] // -> error
205    //    //#[opt(arg = 123)] // -> error
206    //    b_val: bool,
207    //}
208
209    mod tests_when_no_attr {
210        use super::*;
211        use std::collections::HashMap;
212
213        #[derive(OptStore)]
214        struct NoAttrOptions {
215            b_val: bool,
216            s_val: String,
217            i8_val: i8,
218            i16_val: i16,
219            i32_val: i32,
220            i64_val: i64,
221            i128_val: i128,
222            u8_val: u8,
223            u16_val: u16,
224            u32_val: u32,
225            u64_val: u64,
226            u128_val: u128,
227            f32_val: f32,
228            f64_val: f64,
229            s_arr: Vec<String>,
230            i8_arr: Vec<i8>,
231            i16_arr: Vec<i16>,
232            i32_arr: Vec<i32>,
233            i64_arr: Vec<i64>,
234            i128_arr: Vec<i128>,
235            u8_arr: Vec<u8>,
236            u16_arr: Vec<u16>,
237            u32_arr: Vec<u32>,
238            u64_arr: Vec<u64>,
239            u128_arr: Vec<u128>,
240            f32_arr: Vec<f32>,
241            f64_arr: Vec<f64>,
242            s_opt: Option<String>,
243            i8_opt: Option<i8>,
244            i16_opt: Option<i16>,
245            i32_opt: Option<i32>,
246            i64_opt: Option<i64>,
247            i128_opt: Option<i128>,
248            u8_opt: Option<u8>,
249            u16_opt: Option<u16>,
250            u32_opt: Option<u32>,
251            u64_opt: Option<u64>,
252            u128_opt: Option<u128>,
253            f32_opt: Option<f32>,
254            f64_opt: Option<f64>,
255        }
256
257        #[test]
258        fn test_create_instance_with_defaults() {
259            let store = NoAttrOptions::with_defaults();
260            assert_eq!(store.b_val, false);
261            assert_eq!(store.s_val, "".to_string());
262            assert_eq!(store.i8_val, 0);
263            assert_eq!(store.i16_val, 0);
264            assert_eq!(store.i32_val, 0);
265            assert_eq!(store.i64_val, 0);
266            assert_eq!(store.i128_val, 0);
267            assert_eq!(store.u8_val, 0);
268            assert_eq!(store.u16_val, 0);
269            assert_eq!(store.u32_val, 0);
270            assert_eq!(store.u64_val, 0);
271            assert_eq!(store.u128_val, 0);
272            assert_eq!(store.f32_val, 0.0);
273            assert_eq!(store.f64_val, 0.0);
274            assert_eq!(store.s_arr, Vec::<String>::new());
275            assert_eq!(store.i8_arr, Vec::<i8>::new());
276            assert_eq!(store.i16_arr, Vec::<i16>::new());
277            assert_eq!(store.i32_arr, Vec::<i32>::new());
278            assert_eq!(store.i64_arr, Vec::<i64>::new());
279            assert_eq!(store.i128_arr, Vec::<i128>::new());
280            assert_eq!(store.u8_arr, Vec::<u8>::new());
281            assert_eq!(store.u16_arr, Vec::<u16>::new());
282            assert_eq!(store.u32_arr, Vec::<u32>::new());
283            assert_eq!(store.u64_arr, Vec::<u64>::new());
284            assert_eq!(store.u128_arr, Vec::<u128>::new());
285            assert_eq!(store.f32_arr, Vec::<f32>::new());
286            assert_eq!(store.f64_arr, Vec::<f64>::new());
287            assert_eq!(store.s_opt, None);
288            assert_eq!(store.i8_opt, None);
289            assert_eq!(store.i16_opt, None);
290            assert_eq!(store.i32_opt, None);
291            assert_eq!(store.i64_opt, None);
292            assert_eq!(store.i128_opt, None);
293            assert_eq!(store.u8_opt, None);
294            assert_eq!(store.u16_opt, None);
295            assert_eq!(store.u32_opt, None);
296            assert_eq!(store.u64_opt, None);
297            assert_eq!(store.u128_opt, None);
298            assert_eq!(store.f32_opt, None);
299            assert_eq!(store.f64_opt, None);
300        }
301
302        #[test]
303        fn test_make_opt_cfgs_for_opt_store() {
304            let mut store = NoAttrOptions::with_defaults();
305            let cfgs = cliargs::make_opt_cfgs_for(&mut store);
306            assert_eq!(cfgs.len(), 40);
307
308            let cfg = &cfgs[0];
309            assert_eq!(cfg.store_key, "b_val");
310            assert_eq!(cfg.names, Vec::<String>::new());
311            assert_eq!(cfg.has_arg, false);
312            assert_eq!(cfg.is_array, false);
313            assert_eq!(cfg.defaults, None);
314            assert_eq!(cfg.desc, "".to_string());
315            assert_eq!(cfg.arg_in_help, "".to_string());
316
317            let cfg = &cfgs[1];
318            assert_eq!(cfg.store_key, "s_val");
319            assert_eq!(cfg.names, Vec::<String>::new());
320            assert_eq!(cfg.has_arg, true);
321            assert_eq!(cfg.is_array, false);
322            assert_eq!(cfg.defaults, None);
323            assert_eq!(cfg.desc, "".to_string());
324            assert_eq!(cfg.arg_in_help, "".to_string());
325
326            let cfg = &cfgs[2];
327            assert_eq!(cfg.store_key, "i8_val");
328            assert_eq!(cfg.names, Vec::<String>::new());
329            assert_eq!(cfg.has_arg, true);
330            assert_eq!(cfg.is_array, false);
331            assert_eq!(cfg.defaults, None);
332            assert_eq!(cfg.desc, "".to_string());
333            assert_eq!(cfg.arg_in_help, "".to_string());
334
335            let cfg = &cfgs[3];
336            assert_eq!(cfg.store_key, "i16_val");
337            assert_eq!(cfg.names, Vec::<String>::new());
338            assert_eq!(cfg.has_arg, true);
339            assert_eq!(cfg.is_array, false);
340            assert_eq!(cfg.defaults, None);
341            assert_eq!(cfg.desc, "".to_string());
342            assert_eq!(cfg.arg_in_help, "".to_string());
343
344            let cfg = &cfgs[4];
345            assert_eq!(cfg.store_key, "i32_val");
346            assert_eq!(cfg.names, Vec::<String>::new());
347            assert_eq!(cfg.has_arg, true);
348            assert_eq!(cfg.is_array, false);
349            assert_eq!(cfg.defaults, None);
350            assert_eq!(cfg.desc, "".to_string());
351            assert_eq!(cfg.arg_in_help, "".to_string());
352
353            let cfg = &cfgs[5];
354            assert_eq!(cfg.store_key, "i64_val");
355            assert_eq!(cfg.names, Vec::<String>::new());
356            assert_eq!(cfg.has_arg, true);
357            assert_eq!(cfg.is_array, false);
358            assert_eq!(cfg.defaults, None);
359            assert_eq!(cfg.desc, "".to_string());
360            assert_eq!(cfg.arg_in_help, "".to_string());
361
362            let cfg = &cfgs[6];
363            assert_eq!(cfg.store_key, "i128_val");
364            assert_eq!(cfg.names, Vec::<String>::new());
365            assert_eq!(cfg.has_arg, true);
366            assert_eq!(cfg.is_array, false);
367            assert_eq!(cfg.defaults, None);
368            assert_eq!(cfg.desc, "".to_string());
369            assert_eq!(cfg.arg_in_help, "".to_string());
370
371            let cfg = &cfgs[7];
372            assert_eq!(cfg.store_key, "u8_val");
373            assert_eq!(cfg.names, Vec::<String>::new());
374            assert_eq!(cfg.has_arg, true);
375            assert_eq!(cfg.is_array, false);
376            assert_eq!(cfg.defaults, None);
377            assert_eq!(cfg.desc, "".to_string());
378            assert_eq!(cfg.arg_in_help, "".to_string());
379
380            let cfg = &cfgs[8];
381            assert_eq!(cfg.store_key, "u16_val");
382            assert_eq!(cfg.names, Vec::<String>::new());
383            assert_eq!(cfg.has_arg, true);
384            assert_eq!(cfg.is_array, false);
385            assert_eq!(cfg.defaults, None);
386            assert_eq!(cfg.desc, "".to_string());
387            assert_eq!(cfg.arg_in_help, "".to_string());
388
389            let cfg = &cfgs[9];
390            assert_eq!(cfg.store_key, "u32_val");
391            assert_eq!(cfg.names, Vec::<String>::new());
392            assert_eq!(cfg.has_arg, true);
393            assert_eq!(cfg.is_array, false);
394            assert_eq!(cfg.defaults, None);
395            assert_eq!(cfg.desc, "".to_string());
396            assert_eq!(cfg.arg_in_help, "".to_string());
397
398            let cfg = &cfgs[10];
399            assert_eq!(cfg.store_key, "u64_val");
400            assert_eq!(cfg.names, Vec::<String>::new());
401            assert_eq!(cfg.has_arg, true);
402            assert_eq!(cfg.is_array, false);
403            assert_eq!(cfg.defaults, None);
404            assert_eq!(cfg.desc, "".to_string());
405            assert_eq!(cfg.arg_in_help, "".to_string());
406
407            let cfg = &cfgs[11];
408            assert_eq!(cfg.store_key, "u128_val");
409            assert_eq!(cfg.names, Vec::<String>::new());
410            assert_eq!(cfg.has_arg, true);
411            assert_eq!(cfg.is_array, false);
412            assert_eq!(cfg.defaults, None);
413            assert_eq!(cfg.desc, "".to_string());
414            assert_eq!(cfg.arg_in_help, "".to_string());
415
416            let cfg = &cfgs[12];
417            assert_eq!(cfg.store_key, "f32_val");
418            assert_eq!(cfg.names, Vec::<String>::new());
419            assert_eq!(cfg.has_arg, true);
420            assert_eq!(cfg.is_array, false);
421            assert_eq!(cfg.defaults, None);
422            assert_eq!(cfg.desc, "".to_string());
423            assert_eq!(cfg.arg_in_help, "".to_string());
424
425            let cfg = &cfgs[13];
426            assert_eq!(cfg.store_key, "f64_val");
427            assert_eq!(cfg.names, Vec::<String>::new());
428            assert_eq!(cfg.has_arg, true);
429            assert_eq!(cfg.is_array, false);
430            assert_eq!(cfg.defaults, None);
431            assert_eq!(cfg.desc, "".to_string());
432            assert_eq!(cfg.arg_in_help, "".to_string());
433
434            let cfg = &cfgs[14];
435            assert_eq!(cfg.store_key, "s_arr");
436            assert_eq!(cfg.names, Vec::<String>::new());
437            assert_eq!(cfg.has_arg, true);
438            assert_eq!(cfg.is_array, true);
439            assert_eq!(cfg.defaults, None);
440            assert_eq!(cfg.desc, "".to_string());
441            assert_eq!(cfg.arg_in_help, "".to_string());
442
443            let cfg = &cfgs[15];
444            assert_eq!(cfg.store_key, "i8_arr");
445            assert_eq!(cfg.names, Vec::<String>::new());
446            assert_eq!(cfg.has_arg, true);
447            assert_eq!(cfg.is_array, true);
448            assert_eq!(cfg.defaults, None);
449            assert_eq!(cfg.desc, "".to_string());
450            assert_eq!(cfg.arg_in_help, "".to_string());
451
452            let cfg = &cfgs[16];
453            assert_eq!(cfg.store_key, "i16_arr");
454            assert_eq!(cfg.names, Vec::<String>::new());
455            assert_eq!(cfg.has_arg, true);
456            assert_eq!(cfg.is_array, true);
457            assert_eq!(cfg.defaults, None);
458            assert_eq!(cfg.desc, "".to_string());
459            assert_eq!(cfg.arg_in_help, "".to_string());
460
461            let cfg = &cfgs[17];
462            assert_eq!(cfg.store_key, "i32_arr");
463            assert_eq!(cfg.names, Vec::<String>::new());
464            assert_eq!(cfg.has_arg, true);
465            assert_eq!(cfg.is_array, true);
466            assert_eq!(cfg.defaults, None);
467            assert_eq!(cfg.desc, "".to_string());
468            assert_eq!(cfg.arg_in_help, "".to_string());
469
470            let cfg = &cfgs[18];
471            assert_eq!(cfg.store_key, "i64_arr");
472            assert_eq!(cfg.names, Vec::<String>::new());
473            assert_eq!(cfg.has_arg, true);
474            assert_eq!(cfg.is_array, true);
475            assert_eq!(cfg.defaults, None);
476            assert_eq!(cfg.desc, "".to_string());
477            assert_eq!(cfg.arg_in_help, "".to_string());
478
479            let cfg = &cfgs[19];
480            assert_eq!(cfg.store_key, "i128_arr");
481            assert_eq!(cfg.names, Vec::<String>::new());
482            assert_eq!(cfg.has_arg, true);
483            assert_eq!(cfg.is_array, true);
484            assert_eq!(cfg.defaults, None);
485            assert_eq!(cfg.desc, "".to_string());
486            assert_eq!(cfg.arg_in_help, "".to_string());
487
488            let cfg = &cfgs[20];
489            assert_eq!(cfg.store_key, "u8_arr");
490            assert_eq!(cfg.names, Vec::<String>::new());
491            assert_eq!(cfg.has_arg, true);
492            assert_eq!(cfg.is_array, true);
493            assert_eq!(cfg.defaults, None);
494            assert_eq!(cfg.desc, "".to_string());
495            assert_eq!(cfg.arg_in_help, "".to_string());
496
497            let cfg = &cfgs[21];
498            assert_eq!(cfg.store_key, "u16_arr");
499            assert_eq!(cfg.names, Vec::<String>::new());
500            assert_eq!(cfg.has_arg, true);
501            assert_eq!(cfg.is_array, true);
502            assert_eq!(cfg.defaults, None);
503            assert_eq!(cfg.desc, "".to_string());
504            assert_eq!(cfg.arg_in_help, "".to_string());
505
506            let cfg = &cfgs[22];
507            assert_eq!(cfg.store_key, "u32_arr");
508            assert_eq!(cfg.names, Vec::<String>::new());
509            assert_eq!(cfg.has_arg, true);
510            assert_eq!(cfg.is_array, true);
511            assert_eq!(cfg.defaults, None);
512            assert_eq!(cfg.desc, "".to_string());
513            assert_eq!(cfg.arg_in_help, "".to_string());
514
515            let cfg = &cfgs[23];
516            assert_eq!(cfg.store_key, "u64_arr");
517            assert_eq!(cfg.names, Vec::<String>::new());
518            assert_eq!(cfg.has_arg, true);
519            assert_eq!(cfg.is_array, true);
520            assert_eq!(cfg.defaults, None);
521            assert_eq!(cfg.desc, "".to_string());
522            assert_eq!(cfg.arg_in_help, "".to_string());
523
524            let cfg = &cfgs[24];
525            assert_eq!(cfg.store_key, "u128_arr");
526            assert_eq!(cfg.names, Vec::<String>::new());
527            assert_eq!(cfg.has_arg, true);
528            assert_eq!(cfg.is_array, true);
529            assert_eq!(cfg.defaults, None);
530            assert_eq!(cfg.desc, "".to_string());
531            assert_eq!(cfg.arg_in_help, "".to_string());
532
533            let cfg = &cfgs[25];
534            assert_eq!(cfg.store_key, "f32_arr");
535            assert_eq!(cfg.names, Vec::<String>::new());
536            assert_eq!(cfg.has_arg, true);
537            assert_eq!(cfg.is_array, true);
538            assert_eq!(cfg.defaults, None);
539            assert_eq!(cfg.desc, "".to_string());
540            assert_eq!(cfg.arg_in_help, "".to_string());
541
542            let cfg = &cfgs[26];
543            assert_eq!(cfg.store_key, "f64_arr");
544            assert_eq!(cfg.names, Vec::<String>::new());
545            assert_eq!(cfg.has_arg, true);
546            assert_eq!(cfg.is_array, true);
547            assert_eq!(cfg.defaults, None);
548            assert_eq!(cfg.desc, "".to_string());
549            assert_eq!(cfg.arg_in_help, "".to_string());
550
551            let cfg = &cfgs[27];
552            assert_eq!(cfg.store_key, "s_opt");
553            assert_eq!(cfg.names, Vec::<String>::new());
554            assert_eq!(cfg.has_arg, true);
555            assert_eq!(cfg.is_array, false);
556            assert_eq!(cfg.defaults, None);
557            assert_eq!(cfg.desc, "".to_string());
558            assert_eq!(cfg.arg_in_help, "".to_string());
559
560            let cfg = &cfgs[28];
561            assert_eq!(cfg.store_key, "i8_opt");
562            assert_eq!(cfg.names, Vec::<String>::new());
563            assert_eq!(cfg.has_arg, true);
564            assert_eq!(cfg.is_array, false);
565            assert_eq!(cfg.defaults, None);
566            assert_eq!(cfg.desc, "".to_string());
567            assert_eq!(cfg.arg_in_help, "".to_string());
568
569            let cfg = &cfgs[29];
570            assert_eq!(cfg.store_key, "i16_opt");
571            assert_eq!(cfg.names, Vec::<String>::new());
572            assert_eq!(cfg.has_arg, true);
573            assert_eq!(cfg.is_array, false);
574            assert_eq!(cfg.defaults, None);
575            assert_eq!(cfg.desc, "".to_string());
576            assert_eq!(cfg.arg_in_help, "".to_string());
577
578            let cfg = &cfgs[30];
579            assert_eq!(cfg.store_key, "i32_opt");
580            assert_eq!(cfg.names, Vec::<String>::new());
581            assert_eq!(cfg.has_arg, true);
582            assert_eq!(cfg.is_array, false);
583            assert_eq!(cfg.defaults, None);
584            assert_eq!(cfg.desc, "".to_string());
585            assert_eq!(cfg.arg_in_help, "".to_string());
586
587            let cfg = &cfgs[31];
588            assert_eq!(cfg.store_key, "i64_opt");
589            assert_eq!(cfg.names, Vec::<String>::new());
590            assert_eq!(cfg.has_arg, true);
591            assert_eq!(cfg.is_array, false);
592            assert_eq!(cfg.defaults, None);
593            assert_eq!(cfg.desc, "".to_string());
594            assert_eq!(cfg.arg_in_help, "".to_string());
595
596            let cfg = &cfgs[32];
597            assert_eq!(cfg.store_key, "i128_opt");
598            assert_eq!(cfg.names, Vec::<String>::new());
599            assert_eq!(cfg.has_arg, true);
600            assert_eq!(cfg.is_array, false);
601            assert_eq!(cfg.defaults, None);
602            assert_eq!(cfg.desc, "".to_string());
603            assert_eq!(cfg.arg_in_help, "".to_string());
604
605            let cfg = &cfgs[33];
606            assert_eq!(cfg.store_key, "u8_opt");
607            assert_eq!(cfg.names, Vec::<String>::new());
608            assert_eq!(cfg.has_arg, true);
609            assert_eq!(cfg.is_array, false);
610            assert_eq!(cfg.defaults, None);
611            assert_eq!(cfg.desc, "".to_string());
612            assert_eq!(cfg.arg_in_help, "".to_string());
613
614            let cfg = &cfgs[34];
615            assert_eq!(cfg.store_key, "u16_opt");
616            assert_eq!(cfg.names, Vec::<String>::new());
617            assert_eq!(cfg.has_arg, true);
618            assert_eq!(cfg.is_array, false);
619            assert_eq!(cfg.defaults, None);
620            assert_eq!(cfg.desc, "".to_string());
621            assert_eq!(cfg.arg_in_help, "".to_string());
622
623            let cfg = &cfgs[35];
624            assert_eq!(cfg.store_key, "u32_opt");
625            assert_eq!(cfg.names, Vec::<String>::new());
626            assert_eq!(cfg.has_arg, true);
627            assert_eq!(cfg.is_array, false);
628            assert_eq!(cfg.defaults, None);
629            assert_eq!(cfg.desc, "".to_string());
630            assert_eq!(cfg.arg_in_help, "".to_string());
631
632            let cfg = &cfgs[36];
633            assert_eq!(cfg.store_key, "u64_opt");
634            assert_eq!(cfg.names, Vec::<String>::new());
635            assert_eq!(cfg.has_arg, true);
636            assert_eq!(cfg.is_array, false);
637            assert_eq!(cfg.defaults, None);
638            assert_eq!(cfg.desc, "".to_string());
639            assert_eq!(cfg.arg_in_help, "".to_string());
640
641            let cfg = &cfgs[37];
642            assert_eq!(cfg.store_key, "u128_opt");
643            assert_eq!(cfg.names, Vec::<String>::new());
644            assert_eq!(cfg.has_arg, true);
645            assert_eq!(cfg.is_array, false);
646            assert_eq!(cfg.defaults, None);
647            assert_eq!(cfg.desc, "".to_string());
648            assert_eq!(cfg.arg_in_help, "".to_string());
649
650            let cfg = &cfgs[38];
651            assert_eq!(cfg.store_key, "f32_opt");
652            assert_eq!(cfg.names, Vec::<String>::new());
653            assert_eq!(cfg.has_arg, true);
654            assert_eq!(cfg.is_array, false);
655            assert_eq!(cfg.defaults, None);
656            assert_eq!(cfg.desc, "".to_string());
657            assert_eq!(cfg.arg_in_help, "".to_string());
658
659            let cfg = &cfgs[39];
660            assert_eq!(cfg.store_key, "f64_opt");
661            assert_eq!(cfg.names, Vec::<String>::new());
662            assert_eq!(cfg.has_arg, true);
663            assert_eq!(cfg.is_array, false);
664            assert_eq!(cfg.defaults, None);
665            assert_eq!(cfg.desc, "".to_string());
666            assert_eq!(cfg.arg_in_help, "".to_string());
667        }
668
669        #[test]
670        fn tests_set_field_values() {
671            let mut store = NoAttrOptions::with_defaults();
672
673            let mut m = HashMap::<&str, Vec<&str>>::new();
674            m.insert("b_val", vec![]);
675            m.insert("s_val", vec!["ABC"]);
676            m.insert("i8_val", vec!["-111"]);
677            m.insert("i16_val", vec!["-123"]);
678            m.insert("i32_val", vec!["-123"]);
679            m.insert("i64_val", vec!["-123"]);
680            m.insert("i128_val", vec!["-123"]);
681            m.insert("u8_val", vec!["123"]);
682            m.insert("u16_val", vec!["123"]);
683            m.insert("u32_val", vec!["123"]);
684            m.insert("u64_val", vec!["123"]);
685            m.insert("u128_val", vec!["123"]);
686            m.insert("f32_val", vec!["0.12"]);
687            m.insert("f64_val", vec!["3.45"]);
688            m.insert("s_arr", vec!["A", "B", "C"]);
689            m.insert("i8_arr", vec!["-1", "-2", "-3"]);
690            m.insert("i16_arr", vec!["-1", "-2", "-3"]);
691            m.insert("i32_arr", vec!["-1", "-2", "-3"]);
692            m.insert("i64_arr", vec!["-1", "-2", "-3"]);
693            m.insert("i128_arr", vec!["-1", "-2", "-3"]);
694            m.insert("u8_arr", vec!["1", "2", "3"]);
695            m.insert("u16_arr", vec!["1", "2", "3"]);
696            m.insert("u32_arr", vec!["1", "2", "3"]);
697            m.insert("u64_arr", vec!["1", "2", "3"]);
698            m.insert("u128_arr", vec!["1", "2", "3"]);
699            m.insert("f32_arr", vec!["0.1", "0.2", "0.3"]);
700            m.insert("f64_arr", vec!["0.1", "0.2", "0.3"]);
701            m.insert("s_opt", vec!["abc"]);
702            m.insert("i8_opt", vec!["-45"]);
703            m.insert("i16_opt", vec!["-45"]);
704            m.insert("i32_opt", vec!["-45"]);
705            m.insert("i64_opt", vec!["-45"]);
706            m.insert("i128_opt", vec!["-45"]);
707            m.insert("u8_opt", vec!["45"]);
708            m.insert("u16_opt", vec!["45"]);
709            m.insert("u32_opt", vec!["45"]);
710            m.insert("u64_opt", vec!["45"]);
711            m.insert("u128_opt", vec!["45"]);
712            m.insert("f32_opt", vec!["4.5"]);
713            m.insert("f64_opt", vec!["4.5"]);
714
715            match store.set_field_values(&m) {
716                Ok(_) => {
717                    assert_eq!(store.b_val, true);
718                    assert_eq!(store.s_val, "ABC".to_string());
719                    assert_eq!(store.i8_val, -111);
720                    assert_eq!(store.i16_val, -123);
721                    assert_eq!(store.i32_val, -123);
722                    assert_eq!(store.i64_val, -123);
723                    assert_eq!(store.i128_val, -123);
724                    assert_eq!(store.u8_val, 123);
725                    assert_eq!(store.u16_val, 123);
726                    assert_eq!(store.u32_val, 123);
727                    assert_eq!(store.u64_val, 123);
728                    assert_eq!(store.u128_val, 123);
729                    assert_eq!(store.f32_val, 0.12);
730                    assert_eq!(store.f64_val, 3.45);
731                    assert_eq!(
732                        store.s_arr,
733                        vec!["A".to_string(), "B".to_string(), "C".to_string(),]
734                    );
735                    assert_eq!(store.i8_arr, vec![-1, -2, -3]);
736                    assert_eq!(store.i16_arr, vec![-1, -2, -3]);
737                    assert_eq!(store.i32_arr, vec![-1, -2, -3]);
738                    assert_eq!(store.i64_arr, vec![-1, -2, -3]);
739                    assert_eq!(store.i128_arr, vec![-1, -2, -3]);
740                    assert_eq!(store.u8_arr, vec![1, 2, 3]);
741                    assert_eq!(store.u16_arr, vec![1, 2, 3]);
742                    assert_eq!(store.u32_arr, vec![1, 2, 3]);
743                    assert_eq!(store.u64_arr, vec![1, 2, 3]);
744                    assert_eq!(store.u128_arr, vec![1, 2, 3]);
745                    assert_eq!(store.f32_arr, vec![0.1, 0.2, 0.3]);
746                    assert_eq!(store.f64_arr, vec![0.1, 0.2, 0.3]);
747                    assert_eq!(store.s_opt, Some("abc".to_string()));
748                    assert_eq!(store.i8_opt, Some(-45));
749                    assert_eq!(store.i16_opt, Some(-45));
750                    assert_eq!(store.i32_opt, Some(-45));
751                    assert_eq!(store.i64_opt, Some(-45));
752                    assert_eq!(store.i128_opt, Some(-45));
753                    assert_eq!(store.u8_opt, Some(45));
754                    assert_eq!(store.u16_opt, Some(45));
755                    assert_eq!(store.u32_opt, Some(45));
756                    assert_eq!(store.u64_opt, Some(45));
757                    assert_eq!(store.u128_opt, Some(45));
758                    assert_eq!(store.f32_opt, Some(4.5));
759                    assert_eq!(store.f64_opt, Some(4.5));
760                }
761                Err(_) => assert!(false),
762            }
763        }
764
765        #[test]
766        fn tests_set_field_values_if_map_is_empty() {
767            let mut store = NoAttrOptions::with_defaults();
768
769            let m = HashMap::<&str, Vec<&str>>::new();
770            match store.set_field_values(&m) {
771                Ok(_) => {
772                    assert_eq!(store.b_val, false);
773                    assert_eq!(store.s_val, "".to_string());
774                    assert_eq!(store.i8_val, 0);
775                    assert_eq!(store.i16_val, 0);
776                    assert_eq!(store.i32_val, 0);
777                    assert_eq!(store.i64_val, 0);
778                    assert_eq!(store.i128_val, 0);
779                    assert_eq!(store.u8_val, 0);
780                    assert_eq!(store.u16_val, 0);
781                    assert_eq!(store.u32_val, 0);
782                    assert_eq!(store.u64_val, 0);
783                    assert_eq!(store.u128_val, 0);
784                    assert_eq!(store.f32_val, 0.0);
785                    assert_eq!(store.f64_val, 0.0);
786                    assert_eq!(store.s_arr, Vec::<String>::new());
787                    assert_eq!(store.i8_arr, Vec::<i8>::new());
788                    assert_eq!(store.i16_arr, Vec::<i16>::new());
789                    assert_eq!(store.i32_arr, Vec::<i32>::new());
790                    assert_eq!(store.i64_arr, Vec::<i64>::new());
791                    assert_eq!(store.i128_arr, Vec::<i128>::new());
792                    assert_eq!(store.u8_arr, Vec::<u8>::new());
793                    assert_eq!(store.u16_arr, Vec::<u16>::new());
794                    assert_eq!(store.u32_arr, Vec::<u32>::new());
795                    assert_eq!(store.u64_arr, Vec::<u64>::new());
796                    assert_eq!(store.u128_arr, Vec::<u128>::new());
797                    assert_eq!(store.f32_arr, Vec::<f32>::new());
798                    assert_eq!(store.f64_arr, Vec::<f64>::new());
799                    assert_eq!(store.s_opt, None);
800                    assert_eq!(store.i8_opt, None);
801                    assert_eq!(store.i16_opt, None);
802                    assert_eq!(store.i32_opt, None);
803                    assert_eq!(store.i64_opt, None);
804                    assert_eq!(store.i128_opt, None);
805                    assert_eq!(store.u8_opt, None);
806                    assert_eq!(store.u16_opt, None);
807                    assert_eq!(store.u32_opt, None);
808                    assert_eq!(store.u64_opt, None);
809                    assert_eq!(store.u128_opt, None);
810                    assert_eq!(store.f32_opt, None);
811                    assert_eq!(store.f64_opt, None);
812                }
813                Err(_) => assert!(false),
814            }
815        }
816
817        #[test]
818        fn tests_set_field_values_if_number_format_error() {
819            let mut store = NoAttrOptions::with_defaults();
820
821            let mut m = HashMap::<&str, Vec<&str>>::new();
822            m.insert("i8_val", vec!["-1024"]);
823
824            match store.set_field_values(&m) {
825                Ok(_) => assert!(false),
826                Err(InvalidOption::OptionArgIsInvalid {
827                    store_key,
828                    option,
829                    opt_arg,
830                    details,
831                }) => {
832                    assert_eq!(store_key, "i8_val");
833                    assert_eq!(option, "i8_val");
834                    assert_eq!(opt_arg, "-1024");
835                    assert_eq!(details, "number too small to fit in target type");
836                }
837                Err(_) => assert!(false),
838            }
839
840            let mut m = HashMap::<&str, Vec<&str>>::new();
841            m.insert("i8_arr", vec!["abc"]);
842
843            match store.set_field_values(&m) {
844                Ok(_) => assert!(false),
845                Err(InvalidOption::OptionArgIsInvalid {
846                    store_key,
847                    option,
848                    opt_arg,
849                    details,
850                }) => {
851                    assert_eq!(store_key, "i8_arr");
852                    assert_eq!(option, "i8_arr");
853                    assert_eq!(opt_arg, "abc");
854                    assert_eq!(details, "invalid digit found in string");
855                }
856                Err(_) => assert!(false),
857            }
858
859            let mut m = HashMap::<&str, Vec<&str>>::new();
860            m.insert("i8_opt", vec!["abc"]);
861
862            match store.set_field_values(&m) {
863                Ok(_) => assert!(false),
864                Err(InvalidOption::OptionArgIsInvalid {
865                    store_key,
866                    option,
867                    opt_arg,
868                    details,
869                }) => {
870                    assert_eq!(store_key, "i8_opt");
871                    assert_eq!(option, "i8_opt");
872                    assert_eq!(opt_arg, "abc");
873                    assert_eq!(details, "invalid digit found in string");
874                }
875                Err(_) => assert!(false),
876            }
877        }
878    }
879
880    mod tests_when_with_attr {
881        use super::*;
882
883        #[derive(OptStore)]
884        struct WithAttrOptions {
885            #[opt(cfg = "b", desc = "The description of b_val")]
886            b_val: bool,
887
888            #[opt(cfg = "s,sss=ABC", desc = "The description of s_val", arg = "txt")]
889            s_val: String,
890
891            #[opt(cfg = "i8=-12", desc = "The description of i8_val", arg = "<n>")]
892            i8_val: i8,
893
894            #[opt(cfg = "i16=-123", desc = "The description of i16_val", arg = "<n>")]
895            i16_val: i16,
896
897            #[opt(cfg = "i32=-234", desc = "The description of i32_val", arg = "<n>")]
898            i32_val: i32,
899
900            #[opt(cfg = "i64=-345", desc = "The description of i64_val", arg = "<n>")]
901            i64_val: i64,
902
903            #[opt(cfg = "i128=-456", desc = "The description of i128_val", arg = "<n>")]
904            i128_val: i128,
905
906            #[opt(cfg = "u8=123", desc = "The description of u8_val", arg = "<n>")]
907            u8_val: u8,
908
909            #[opt(cfg = "u16=234", desc = "The description of u16_val", arg = "<n>")]
910            u16_val: u16,
911
912            #[opt(cfg = "u32=345", desc = "The description of u32_val", arg = "<n>")]
913            u32_val: u32,
914
915            #[opt(cfg = "u64=456", desc = "The description of u64_val", arg = "<n>")]
916            u64_val: u64,
917
918            #[opt(cfg = "u128=567", desc = "The description of u128_val", arg = "<n>")]
919            u128_val: u128,
920
921            #[opt(cfg = "f32=0.678", desc = "The description of f32_val", arg = "<n>")]
922            f32_val: f32,
923
924            #[opt(cfg = "f64=7.89", desc = "The description of f64_val", arg = "<n>")]
925            f64_val: f64,
926
927            #[opt(
928                cfg = "ss=/[A,a/B,b/C,c]",
929                desc = "The description of s_arr",
930                arg = "<s>"
931            )]
932            s_arr: Vec<String>,
933
934            #[opt(cfg = "ii8=[-1,2,-3]", desc = "The description of i8_arr", arg = "<n>")]
935            i8_arr: Vec<i8>,
936
937            #[opt(
938                cfg = "ii16=[2,-3,4]",
939                desc = "The description of i16_arr",
940                arg = "<n>"
941            )]
942            i16_arr: Vec<i16>,
943
944            #[opt(
945                cfg = "ii32=[-3,4,-5]",
946                desc = "The description of i32_arr",
947                arg = "<n>"
948            )]
949            i32_arr: Vec<i32>,
950
951            #[opt(
952                cfg = "ii64=[4,-5,6]",
953                desc = "The description of i64_arr",
954                arg = "<n>"
955            )]
956            i64_arr: Vec<i64>,
957
958            #[opt(
959                cfg = "ii128=[-5,6,-7]",
960                desc = "The description of i128_arr",
961                arg = "<n>"
962            )]
963            i128_arr: Vec<i128>,
964
965            #[opt(cfg = "uu8=[1,2,3]", desc = "The description of u8_arr", arg = "<n>")]
966            u8_arr: Vec<u8>,
967
968            #[opt(cfg = "uu16=[2,3,4]", desc = "The description of u16_arr", arg = "<n>")]
969            u16_arr: Vec<u16>,
970
971            #[opt(cfg = "uu32=[3,4,5]", desc = "The description of u32_arr", arg = "<n>")]
972            u32_arr: Vec<u32>,
973
974            #[opt(cfg = "uu64=[4,5,6]", desc = "The description of u64_arr", arg = "<n>")]
975            u64_arr: Vec<u64>,
976
977            #[opt(
978                cfg = "uu128=[5,6,7]",
979                desc = "The description of u128_arr",
980                arg = "<n>"
981            )]
982            u128_arr: Vec<u128>,
983
984            #[opt(
985                cfg = "ff32=[0.6,0.7]",
986                desc = "The description of f32_arr",
987                arg = "<n>"
988            )]
989            f32_arr: Vec<f32>,
990
991            #[opt(
992                cfg = "ff64=[0.7,0.8]",
993                desc = "The description of f64_arr",
994                arg = "<n>"
995            )]
996            f64_arr: Vec<f64>,
997
998            #[opt(cfg = "=ABC", desc = "The description of s_opt", arg = "<s>")]
999            s_opt: Option<String>,
1000
1001            #[opt(cfg = "=-12", desc = "The description of i8_opt", arg = "<n>")]
1002            i8_opt: Option<i8>,
1003
1004            #[opt(cfg = "=-234", desc = "The description of i16_opt", arg = "<n>")]
1005            i16_opt: Option<i16>,
1006
1007            #[opt(cfg = "=-345", desc = "The description of i32_opt", arg = "<n>")]
1008            i32_opt: Option<i32>,
1009
1010            #[opt(cfg = "=-456", desc = "The description of i64_opt", arg = "<n>")]
1011            i64_opt: Option<i64>,
1012
1013            #[opt(cfg = "=-567", desc = "The description of i128_opt", arg = "<n>")]
1014            i128_opt: Option<i128>,
1015
1016            #[opt(cfg = "=123", desc = "The description of u8_opt", arg = "<n>")]
1017            u8_opt: Option<u8>,
1018
1019            #[opt(cfg = "=234", desc = "The description of u16_opt", arg = "<n>")]
1020            u16_opt: Option<u16>,
1021
1022            #[opt(cfg = "=345", desc = "The description of u32_opt", arg = "<n>")]
1023            u32_opt: Option<u32>,
1024
1025            #[opt(cfg = "=456", desc = "The description of u64_opt", arg = "<n>")]
1026            u64_opt: Option<u64>,
1027
1028            #[opt(cfg = "=567", desc = "The description of u128_opt", arg = "<n>")]
1029            u128_opt: Option<u128>,
1030
1031            #[opt(cfg = "=0.1", desc = "The description of f32_opt", arg = "<n>")]
1032            f32_opt: Option<f32>,
1033
1034            #[opt(cfg = "=1.2", desc = "The description of f64_opt", arg = "<n>")]
1035            f64_opt: Option<f64>,
1036        }
1037
1038        #[test]
1039        fn test_create_instance_with_defaults() {
1040            let store = WithAttrOptions::with_defaults();
1041            assert_eq!(store.b_val, false);
1042            assert_eq!(store.s_val, "ABC".to_string());
1043            assert_eq!(store.i8_val, -12);
1044            assert_eq!(store.i16_val, -123);
1045            assert_eq!(store.i32_val, -234);
1046            assert_eq!(store.i64_val, -345);
1047            assert_eq!(store.i128_val, -456);
1048            assert_eq!(store.u8_val, 123);
1049            assert_eq!(store.u16_val, 234);
1050            assert_eq!(store.u32_val, 345);
1051            assert_eq!(store.u64_val, 456);
1052            assert_eq!(store.u128_val, 567);
1053            assert_eq!(store.f32_val, 0.678);
1054            assert_eq!(store.f64_val, 7.89);
1055            assert_eq!(
1056                store.s_arr,
1057                vec!["A,a".to_string(), "B,b".to_string(), "C,c".to_string()]
1058            );
1059            assert_eq!(store.i8_arr, vec![-1, 2, -3]);
1060            assert_eq!(store.i16_arr, vec![2, -3, 4]);
1061            assert_eq!(store.i32_arr, vec![-3, 4, -5]);
1062            assert_eq!(store.i64_arr, vec![4, -5, 6]);
1063            assert_eq!(store.i128_arr, vec![-5, 6, -7]);
1064            assert_eq!(store.u8_arr, vec![1, 2, 3]);
1065            assert_eq!(store.u16_arr, vec![2, 3, 4]);
1066            assert_eq!(store.u32_arr, vec![3, 4, 5]);
1067            assert_eq!(store.u64_arr, vec![4, 5, 6]);
1068            assert_eq!(store.u128_arr, vec![5, 6, 7]);
1069            assert_eq!(store.f32_arr, vec![0.6, 0.7]);
1070            assert_eq!(store.f64_arr, vec![0.7, 0.8]);
1071            assert_eq!(store.s_opt, Some("ABC".to_string()));
1072            assert_eq!(store.i8_opt, Some(-12));
1073            assert_eq!(store.i16_opt, Some(-234));
1074            assert_eq!(store.i32_opt, Some(-345));
1075            assert_eq!(store.i64_opt, Some(-456));
1076            assert_eq!(store.i128_opt, Some(-567));
1077            assert_eq!(store.u8_opt, Some(123));
1078            assert_eq!(store.u16_opt, Some(234));
1079            assert_eq!(store.u32_opt, Some(345));
1080            assert_eq!(store.u64_opt, Some(456));
1081            assert_eq!(store.u128_opt, Some(567));
1082            assert_eq!(store.f32_opt, Some(0.1));
1083            assert_eq!(store.f64_opt, Some(1.2));
1084        }
1085
1086        #[test]
1087        fn test_make_opt_cfgs_for_store() {
1088            let mut store = WithAttrOptions::with_defaults();
1089            let cfgs = cliargs::make_opt_cfgs_for(&mut store);
1090            assert_eq!(cfgs.len(), 40);
1091
1092            let cfg = &cfgs[0];
1093            assert_eq!(cfg.store_key, "b_val");
1094            assert_eq!(cfg.names, vec!["b"]);
1095            assert_eq!(cfg.has_arg, false);
1096            assert_eq!(cfg.is_array, false);
1097            assert_eq!(cfg.defaults, None);
1098            assert_eq!(cfg.desc, "The description of b_val".to_string());
1099            assert_eq!(cfg.arg_in_help, "".to_string());
1100
1101            let cfg = &cfgs[1];
1102            assert_eq!(cfg.store_key, "s_val");
1103            assert_eq!(cfg.names, vec!["s".to_string(), "sss".to_string()]);
1104            assert_eq!(cfg.has_arg, true);
1105            assert_eq!(cfg.is_array, false);
1106            assert_eq!(cfg.defaults, Some(vec!["ABC".to_string()]));
1107            assert_eq!(cfg.desc, "The description of s_val".to_string());
1108            assert_eq!(cfg.arg_in_help, "txt".to_string());
1109
1110            let cfg = &cfgs[2];
1111            assert_eq!(cfg.store_key, "i8_val");
1112            assert_eq!(cfg.names, vec!["i8"]);
1113            assert_eq!(cfg.has_arg, true);
1114            assert_eq!(cfg.is_array, false);
1115            assert_eq!(cfg.defaults, Some(vec!["-12".to_string()]));
1116            assert_eq!(cfg.desc, "The description of i8_val".to_string());
1117            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1118
1119            let cfg = &cfgs[3];
1120            assert_eq!(cfg.store_key, "i16_val");
1121            assert_eq!(cfg.names, vec!["i16"]);
1122            assert_eq!(cfg.has_arg, true);
1123            assert_eq!(cfg.is_array, false);
1124            assert_eq!(cfg.defaults, Some(vec!["-123".to_string()]));
1125            assert_eq!(cfg.desc, "The description of i16_val".to_string());
1126            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1127
1128            let cfg = &cfgs[4];
1129            assert_eq!(cfg.store_key, "i32_val");
1130            assert_eq!(cfg.names, vec!["i32"]);
1131            assert_eq!(cfg.has_arg, true);
1132            assert_eq!(cfg.is_array, false);
1133            assert_eq!(cfg.defaults, Some(vec!["-234".to_string()]));
1134            assert_eq!(cfg.desc, "The description of i32_val".to_string());
1135            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1136
1137            let cfg = &cfgs[5];
1138            assert_eq!(cfg.store_key, "i64_val");
1139            assert_eq!(cfg.names, vec!["i64"]);
1140            assert_eq!(cfg.has_arg, true);
1141            assert_eq!(cfg.is_array, false);
1142            assert_eq!(cfg.defaults, Some(vec!["-345".to_string()]));
1143            assert_eq!(cfg.desc, "The description of i64_val".to_string());
1144            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1145
1146            let cfg = &cfgs[6];
1147            assert_eq!(cfg.store_key, "i128_val");
1148            assert_eq!(cfg.names, vec!["i128"]);
1149            assert_eq!(cfg.has_arg, true);
1150            assert_eq!(cfg.is_array, false);
1151            assert_eq!(cfg.defaults, Some(vec!["-456".to_string()]));
1152            assert_eq!(cfg.desc, "The description of i128_val".to_string());
1153            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1154
1155            let cfg = &cfgs[7];
1156            assert_eq!(cfg.store_key, "u8_val");
1157            assert_eq!(cfg.names, vec!["u8"]);
1158            assert_eq!(cfg.has_arg, true);
1159            assert_eq!(cfg.is_array, false);
1160            assert_eq!(cfg.defaults, Some(vec!["123".to_string()]));
1161            assert_eq!(cfg.desc, "The description of u8_val".to_string());
1162            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1163
1164            let cfg = &cfgs[8];
1165            assert_eq!(cfg.store_key, "u16_val");
1166            assert_eq!(cfg.names, vec!["u16"]);
1167            assert_eq!(cfg.has_arg, true);
1168            assert_eq!(cfg.is_array, false);
1169            assert_eq!(cfg.defaults, Some(vec!["234".to_string()]));
1170            assert_eq!(cfg.desc, "The description of u16_val".to_string());
1171            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1172
1173            let cfg = &cfgs[9];
1174            assert_eq!(cfg.store_key, "u32_val");
1175            assert_eq!(cfg.names, vec!["u32"]);
1176            assert_eq!(cfg.has_arg, true);
1177            assert_eq!(cfg.is_array, false);
1178            assert_eq!(cfg.defaults, Some(vec!["345".to_string()]));
1179            assert_eq!(cfg.desc, "The description of u32_val".to_string());
1180            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1181
1182            let cfg = &cfgs[10];
1183            assert_eq!(cfg.store_key, "u64_val");
1184            assert_eq!(cfg.names, vec!["u64"]);
1185            assert_eq!(cfg.has_arg, true);
1186            assert_eq!(cfg.is_array, false);
1187            assert_eq!(cfg.defaults, Some(vec!["456".to_string()]));
1188            assert_eq!(cfg.desc, "The description of u64_val".to_string());
1189            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1190
1191            let cfg = &cfgs[11];
1192            assert_eq!(cfg.store_key, "u128_val");
1193            assert_eq!(cfg.names, vec!["u128"]);
1194            assert_eq!(cfg.has_arg, true);
1195            assert_eq!(cfg.is_array, false);
1196            assert_eq!(cfg.defaults, Some(vec!["567".to_string()]));
1197            assert_eq!(cfg.desc, "The description of u128_val".to_string());
1198            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1199
1200            let cfg = &cfgs[12];
1201            assert_eq!(cfg.store_key, "f32_val");
1202            assert_eq!(cfg.names, vec!["f32"]);
1203            assert_eq!(cfg.has_arg, true);
1204            assert_eq!(cfg.is_array, false);
1205            assert_eq!(cfg.defaults, Some(vec!["0.678".to_string()]));
1206            assert_eq!(cfg.desc, "The description of f32_val".to_string());
1207            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1208
1209            let cfg = &cfgs[13];
1210            assert_eq!(cfg.store_key, "f64_val");
1211            assert_eq!(cfg.names, vec!["f64"]);
1212            assert_eq!(cfg.has_arg, true);
1213            assert_eq!(cfg.is_array, false);
1214            assert_eq!(cfg.defaults, Some(vec!["7.89".to_string()]));
1215            assert_eq!(cfg.desc, "The description of f64_val".to_string());
1216            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1217
1218            let cfg = &cfgs[14];
1219            assert_eq!(cfg.store_key, "s_arr");
1220            assert_eq!(cfg.names, vec!["ss".to_string()]);
1221            assert_eq!(cfg.has_arg, true);
1222            assert_eq!(cfg.is_array, true);
1223            assert_eq!(
1224                cfg.defaults,
1225                Some(vec![
1226                    "A,a".to_string(),
1227                    "B,b".to_string(),
1228                    "C,c".to_string()
1229                ])
1230            );
1231            assert_eq!(cfg.desc, "The description of s_arr".to_string());
1232            assert_eq!(cfg.arg_in_help, "<s>".to_string());
1233
1234            let cfg = &cfgs[15];
1235            assert_eq!(cfg.store_key, "i8_arr");
1236            assert_eq!(cfg.names, vec!["ii8".to_string()]);
1237            assert_eq!(cfg.has_arg, true);
1238            assert_eq!(cfg.is_array, true);
1239            assert_eq!(
1240                cfg.defaults,
1241                Some(vec!["-1".to_string(), "2".to_string(), "-3".to_string()])
1242            );
1243            assert_eq!(cfg.desc, "The description of i8_arr".to_string());
1244            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1245
1246            let cfg = &cfgs[16];
1247            assert_eq!(cfg.store_key, "i16_arr");
1248            assert_eq!(cfg.names, vec!["ii16".to_string()]);
1249            assert_eq!(cfg.has_arg, true);
1250            assert_eq!(cfg.is_array, true);
1251            assert_eq!(
1252                cfg.defaults,
1253                Some(vec!["2".to_string(), "-3".to_string(), "4".to_string()])
1254            );
1255            assert_eq!(cfg.desc, "The description of i16_arr".to_string());
1256            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1257
1258            let cfg = &cfgs[17];
1259            assert_eq!(cfg.store_key, "i32_arr");
1260            assert_eq!(cfg.names, vec!["ii32".to_string()]);
1261            assert_eq!(cfg.has_arg, true);
1262            assert_eq!(cfg.is_array, true);
1263            assert_eq!(
1264                cfg.defaults,
1265                Some(vec!["-3".to_string(), "4".to_string(), "-5".to_string()])
1266            );
1267            assert_eq!(cfg.desc, "The description of i32_arr".to_string());
1268            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1269
1270            let cfg = &cfgs[18];
1271            assert_eq!(cfg.store_key, "i64_arr");
1272            assert_eq!(cfg.names, vec!["ii64".to_string()]);
1273            assert_eq!(cfg.has_arg, true);
1274            assert_eq!(cfg.is_array, true);
1275            assert_eq!(
1276                cfg.defaults,
1277                Some(vec!["4".to_string(), "-5".to_string(), "6".to_string()])
1278            );
1279            assert_eq!(cfg.desc, "The description of i64_arr".to_string());
1280            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1281
1282            let cfg = &cfgs[19];
1283            assert_eq!(cfg.store_key, "i128_arr");
1284            assert_eq!(cfg.names, vec!["ii128".to_string()]);
1285            assert_eq!(cfg.has_arg, true);
1286            assert_eq!(cfg.is_array, true);
1287            assert_eq!(
1288                cfg.defaults,
1289                Some(vec!["-5".to_string(), "6".to_string(), "-7".to_string()])
1290            );
1291            assert_eq!(cfg.desc, "The description of i128_arr".to_string());
1292            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1293
1294            let cfg = &cfgs[20];
1295            assert_eq!(cfg.store_key, "u8_arr");
1296            assert_eq!(cfg.names, vec!["uu8".to_string()]);
1297            assert_eq!(cfg.has_arg, true);
1298            assert_eq!(cfg.is_array, true);
1299            assert_eq!(
1300                cfg.defaults,
1301                Some(vec!["1".to_string(), "2".to_string(), "3".to_string()])
1302            );
1303            assert_eq!(cfg.desc, "The description of u8_arr".to_string());
1304            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1305
1306            let cfg = &cfgs[21];
1307            assert_eq!(cfg.store_key, "u16_arr");
1308            assert_eq!(cfg.names, vec!["uu16".to_string()]);
1309            assert_eq!(cfg.has_arg, true);
1310            assert_eq!(cfg.is_array, true);
1311            assert_eq!(
1312                cfg.defaults,
1313                Some(vec!["2".to_string(), "3".to_string(), "4".to_string()])
1314            );
1315            assert_eq!(cfg.desc, "The description of u16_arr".to_string());
1316            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1317
1318            let cfg = &cfgs[22];
1319            assert_eq!(cfg.store_key, "u32_arr");
1320            assert_eq!(cfg.names, vec!["uu32".to_string()]);
1321            assert_eq!(cfg.has_arg, true);
1322            assert_eq!(cfg.is_array, true);
1323            assert_eq!(
1324                cfg.defaults,
1325                Some(vec!["3".to_string(), "4".to_string(), "5".to_string()])
1326            );
1327            assert_eq!(cfg.desc, "The description of u32_arr".to_string());
1328            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1329
1330            let cfg = &cfgs[23];
1331            assert_eq!(cfg.store_key, "u64_arr");
1332            assert_eq!(cfg.names, vec!["uu64".to_string()]);
1333            assert_eq!(cfg.has_arg, true);
1334            assert_eq!(cfg.is_array, true);
1335            assert_eq!(
1336                cfg.defaults,
1337                Some(vec!["4".to_string(), "5".to_string(), "6".to_string()])
1338            );
1339            assert_eq!(cfg.desc, "The description of u64_arr".to_string());
1340            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1341
1342            let cfg = &cfgs[24];
1343            assert_eq!(cfg.store_key, "u128_arr");
1344            assert_eq!(cfg.names, vec!["uu128".to_string()]);
1345            assert_eq!(cfg.has_arg, true);
1346            assert_eq!(cfg.is_array, true);
1347            assert_eq!(
1348                cfg.defaults,
1349                Some(vec!["5".to_string(), "6".to_string(), "7".to_string()])
1350            );
1351            assert_eq!(cfg.desc, "The description of u128_arr".to_string());
1352            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1353
1354            let cfg = &cfgs[25];
1355            assert_eq!(cfg.store_key, "f32_arr");
1356            assert_eq!(cfg.names, vec!["ff32".to_string()]);
1357            assert_eq!(cfg.has_arg, true);
1358            assert_eq!(cfg.is_array, true);
1359            assert_eq!(
1360                cfg.defaults,
1361                Some(vec!["0.6".to_string(), "0.7".to_string()])
1362            );
1363            assert_eq!(cfg.desc, "The description of f32_arr".to_string());
1364            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1365
1366            let cfg = &cfgs[26];
1367            assert_eq!(cfg.store_key, "f64_arr");
1368            assert_eq!(cfg.names, vec!["ff64".to_string()]);
1369            assert_eq!(cfg.has_arg, true);
1370            assert_eq!(cfg.is_array, true);
1371            assert_eq!(
1372                cfg.defaults,
1373                Some(vec!["0.7".to_string(), "0.8".to_string()])
1374            );
1375            assert_eq!(cfg.desc, "The description of f64_arr".to_string());
1376            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1377
1378            let cfg = &cfgs[27];
1379            assert_eq!(cfg.store_key, "s_opt");
1380            assert_eq!(cfg.names, Vec::<String>::new());
1381            assert_eq!(cfg.has_arg, true);
1382            assert_eq!(cfg.is_array, false);
1383            assert_eq!(cfg.defaults, Some(vec!["ABC".to_string()]));
1384            assert_eq!(cfg.desc, "The description of s_opt".to_string());
1385            assert_eq!(cfg.arg_in_help, "<s>".to_string());
1386
1387            let cfg = &cfgs[28];
1388            assert_eq!(cfg.store_key, "i8_opt");
1389            assert_eq!(cfg.names, Vec::<String>::new());
1390            assert_eq!(cfg.has_arg, true);
1391            assert_eq!(cfg.is_array, false);
1392            assert_eq!(cfg.defaults, Some(vec!["-12".to_string()]));
1393            assert_eq!(cfg.desc, "The description of i8_opt".to_string());
1394            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1395
1396            let cfg = &cfgs[29];
1397            assert_eq!(cfg.store_key, "i16_opt");
1398            assert_eq!(cfg.names, Vec::<String>::new());
1399            assert_eq!(cfg.has_arg, true);
1400            assert_eq!(cfg.is_array, false);
1401            assert_eq!(cfg.defaults, Some(vec!["-234".to_string()]));
1402            assert_eq!(cfg.desc, "The description of i16_opt".to_string());
1403            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1404
1405            let cfg = &cfgs[30];
1406            assert_eq!(cfg.store_key, "i32_opt");
1407            assert_eq!(cfg.names, Vec::<String>::new());
1408            assert_eq!(cfg.has_arg, true);
1409            assert_eq!(cfg.is_array, false);
1410            assert_eq!(cfg.defaults, Some(vec!["-345".to_string()]));
1411            assert_eq!(cfg.desc, "The description of i32_opt".to_string());
1412            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1413
1414            let cfg = &cfgs[31];
1415            assert_eq!(cfg.store_key, "i64_opt");
1416            assert_eq!(cfg.names, Vec::<String>::new());
1417            assert_eq!(cfg.has_arg, true);
1418            assert_eq!(cfg.is_array, false);
1419            assert_eq!(cfg.defaults, Some(vec!["-456".to_string()]));
1420            assert_eq!(cfg.desc, "The description of i64_opt".to_string());
1421            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1422
1423            let cfg = &cfgs[32];
1424            assert_eq!(cfg.store_key, "i128_opt");
1425            assert_eq!(cfg.names, Vec::<String>::new());
1426            assert_eq!(cfg.has_arg, true);
1427            assert_eq!(cfg.is_array, false);
1428            assert_eq!(cfg.defaults, Some(vec!["-567".to_string()]));
1429            assert_eq!(cfg.desc, "The description of i128_opt".to_string());
1430            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1431
1432            let cfg = &cfgs[33];
1433            assert_eq!(cfg.store_key, "u8_opt");
1434            assert_eq!(cfg.names, Vec::<String>::new());
1435            assert_eq!(cfg.has_arg, true);
1436            assert_eq!(cfg.is_array, false);
1437            assert_eq!(cfg.defaults, Some(vec!["123".to_string()]));
1438            assert_eq!(cfg.desc, "The description of u8_opt".to_string());
1439            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1440
1441            let cfg = &cfgs[34];
1442            assert_eq!(cfg.store_key, "u16_opt");
1443            assert_eq!(cfg.names, Vec::<String>::new());
1444            assert_eq!(cfg.has_arg, true);
1445            assert_eq!(cfg.is_array, false);
1446            assert_eq!(cfg.defaults, Some(vec!["234".to_string()]));
1447            assert_eq!(cfg.desc, "The description of u16_opt".to_string());
1448            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1449
1450            let cfg = &cfgs[35];
1451            assert_eq!(cfg.store_key, "u32_opt");
1452            assert_eq!(cfg.names, Vec::<String>::new());
1453            assert_eq!(cfg.has_arg, true);
1454            assert_eq!(cfg.is_array, false);
1455            assert_eq!(cfg.defaults, Some(vec!["345".to_string()]));
1456            assert_eq!(cfg.desc, "The description of u32_opt".to_string());
1457            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1458
1459            let cfg = &cfgs[36];
1460            assert_eq!(cfg.store_key, "u64_opt");
1461            assert_eq!(cfg.names, Vec::<String>::new());
1462            assert_eq!(cfg.has_arg, true);
1463            assert_eq!(cfg.is_array, false);
1464            assert_eq!(cfg.defaults, Some(vec!["456".to_string()]));
1465            assert_eq!(cfg.desc, "The description of u64_opt".to_string());
1466            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1467
1468            let cfg = &cfgs[37];
1469            assert_eq!(cfg.store_key, "u128_opt");
1470            assert_eq!(cfg.names, Vec::<String>::new());
1471            assert_eq!(cfg.has_arg, true);
1472            assert_eq!(cfg.is_array, false);
1473            assert_eq!(cfg.defaults, Some(vec!["567".to_string()]));
1474            assert_eq!(cfg.desc, "The description of u128_opt".to_string());
1475            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1476
1477            let cfg = &cfgs[38];
1478            assert_eq!(cfg.store_key, "f32_opt");
1479            assert_eq!(cfg.names, Vec::<String>::new());
1480            assert_eq!(cfg.has_arg, true);
1481            assert_eq!(cfg.is_array, false);
1482            assert_eq!(cfg.defaults, Some(vec!["0.1".to_string()]));
1483            assert_eq!(cfg.desc, "The description of f32_opt".to_string());
1484            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1485
1486            let cfg = &cfgs[39];
1487            assert_eq!(cfg.store_key, "f64_opt");
1488            assert_eq!(cfg.names, Vec::<String>::new());
1489            assert_eq!(cfg.has_arg, true);
1490            assert_eq!(cfg.is_array, false);
1491            assert_eq!(cfg.defaults, Some(vec!["1.2".to_string()]));
1492            assert_eq!(cfg.desc, "The description of f64_opt".to_string());
1493            assert_eq!(cfg.arg_in_help, "<n>".to_string());
1494        }
1495
1496        #[test]
1497        fn test_defaults_for_string_array_field() {
1498            #[derive(OptStore)]
1499            struct MyOptions {
1500                #[opt(cfg = "=[]")]
1501                empty: Vec<String>,
1502                #[opt(cfg = "=[a]")]
1503                single_str: Vec<String>,
1504                #[opt(cfg = "=[a,b]")]
1505                multiple_str: Vec<String>,
1506                #[opt(cfg = "=")]
1507                empty_str: Vec<String>,
1508            }
1509            let mut store = MyOptions::with_defaults();
1510            let cfgs = cliargs::make_opt_cfgs_for(&mut store);
1511            assert_eq!(cfgs.len(), 4);
1512            assert_eq!(cfgs[0].store_key, "empty".to_string());
1513            assert_eq!(cfgs[0].defaults, Some(Vec::<String>::new()));
1514            assert_eq!(cfgs[1].store_key, "single_str".to_string());
1515            assert_eq!(cfgs[1].defaults, Some(vec!["a".to_string()]));
1516            assert_eq!(cfgs[2].store_key, "multiple_str".to_string());
1517            assert_eq!(
1518                cfgs[2].defaults,
1519                Some(vec!["a".to_string(), "b".to_string()])
1520            );
1521            assert_eq!(cfgs[3].store_key, "empty_str".to_string());
1522            assert_eq!(cfgs[3].defaults, Some(vec!["".to_string()]));
1523        }
1524    }
1525}
1526
1527#[cfg(test)]
1528mod tests_of_parse_for {
1529    use crate as cliargs;
1530
1531    #[derive(cliargs::OptStore, Debug)]
1532    struct MyOptions {
1533        #[opt(cfg = "b-val")]
1534        b_val: bool,
1535
1536        #[opt(cfg = "s-val")]
1537        s_val: String,
1538
1539        #[opt(cfg = "i8-val")]
1540        i8_val: i8,
1541
1542        #[opt(cfg = "i16-val")]
1543        i16_val: i16,
1544
1545        #[opt(cfg = "i32-val")]
1546        i32_val: i32,
1547
1548        #[opt(cfg = "i64-val")]
1549        i64_val: i64,
1550
1551        #[opt(cfg = "i128-val")]
1552        i128_val: i128,
1553
1554        #[opt(cfg = "u8-val")]
1555        u8_val: u8,
1556
1557        #[opt(cfg = "u16-val")]
1558        u16_val: u16,
1559
1560        #[opt(cfg = "u32-val")]
1561        u32_val: u32,
1562
1563        #[opt(cfg = "u64-val")]
1564        u64_val: u64,
1565
1566        #[opt(cfg = "u128-val")]
1567        u128_val: u128,
1568
1569        #[opt(cfg = "f32-val")]
1570        f32_val: f32,
1571
1572        #[opt(cfg = "f64-val")]
1573        f64_val: f64,
1574
1575        #[opt(cfg = "s-arr")]
1576        s_arr: Vec<String>,
1577
1578        #[opt(cfg = "i8-arr")]
1579        i8_arr: Vec<i8>,
1580
1581        #[opt(cfg = "i16-arr")]
1582        i16_arr: Vec<i16>,
1583
1584        #[opt(cfg = "i32-arr")]
1585        i32_arr: Vec<i32>,
1586
1587        #[opt(cfg = "i64-arr")]
1588        i64_arr: Vec<i64>,
1589
1590        #[opt(cfg = "i128-arr")]
1591        i128_arr: Vec<i128>,
1592
1593        #[opt(cfg = "u8-arr")]
1594        u8_arr: Vec<u8>,
1595
1596        #[opt(cfg = "u16-arr")]
1597        u16_arr: Vec<u16>,
1598
1599        #[opt(cfg = "u32-arr")]
1600        u32_arr: Vec<u32>,
1601
1602        #[opt(cfg = "u64-arr")]
1603        u64_arr: Vec<u64>,
1604
1605        #[opt(cfg = "u128-arr")]
1606        u128_arr: Vec<u128>,
1607
1608        #[opt(cfg = "f32-arr")]
1609        f32_arr: Vec<f32>,
1610
1611        #[opt(cfg = "f64-arr")]
1612        f64_arr: Vec<f64>,
1613
1614        #[opt(cfg = "s-opt")]
1615        s_opt: Option<String>,
1616
1617        #[opt(cfg = "i8-opt")]
1618        i8_opt: Option<i8>,
1619
1620        #[opt(cfg = "i16-opt")]
1621        i16_opt: Option<i16>,
1622
1623        #[opt(cfg = "i32-opt")]
1624        i32_opt: Option<i32>,
1625
1626        #[opt(cfg = "i64-opt")]
1627        i64_opt: Option<i64>,
1628
1629        #[opt(cfg = "i128-opt")]
1630        i128_opt: Option<i128>,
1631
1632        #[opt(cfg = "u8-opt")]
1633        u8_opt: Option<u8>,
1634
1635        #[opt(cfg = "u16-opt")]
1636        u16_opt: Option<u16>,
1637
1638        #[opt(cfg = "u32-opt")]
1639        u32_opt: Option<u32>,
1640
1641        #[opt(cfg = "u64-opt")]
1642        u64_opt: Option<u64>,
1643
1644        #[opt(cfg = "u128-opt")]
1645        u128_opt: Option<u128>,
1646
1647        #[opt(cfg = "f32-opt")]
1648        f32_opt: Option<f32>,
1649
1650        #[opt(cfg = "f64-opt")]
1651        f64_opt: Option<f64>,
1652    }
1653
1654    #[test]
1655    fn test_parse_for_my_options() {
1656        let mut store = MyOptions::with_defaults();
1657        let mut cmd = cliargs::Cmd::with_strings([
1658            "/path/to/command".to_string(),
1659            "--b-val".to_string(),
1660            "--s-val".to_string(),
1661            "abcd".to_string(),
1662            "--i8-val=1".to_string(),
1663            "--i16-val=-12".to_string(),
1664            "--i32-val=123".to_string(),
1665            "--i64-val=-1234".to_string(),
1666            "--i128-val=12345".to_string(),
1667            "--u8-val=1".to_string(),
1668            "--u16-val=12".to_string(),
1669            "--u32-val=123".to_string(),
1670            "--u64-val=1234".to_string(),
1671            "--u128-val=12345".to_string(),
1672            "--f32-val=1.23".to_string(),
1673            "--f64-val=-4.56".to_string(),
1674            "--s-arr=a".to_string(),
1675            "--s-arr".to_string(),
1676            "b".to_string(),
1677            "--s-arr=c".to_string(),
1678            "--i8-arr=-1".to_string(),
1679            "--i8-arr=-2".to_string(),
1680            "--i16-arr=-1".to_string(),
1681            "--i16-arr=-2".to_string(),
1682            "--i32-arr=-1".to_string(),
1683            "--i32-arr=-2".to_string(),
1684            "--i64-arr=-1".to_string(),
1685            "--i64-arr=-2".to_string(),
1686            "--i128-arr=-1".to_string(),
1687            "--i128-arr=-2".to_string(),
1688            "--u8-arr=3".to_string(),
1689            "--u8-arr=4".to_string(),
1690            "--u16-arr=3".to_string(),
1691            "--u16-arr=4".to_string(),
1692            "--u32-arr=3".to_string(),
1693            "--u32-arr=4".to_string(),
1694            "--u64-arr=3".to_string(),
1695            "--u64-arr=4".to_string(),
1696            "--u128-arr=3".to_string(),
1697            "--u128-arr=4".to_string(),
1698            "--f32-arr=0.1".to_string(),
1699            "--f32-arr=-0.2".to_string(),
1700            "--f64-arr=-0.3".to_string(),
1701            "--f64-arr=0.4".to_string(),
1702            "--s-opt=aaa".to_string(),
1703            "--i8-opt=-1".to_string(),
1704            "--i16-opt=-2".to_string(),
1705            "--i32-opt=-3".to_string(),
1706            "--i64-opt=-4".to_string(),
1707            "--i128-opt=-5".to_string(),
1708            "--u8-opt=1".to_string(),
1709            "--u16-opt=2".to_string(),
1710            "--u32-opt=3".to_string(),
1711            "--u64-opt=4".to_string(),
1712            "--u128-opt=5".to_string(),
1713            "--f32-opt=-0.1".to_string(),
1714            "--f64-opt=2.3".to_string(),
1715        ]);
1716
1717        assert_eq!(cmd.parse_for(&mut store), Ok(()));
1718
1719        assert_eq!(store.b_val, true);
1720        assert_eq!(store.s_val, "abcd".to_string());
1721        assert_eq!(store.i8_val, 1);
1722        assert_eq!(store.i16_val, -12);
1723        assert_eq!(store.i32_val, 123);
1724        assert_eq!(store.i64_val, -1234);
1725        assert_eq!(store.i128_val, 12345);
1726        assert_eq!(store.u8_val, 1);
1727        assert_eq!(store.u16_val, 12);
1728        assert_eq!(store.u32_val, 123);
1729        assert_eq!(store.u64_val, 1234);
1730        assert_eq!(store.u128_val, 12345);
1731        assert_eq!(store.f32_val, 1.23);
1732        assert_eq!(store.f64_val, -4.56);
1733        assert_eq!(
1734            store.s_arr,
1735            vec!["a".to_string(), "b".to_string(), "c".to_string(),]
1736        );
1737        assert_eq!(store.i8_arr, vec![-1, -2]);
1738        assert_eq!(store.i16_arr, vec![-1, -2]);
1739        assert_eq!(store.i32_arr, vec![-1, -2]);
1740        assert_eq!(store.i64_arr, vec![-1, -2]);
1741        assert_eq!(store.i128_arr, vec![-1, -2]);
1742        assert_eq!(store.u8_arr, vec![3, 4]);
1743        assert_eq!(store.u16_arr, vec![3, 4]);
1744        assert_eq!(store.u32_arr, vec![3, 4]);
1745        assert_eq!(store.u64_arr, vec![3, 4]);
1746        assert_eq!(store.u128_arr, vec![3, 4]);
1747        assert_eq!(store.f32_arr, vec![0.1, -0.2]);
1748        assert_eq!(store.f64_arr, vec![-0.3, 0.4]);
1749        assert_eq!(store.s_opt, Some("aaa".to_string()));
1750        assert_eq!(store.i8_opt, Some(-1));
1751        assert_eq!(store.i16_opt, Some(-2));
1752        assert_eq!(store.i32_opt, Some(-3));
1753        assert_eq!(store.i64_opt, Some(-4));
1754        assert_eq!(store.i128_opt, Some(-5));
1755        assert_eq!(store.u8_opt, Some(1));
1756        assert_eq!(store.u16_opt, Some(2));
1757        assert_eq!(store.u32_opt, Some(3));
1758        assert_eq!(store.u64_opt, Some(4));
1759        assert_eq!(store.u128_opt, Some(5));
1760        assert_eq!(store.f32_opt, Some(-0.1));
1761        assert_eq!(store.f64_opt, Some(2.3));
1762    }
1763}
1764
1765#[cfg(test)]
1766mod tests_of_parse_util_sub_cmd_for {
1767    use super::*;
1768    use crate as cliargs;
1769
1770    #[derive(cliargs::OptStore, Debug)]
1771    struct MyOptions {
1772        #[opt(cfg = "foo,f")]
1773        foo: bool,
1774    }
1775
1776    #[derive(cliargs::OptStore, Debug)]
1777    struct SubOptions {
1778        #[opt(cfg = "bar,b")]
1779        bar: bool,
1780    }
1781
1782    #[test]
1783    fn get_sub_cmd() {
1784        let mut cmd = Cmd::with_strings([
1785            "app".to_string(),
1786            "--foo".to_string(),
1787            "sub".to_string(),
1788            "--bar".to_string(),
1789        ]);
1790
1791        let mut my_options = MyOptions::with_defaults();
1792        let mut sub_options = SubOptions::with_defaults();
1793
1794        match cmd.parse_until_sub_cmd_for(&mut my_options) {
1795            Ok(Some(mut sub_cmd)) => {
1796                assert_eq!(sub_cmd.name(), "sub");
1797                assert_eq!(sub_cmd.args(), &[] as &[&str]);
1798                assert_eq!(sub_cmd.has_opt("bar"), false);
1799                assert_eq!(sub_cmd.opt_arg("fbar"), None);
1800                assert_eq!(sub_cmd.opt_args("bar"), None);
1801
1802                let _ = sub_cmd.parse_for(&mut sub_options);
1803                assert_eq!(sub_cmd.name(), "sub");
1804                assert_eq!(sub_cmd.args(), &[] as &[&str]);
1805                assert_eq!(sub_cmd.has_opt("bar"), true);
1806                assert_eq!(sub_cmd.opt_arg("bar"), None);
1807                assert_eq!(sub_cmd.opt_args("bar"), Some(&[] as &[&str]));
1808
1809                assert_eq!(sub_cmd.cfgs.len(), 1);
1810                assert_eq!(sub_cmd.cfgs[0].store_key, "bar".to_string());
1811                assert_eq!(
1812                    sub_cmd.cfgs[0].names,
1813                    vec!["bar".to_string(), "b".to_string()]
1814                );
1815                assert_eq!(sub_cmd.cfgs[0].has_arg, false);
1816                assert_eq!(sub_cmd.cfgs[0].is_array, false);
1817                assert_eq!(sub_cmd.cfgs[0].defaults, None);
1818                assert_eq!(sub_cmd.cfgs[0].desc, "".to_string());
1819                assert_eq!(sub_cmd.cfgs[0].arg_in_help, "".to_string());
1820            }
1821            Ok(None) => assert!(false),
1822            Err(_) => assert!(false),
1823        }
1824
1825        assert_eq!(cmd.name(), "app");
1826        assert_eq!(cmd.args(), &[] as &[&str]);
1827        assert_eq!(cmd.has_opt("foo"), true);
1828        assert_eq!(cmd.opt_arg("foo"), None);
1829        assert_eq!(cmd.opt_args("foo"), Some(&[] as &[&str]));
1830
1831        assert_eq!(cmd.cfgs.len(), 1);
1832        assert_eq!(cmd.cfgs[0].store_key, "foo".to_string());
1833        assert_eq!(cmd.cfgs[0].names, vec!["foo".to_string(), "f".to_string()]);
1834        assert_eq!(cmd.cfgs[0].has_arg, false);
1835        assert_eq!(cmd.cfgs[0].is_array, false);
1836        assert_eq!(cmd.cfgs[0].defaults, None);
1837        assert_eq!(cmd.cfgs[0].desc, "".to_string());
1838        assert_eq!(cmd.cfgs[0].arg_in_help, "".to_string());
1839
1840        assert_eq!(my_options.foo, true);
1841        assert_eq!(sub_options.bar, true);
1842    }
1843
1844    #[test]
1845    fn no_sub_cmd() {
1846        let mut my_options = MyOptions::with_defaults();
1847
1848        let mut cmd = Cmd::with_strings(["app".to_string(), "--foo".to_string()]);
1849
1850        match cmd.parse_until_sub_cmd_for(&mut my_options) {
1851            Ok(Some(_)) => assert!(false),
1852            Ok(None) => {}
1853            Err(_) => assert!(false),
1854        }
1855
1856        assert_eq!(cmd.name(), "app");
1857        assert_eq!(cmd.args(), &[] as &[&str]);
1858        assert_eq!(cmd.has_opt("foo"), true);
1859        assert_eq!(cmd.opt_arg("foo"), None);
1860        assert_eq!(cmd.opt_args("foo"), Some(&[] as &[&str]));
1861
1862        assert_eq!(cmd.cfgs.len(), 1);
1863        assert_eq!(cmd.cfgs[0].store_key, "foo".to_string());
1864        assert_eq!(cmd.cfgs[0].names, vec!["foo".to_string(), "f".to_string()]);
1865        assert_eq!(cmd.cfgs[0].has_arg, false);
1866        assert_eq!(cmd.cfgs[0].is_array, false);
1867        assert_eq!(cmd.cfgs[0].defaults, None);
1868        assert_eq!(cmd.cfgs[0].desc, "".to_string());
1869        assert_eq!(cmd.cfgs[0].arg_in_help, "".to_string());
1870
1871        assert_eq!(my_options.foo, true);
1872    }
1873
1874    #[test]
1875    fn fail_to_parse() {
1876        let mut my_options = MyOptions::with_defaults();
1877
1878        let mut cmd = Cmd::with_strings(["path/to/app".to_string(), "--goo".to_string()]);
1879
1880        match cmd.parse_until_sub_cmd_for(&mut my_options) {
1881            Ok(_) => assert!(false),
1882            Err(InvalidOption::UnconfiguredOption { option }) => {
1883                assert_eq!(option, "goo");
1884            }
1885            Err(_) => {}
1886        }
1887
1888        assert_eq!(cmd.name(), "app");
1889        assert_eq!(cmd.has_opt("foo"), false);
1890        assert_eq!(cmd.opt_arg("foo"), None);
1891        assert_eq!(cmd.opt_args("foo"), None);
1892        assert_eq!(cmd.has_opt("f"), false);
1893        assert_eq!(cmd.opt_arg("f"), None);
1894        assert_eq!(cmd.opt_args("f"), None);
1895        assert_eq!(cmd.args(), &[] as &[&str]);
1896
1897        assert_eq!(cmd.has_opt("goo"), false);
1898        assert_eq!(cmd.opt_arg("goo"), None);
1899        assert_eq!(cmd.opt_args("goo"), None);
1900
1901        assert_eq!(cmd.cfgs.len(), 1);
1902        assert_eq!(cmd.cfgs[0].store_key, "foo".to_string());
1903        assert_eq!(cmd.cfgs[0].names, vec!["foo".to_string(), "f".to_string()]);
1904        assert_eq!(cmd.cfgs[0].has_arg, false);
1905        assert_eq!(cmd.cfgs[0].is_array, false);
1906        assert_eq!(cmd.cfgs[0].defaults, None);
1907        assert_eq!(cmd.cfgs[0].desc, "".to_string());
1908        assert_eq!(cmd.cfgs[0].arg_in_help, "".to_string());
1909
1910        assert_eq!(my_options.foo, false);
1911    }
1912
1913    #[test]
1914    fn should_parse_with_end_opt_mark() {
1915        let mut my_options = MyOptions::with_defaults();
1916        let mut sub_options = SubOptions::with_defaults();
1917
1918        let mut cmd = Cmd::with_strings([
1919            "app".to_string(),
1920            "--foo".to_string(),
1921            "sub".to_string(),
1922            "--".to_string(),
1923            "bar".to_string(),
1924            "-@".to_string(),
1925        ]);
1926
1927        match cmd.parse_until_sub_cmd_for(&mut my_options) {
1928            Ok(Some(mut sub_cmd)) => {
1929                assert_eq!(cmd.name(), "app");
1930                assert_eq!(cmd.args(), &[] as &[&str]);
1931                assert_eq!(cmd.has_opt("foo"), true);
1932                assert_eq!(cmd.opt_arg("foo"), None);
1933                assert_eq!(cmd.opt_args("foo"), Some(&[] as &[&str]));
1934                assert_eq!(cmd.has_opt("bar"), false);
1935                assert_eq!(cmd.opt_arg("bar"), None);
1936                assert_eq!(cmd.opt_args("bar"), None);
1937
1938                match sub_cmd.parse_for(&mut sub_options) {
1939                    Ok(_) => {
1940                        assert_eq!(sub_cmd.name(), "sub");
1941                        assert_eq!(sub_cmd.args(), &["bar", "-@"] as &[&str]);
1942                        assert_eq!(sub_cmd.has_opt("foo"), false);
1943                        assert_eq!(sub_cmd.opt_arg("foo"), None);
1944                        assert_eq!(sub_cmd.opt_args("foo"), None);
1945                        assert_eq!(sub_cmd.has_opt("bar"), false);
1946                        assert_eq!(sub_cmd.opt_arg("bar"), None);
1947                        assert_eq!(sub_cmd.opt_args("bar"), None);
1948                    }
1949                    Err(_) => assert!(false),
1950                }
1951            }
1952            Ok(None) => assert!(false),
1953            Err(_) => assert!(false),
1954        }
1955    }
1956
1957    #[test]
1958    fn should_parse_after_end_opt_mark() {
1959        let mut my_options = MyOptions::with_defaults();
1960        let mut sub_options = SubOptions::with_defaults();
1961
1962        let mut cmd = Cmd::with_strings([
1963            "app".to_string(),
1964            "--".to_string(),
1965            "--foo".to_string(),
1966            "sub".to_string(),
1967            "bar".to_string(),
1968            "-@".to_string(),
1969        ]);
1970
1971        match cmd.parse_until_sub_cmd_for(&mut my_options) {
1972            Ok(Some(mut sub_cmd)) => {
1973                assert_eq!(cmd.name(), "app");
1974                assert_eq!(cmd.args(), &[] as &[&str]);
1975                assert_eq!(cmd.has_opt("foo"), false);
1976                assert_eq!(cmd.opt_arg("foo"), None);
1977                assert_eq!(cmd.opt_args("foo"), None);
1978                assert_eq!(cmd.has_opt("bar"), false);
1979                assert_eq!(cmd.opt_arg("bar"), None);
1980                assert_eq!(cmd.opt_args("bar"), None);
1981
1982                match sub_cmd.parse_for(&mut sub_options) {
1983                    Ok(_) => {
1984                        assert_eq!(sub_cmd.name(), "--foo");
1985                        assert_eq!(sub_cmd.args(), &["sub", "bar", "-@"] as &[&str]);
1986                        assert_eq!(sub_cmd.has_opt("foo"), false);
1987                        assert_eq!(sub_cmd.opt_arg("foo"), None);
1988                        assert_eq!(sub_cmd.opt_args("foo"), None);
1989                        assert_eq!(sub_cmd.has_opt("bar"), false);
1990                        assert_eq!(sub_cmd.opt_arg("bar"), None);
1991                        assert_eq!(sub_cmd.opt_args("bar"), None);
1992                    }
1993                    Err(_) => assert!(false),
1994                }
1995            }
1996            Ok(None) => assert!(false),
1997            Err(_) => assert!(false),
1998        }
1999    }
2000}