1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
use TokenStream;
/// Derives the [`pareg_core::FromArg`] macro for an enum. The enum must not be
/// generic and the enum members cannot contain any fields.
///
/// The parsing is case insensitive.
///
/// The arguments for the `arg` attribute must be lowercase to match properly.
///
/// Options on enum:
/// - `exact`: Dont infer any name and dont do any case conversions.
/// Everything must match the arguments specified in `arg`. If there is
/// nothing specified for a variant, that variant cannot be created by
/// parsing.
/// - `split = <char>`: For variants with values, split the value from the
/// variant name with the given character literal.
///
/// Options on variants:
/// - `exact`: This variant will have no implicit name.
/// - `split = <char>`: For variants with values, split the value from the
/// variant name with the given character literal.
/// - `default`, `default = <expr>`: Specify the default value for variant with
/// value.
/// - `parser = <expr>`: Callable that parses the value.
///
/// # Examples
/// ```
/// use pareg_core::{self as pareg, FromArg};
/// use pareg_proc::FromArg;
///
/// #[derive(FromArg, PartialEq, Debug)]
/// enum ColorMode {
/// Auto,
/// #[arg("yes", "ok")]
/// Always,
/// #[arg("no")]
/// Never,
/// }
///
/// assert_eq!(ColorMode::Auto, ColorMode::from_arg("auto").unwrap());
/// assert_eq!(ColorMode::Always, ColorMode::from_arg("Always").unwrap());
/// assert_eq!(ColorMode::Never, ColorMode::from_arg("NEVER").unwrap());
/// assert_eq!(ColorMode::Always, ColorMode::from_arg("yes").unwrap());
/// assert_eq!(ColorMode::Always, ColorMode::from_arg("oK").unwrap());
/// assert_eq!(ColorMode::Never, ColorMode::from_arg("NO").unwrap());
/// assert_eq!(ColorMode::Auto, ColorMode::from_arg("AuTo").unwrap());
/// ```
/// Derives the [`pareg_core::FromArgs`] trait.
///
/// ## `#[from_args]` on field
/// - `<string literal>`: variant for the given field.
/// - `default`: The field is not required. Use the [`Default`] implementation
/// for default value. When used with `collect` and `option`, the type inside
/// the [`Option`] must implement [`Default`]. Otherwise ignored when used
/// with `option`.
/// - `default = <expr>`: same as `default` but uses the given expression for
/// default value instead of the [`Default`] implementation. When used with
/// `collect` and `option`, the expression has to produce the type inside the
/// [`Option`] and not the option itself. Otherwise ignored when used with
/// `option`.
/// - `flag`: The field is type that implements `From<bool>` which will be set
/// to `true.into()` if the flag is present. When used with `collect`, the
/// type is expected to be collection of that type. When used with `option`
/// the field has to be option of that type.
/// - `positional`: Specifies that this argument may be set by any unknown
/// argument. Positional arguments are filled in the order that they are
/// present in the source code. Positional arguments can also have names
/// specified to signify option to specify them explicitly. In addition,
/// multiple positional arguments may have the same name. In that case that
/// name will fill the first empty positional argument with that name.
/// - `collect`: Specifies that this argument is expected to be present
/// multiple times and all occurences will be collected into a collection.
/// The type has to have method `extend` available with the same sematics as
/// that of the trait [`Extend`]. The type must implement [`Default`] or the
/// default value must be specified with `default = <expr>`. This default is
/// representing empty collection. If `collect` is combined with
/// `positional`, and there are positional fields after collect, the
/// positional fields after this one will never be filled as positional as
/// the collection will consume all positional fields and never move to the
/// next field. When used with `opition`, the type inside the option is the
/// collection and it is required to implement method `.is_empty()` which
/// checks whether the collection is empty or not by returning [`bool`]. This
/// method will decide if the result is the collection or [`None`].
/// - `collect = <range>`: Same as collect. This will also enable verification
/// that the number of items is within the given range. `<range>` may be any
/// expression for which `(<range>).contains(&field.len())` is valid and
/// returns [`bool`] where <field> is variable of the type of this field.
/// This is valid for example for standard ranges (e.g. `2..`) or arrays
/// (e.g. `[2]`), if the collection has method `len` which returns the number
/// of elements as [`usize`]. This range limit doesn't affect the behaviour
/// of combination of `positional` and `collect` (collect will consume all
/// remaining positional fields no matter the limitation in `<range>`).
/// - `no_rewrite`: Decides how repeating arguments are handled. If set, this
/// field will throw error when it would be set more than once. By default
/// the action is decided by attribute on the `FromArgs` type of which this
/// field is part, which is by default set to overwrite the old value. This
/// is ignored by fields with `collect`. This doesn't affect positional
/// arguments.
/// - `rewrite`: The reverse of `no_rewrite`. This us useful to allow
/// owerwriting the default set by the `FromArgs` type of which is this
/// field.
/// - `option`: The field type is option. The option will be set to a value if
/// the argument is present and otherwise it will be [`None`].
/// - `check = <expr>`: If the field is set, the condition in `<expr>` is
/// checked. If the condition is `false` an error is emited. This field is
/// available as not option reference for this condition and other fields are
/// available either as options or as the fields themself depending on the
/// field configuration. The condition is evaluated only after all arguments
/// have been successfully parsed.
/// - `otherwise = <cond>`: If the field is not set, the given condition must
/// be true. If it is not true, the parsing will result in error.
/// - `conflict = [<fields>]`: specifies that the fields are in conflict with
/// this field. If this field is set and at least one of the given fields is
/// also set, it will produce error.
/// - `require = [<fields>]`: specifies that if this field is set, all of the
/// given fields have to be also set. If at least one of them is not set,
/// parsing will result in error.
///
/// ## `#[from_args]` on the type
/// - `match start { <arms> }`: custom match arms that will be before the arms
/// for the fields. All fields are accesible with their name, but they may be
/// option of that type instead of that type itself depending on the
/// configuration of the field.
/// - `match end { <arms> }`: same as `match start` but places the arms after
/// the arms for fields.
/// - `positional_guard`: if present, enables guarding of positional arguments.
/// This means that positional arguments starting with `-` are rejected as
/// unknown argument.
/// - `no_rewrite`: Decides how repeating arguments are handled. If set, fields
/// will throw error when they would be set more than once. By default,
/// rewrites are allowed and the latest value is used. This is ignored by
/// fields with `collect`. This doesn't affect positional arguments.
/// - `check = <expr>`: Checks the given condition after all arguments have
/// been parsed and their conditions succeeded. If the condition is `false`,
/// an error is emited.
/// - `conflict = [<fields>]`: Specify that the given fields are mutually in
/// conflict. This means that only one of them may be set. If more of them
/// are set, it will result in error.
/// - `require = [<fields>]`: Specifies that the given fields have to be set
/// together. If some of them is set but not all, parsing will result in
/// error.
///
/// # Example
/// ```
/// use std::path::PathBuf;
/// use pareg_core::{self as pareg, Pareg};
/// use pareg_proc::FromArgs;
///
/// #[derive(FromArgs)]
/// #[from_args(match start { "-h" | "-?" | "--help" => println!("help") })]
/// struct Args {
/// #[from_args("-o", "--output", default = "output.png".into())]
/// output: PathBuf,
/// #[from_args("-v", "--verbose", flag, default)]
/// verbose: bool,
/// }
///
/// let mut args = Pareg::new(vec!["-o", "test.png"]);
/// let parsed: Args = args.next_sub().unwrap();
///
/// assert_eq!(parsed.output, PathBuf::from("test.png"));
/// assert_eq!(parsed.verbose, false);
///
/// let mut args = Pareg::new(vec!["-v"]);
/// let parsed: Args = args.next_sub().unwrap();
///
/// assert_eq!(parsed.output, PathBuf::from("output.png"));
/// assert_eq!(parsed.verbose, true);
///
/// let mut args = Pareg::new(vec!["--lol"]);
///
/// assert!(args.next_sub::<Args>().is_err());
/// ```
/// This macro can be tought of as opposite of [`write!`] or as something like
/// `fscanf` in C.
///
/// As arguments, takes reader to parse, format string and than arguments to
/// which result will be written.
///
/// The format string can contain format strings for the specific arguments
/// after `:`. The format is `CTS..ER` where:
/// - `CT` is optional trim mode.
/// - `C` is optional character to trim. If not present, trim whitespace.
/// - `T` is the side from which to trim. It is the opposite of alignment
/// in format functions:
/// - `<` trim from right.
/// - `>` trim from left.
/// - `^` trim from both sides.
/// - `S..E` is optional length range. The parsing function should use at least
/// `S` and at most `E` characters.
/// - `S`, `E` or both may be omited. In that case `S` will be same as `0`
/// and `E` will be same as max length.
/// - If only `S` is present (without `..E`), it is same as `S..S`.
/// - `R` is optional radix for conversion. It may be:
/// - `D` as decimal.
/// - `X` as hexadecimal.
/// - `O` as octal.
///
/// Anything else after the format is custom format string for the given type.
/// Nothing forces the parsing function to follow the standart formatting and
/// no format is invalid.
///
/// # Returns
/// [`pareg_core::Result<()>`] that indicates success or failure.
///
/// # Example
///
/// ```rust
/// use std::str::FromStr;
/// use pareg_core::{self as pareg, ArgError, check};
/// use pareg_proc::parsef;
///
/// #[derive(Debug, Default, PartialEq)]
/// struct Address {
/// adr: (u8, u8, u8, u8),
/// mask: u8,
/// }
///
/// impl FromStr for Address {
/// type Err = ArgError;
///
/// fn from_str(s: &str) -> Result<Self, Self::Err> {
/// let mut res = Self::default();
/// parsef!(
/// &mut s.into(),
/// "{}.{}.{}.{}/{}",
/// &mut res.adr.0,
/// &mut res.adr.1,
/// &mut res.adr.2,
/// &mut res.adr.3,
/// &mut check::InRange(&mut res.mask, 0..33),
/// )?;
///
/// Ok(res)
/// }
/// }
///
/// assert_eq!(
/// Address::from_str("127.5.20.1/24").unwrap(),
/// Address {
/// adr: (127, 5, 20, 1),
/// mask: 24
/// }
/// );
/// ```
/// Simmilar to [`parsef!`], but doesn't expect to parse the whole string, but
/// only start of the string. It macro can be tought of as opposite of
/// [`write!`] or as something like `fscanf` in C.
///
/// As arguments, takes reader to parse, format string and than arguments to
/// which result will be written.
///
/// The format string can contain format strings for the specific arguments
/// after `:`. The format is `CTS..ER` where:
/// - `CT` is optional trim mode.
/// - `C` is optional character to trim. If not present, trim whitespace.
/// - `T` is the side from which to trim. It is the opposite of alignment
/// in format functions:
/// - `<` trim from right.
/// - `>` trim from left.
/// - `^` trim from both sides.
/// - `S..E` is optional length range. The parsing function should use at least
/// `S` and at most `E` characters.
/// - `S`, `E` or both may be omited. In that case `S` will be same as `0`
/// and `E` will be same as max length.
/// - If only `S` is present (without `..E`), it is same as `S..S`.
/// - `R` is optional radix for conversion. It may be:
/// - `D` as decimal.
/// - `X` as hexadecimal.
/// - `O` as octal.
///
/// # Returns
/// `pareg_core::Result<Option<pareg_core::ArgError>>` that indicates success
/// or failure. On success, if the string was not fully parsed also returns
/// error that should be raised if it was expected to parse more of the string.
///
/// # Example
/// ```rust
/// use pareg_core::{self as pareg, ArgError, check};
/// use pareg_proc::parsef_part;
///
/// #[derive(Debug, Default, PartialEq)]
/// struct Address {
/// adr: (u8, u8, u8, u8),
/// mask: u8,
/// }
///
/// let mut adr = Address::default();
/// let res = parsef_part!(
/// &mut "127.5.20.1/24some other stuff".into(),
/// "{}.{}.{}.{}/{}",
/// &mut adr.adr.0,
/// &mut adr.adr.1,
/// &mut adr.adr.2,
/// &mut adr.adr.3,
/// &mut check::InRange(&mut adr.mask, 0..33),
/// );
/// assert!(res.is_ok());
///
/// assert_eq!(
/// adr,
/// Address {
/// adr: (127, 5, 20, 1),
/// mask: 24
/// }
/// );
/// ```