Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.5.31/src/derive.rs
Line
Count
Source
1
//! This module contains traits that are usable with the `#[derive(...)]`
2
//! macros in `clap_derive`.
3
4
use crate::builder::PossibleValue;
5
use crate::{ArgMatches, Command, Error};
6
7
use std::ffi::OsString;
8
9
/// Parse command-line arguments into `Self`.
10
///
11
/// The primary one-stop-shop trait used to create an instance of a `clap`
12
/// [`Command`], conduct the parsing, and turn the resulting [`ArgMatches`] back
13
/// into concrete instance of the user struct.
14
///
15
/// This trait is primarily a convenience on top of [`FromArgMatches`] +
16
/// [`CommandFactory`] which uses those two underlying traits to build the two
17
/// fundamental functions `parse` which uses the `std::env::args_os` iterator,
18
/// and `parse_from` which allows the consumer to supply the iterator (along
19
/// with fallible options for each).
20
///
21
/// See also [`Subcommand`] and [`Args`].
22
///
23
/// <div class="warning">
24
///
25
/// **NOTE:** Deriving requires the `derive` feature flag
26
///
27
/// </div>
28
pub trait Parser: FromArgMatches + CommandFactory + Sized {
29
    /// Parse from `std::env::args_os()`, [exit][Error::exit] on error.
30
0
    fn parse() -> Self {
31
0
        let mut matches = <Self as CommandFactory>::command().get_matches();
32
0
        let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches)
33
0
            .map_err(format_error::<Self>);
34
0
        match res {
35
0
            Ok(s) => s,
36
0
            Err(e) => {
37
                // Since this is more of a development-time error, we aren't doing as fancy of a quit
38
                // as `get_matches`
39
0
                e.exit()
40
            }
41
        }
42
0
    }
43
44
    /// Parse from `std::env::args_os()`, return Err on error.
45
0
    fn try_parse() -> Result<Self, Error> {
46
0
        let mut matches = ok!(<Self as CommandFactory>::command().try_get_matches());
47
0
        <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>)
48
0
    }
49
50
    /// Parse from iterator, [exit][Error::exit] on error.
51
0
    fn parse_from<I, T>(itr: I) -> Self
52
0
    where
53
0
        I: IntoIterator<Item = T>,
54
0
        T: Into<OsString> + Clone,
55
    {
56
0
        let mut matches = <Self as CommandFactory>::command().get_matches_from(itr);
57
0
        let res = <Self as FromArgMatches>::from_arg_matches_mut(&mut matches)
58
0
            .map_err(format_error::<Self>);
59
0
        match res {
60
0
            Ok(s) => s,
61
0
            Err(e) => {
62
                // Since this is more of a development-time error, we aren't doing as fancy of a quit
63
                // as `get_matches_from`
64
0
                e.exit()
65
            }
66
        }
67
0
    }
68
69
    /// Parse from iterator, return Err on error.
70
0
    fn try_parse_from<I, T>(itr: I) -> Result<Self, Error>
71
0
    where
72
0
        I: IntoIterator<Item = T>,
73
0
        T: Into<OsString> + Clone,
74
    {
75
0
        let mut matches = ok!(<Self as CommandFactory>::command().try_get_matches_from(itr));
76
0
        <Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>)
77
0
    }
78
79
    /// Update from iterator, [exit][Error::exit] on error.
80
    ///
81
    /// Unlike [`Parser::parse`], this works with an existing instance of `self`.
82
    /// The assumption is that all required fields are already provided and any [`Args`] or
83
    /// [`Subcommand`]s provided by the user will modify only what is specified.
84
0
    fn update_from<I, T>(&mut self, itr: I)
85
0
    where
86
0
        I: IntoIterator<Item = T>,
87
0
        T: Into<OsString> + Clone,
88
    {
89
0
        let mut matches = <Self as CommandFactory>::command_for_update().get_matches_from(itr);
90
0
        let res = <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
91
0
            .map_err(format_error::<Self>);
92
0
        if let Err(e) = res {
93
            // Since this is more of a development-time error, we aren't doing as fancy of a quit
94
            // as `get_matches_from`
95
0
            e.exit()
96
0
        }
97
0
    }
98
99
    /// Update from iterator, return Err on error.
100
0
    fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error>
101
0
    where
102
0
        I: IntoIterator<Item = T>,
103
0
        T: Into<OsString> + Clone,
104
    {
105
0
        let mut matches =
106
0
            ok!(<Self as CommandFactory>::command_for_update().try_get_matches_from(itr));
107
0
        <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
108
0
            .map_err(format_error::<Self>)
109
0
    }
110
}
111
112
/// Create a [`Command`] relevant for a user-defined container.
113
///
114
/// Derived as part of [`Parser`].
115
pub trait CommandFactory: Sized {
116
    /// Build a [`Command`] that can instantiate `Self`.
117
    ///
118
    /// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
119
    fn command() -> Command;
120
    /// Build a [`Command`] that can update `self`.
121
    ///
122
    /// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
123
    fn command_for_update() -> Command;
124
}
125
126
/// Converts an instance of [`ArgMatches`] to a user-defined container.
127
///
128
/// Derived as part of [`Parser`], [`Args`], and [`Subcommand`].
129
pub trait FromArgMatches: Sized {
130
    /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
131
    ///
132
    /// Motivation: If our application had two CLI options, `--name
133
    /// <STRING>` and the flag `--debug`, we may create a struct as follows:
134
    ///
135
    /// ```rust
136
    /// # #[cfg(feature = "derive")] {
137
    /// struct Context {
138
    ///     name: String,
139
    ///     debug: bool
140
    /// }
141
    /// # }
142
    /// ```
143
    ///
144
    /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
145
    /// `from_arg_matches` serves as the equivalent of:
146
    ///
147
    /// ```rust
148
    /// # #[cfg(feature = "derive")] {
149
    /// # use clap::ArgMatches;
150
    /// # struct Context {
151
    /// #   name: String,
152
    /// #   debug: bool
153
    /// # }
154
    /// impl From<ArgMatches> for Context {
155
    ///    fn from(m: ArgMatches) -> Self {
156
    ///        Context {
157
    ///            name: m.get_one::<String>("name").unwrap().clone(),
158
    ///            debug: m.get_flag("debug"),
159
    ///        }
160
    ///    }
161
    /// }
162
    /// # }
163
    /// ```
164
    fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error>;
165
166
    /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
167
    ///
168
    /// Motivation: If our application had two CLI options, `--name
169
    /// <STRING>` and the flag `--debug`, we may create a struct as follows:
170
    ///
171
    /// ```rust
172
    /// # #[cfg(feature = "derive")] {
173
    /// struct Context {
174
    ///     name: String,
175
    ///     debug: bool
176
    /// }
177
    /// # }
178
    /// ```
179
    ///
180
    /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
181
    /// `from_arg_matches_mut` serves as the equivalent of:
182
    ///
183
    /// ```rust
184
    /// # #[cfg(feature = "derive")] {
185
    /// # use clap::ArgMatches;
186
    /// # struct Context {
187
    /// #   name: String,
188
    /// #   debug: bool
189
    /// # }
190
    /// impl From<ArgMatches> for Context {
191
    ///    fn from(m: ArgMatches) -> Self {
192
    ///        Context {
193
    ///            name: m.get_one::<String>("name").unwrap().to_string(),
194
    ///            debug: m.get_flag("debug"),
195
    ///        }
196
    ///    }
197
    /// }
198
    /// # }
199
    /// ```
200
0
    fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
201
0
        Self::from_arg_matches(matches)
202
0
    }
203
204
    /// Assign values from `ArgMatches` to `self`.
205
    fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>;
206
207
    /// Assign values from `ArgMatches` to `self`.
208
0
    fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
209
0
        self.update_from_arg_matches(matches)
210
0
    }
211
}
212
213
/// Parse a set of arguments into a user-defined container.
214
///
215
/// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`.
216
/// with:
217
/// - `#[command(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl
218
///   `Args`.
219
/// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`.
220
///
221
/// <div class="warning">
222
///
223
/// **NOTE:** Deriving requires the `derive` feature flag
224
///
225
/// </div>
226
pub trait Args: FromArgMatches + Sized {
227
    /// Report the [`ArgGroup::id`][crate::ArgGroup::id] for this set of arguments
228
0
    fn group_id() -> Option<crate::Id> {
229
0
        None
230
0
    }
231
    /// Append to [`Command`] so it can instantiate `Self` via
232
    /// [`FromArgMatches::from_arg_matches_mut`]
233
    ///
234
    /// This is used to implement `#[command(flatten)]`
235
    ///
236
    /// See also [`CommandFactory::command`].
237
    fn augment_args(cmd: Command) -> Command;
238
    /// Append to [`Command`] so it can instantiate `self` via
239
    /// [`FromArgMatches::update_from_arg_matches_mut`]
240
    ///
241
    /// This is used to implement `#[command(flatten)]`
242
    ///
243
    /// See also [`CommandFactory::command_for_update`].
244
    fn augment_args_for_update(cmd: Command) -> Command;
245
}
246
247
/// Parse a sub-command into a user-defined enum.
248
///
249
/// Implementing this trait lets a parent container delegate subcommand behavior to `Self`.
250
/// with:
251
/// - `#[command(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum
252
///   variants that impl `Subcommand`.
253
/// - `#[command(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl
254
///   `Subcommand`.
255
///
256
/// <div class="warning">
257
///
258
/// **NOTE:** Deriving requires the `derive` feature flag
259
///
260
/// </div>
261
pub trait Subcommand: FromArgMatches + Sized {
262
    /// Append to [`Command`] so it can instantiate `Self` via
263
    /// [`FromArgMatches::from_arg_matches_mut`]
264
    ///
265
    /// This is used to implement `#[command(flatten)]`
266
    ///
267
    /// See also [`CommandFactory::command`].
268
    fn augment_subcommands(cmd: Command) -> Command;
269
    /// Append to [`Command`] so it can instantiate `self` via
270
    /// [`FromArgMatches::update_from_arg_matches_mut`]
271
    ///
272
    /// This is used to implement `#[command(flatten)]`
273
    ///
274
    /// See also [`CommandFactory::command_for_update`].
275
    fn augment_subcommands_for_update(cmd: Command) -> Command;
276
    /// Test whether `Self` can parse a specific subcommand
277
    fn has_subcommand(name: &str) -> bool;
278
}
279
280
/// Parse arguments into enums.
281
///
282
/// When deriving [`Parser`], a field whose type implements `ValueEnum` can have the attribute
283
/// `#[arg(value_enum)]` which will
284
/// - Call [`EnumValueParser`][crate::builder::EnumValueParser]
285
/// - Allowing using the `#[arg(default_value_t)]` attribute without implementing `Display`.
286
///
287
/// <div class="warning">
288
///
289
/// **NOTE:** Deriving requires the `derive` feature flag
290
///
291
/// </div>
292
pub trait ValueEnum: Sized + Clone {
293
    /// All possible argument values, in display order.
294
    fn value_variants<'a>() -> &'a [Self];
295
296
    /// Parse an argument into `Self`.
297
0
    fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
298
0
        Self::value_variants()
299
0
            .iter()
300
0
            .find(|v| {
301
0
                v.to_possible_value()
302
0
                    .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value")
303
0
                    .matches(input, ignore_case)
304
0
            })
305
0
            .cloned()
306
0
            .ok_or_else(|| format!("invalid variant: {input}"))
307
0
    }
308
309
    /// The canonical argument value.
310
    ///
311
    /// The value is `None` for skipped variants.
312
    fn to_possible_value(&self) -> Option<PossibleValue>;
313
}
314
315
impl<T: Parser> Parser for Box<T> {
316
0
    fn parse() -> Self {
317
0
        Box::new(<T as Parser>::parse())
318
0
    }
319
320
0
    fn try_parse() -> Result<Self, Error> {
321
0
        <T as Parser>::try_parse().map(Box::new)
322
0
    }
323
324
0
    fn parse_from<I, It>(itr: I) -> Self
325
0
    where
326
0
        I: IntoIterator<Item = It>,
327
0
        It: Into<OsString> + Clone,
328
    {
329
0
        Box::new(<T as Parser>::parse_from(itr))
330
0
    }
331
332
0
    fn try_parse_from<I, It>(itr: I) -> Result<Self, Error>
333
0
    where
334
0
        I: IntoIterator<Item = It>,
335
0
        It: Into<OsString> + Clone,
336
    {
337
0
        <T as Parser>::try_parse_from(itr).map(Box::new)
338
0
    }
339
}
340
341
impl<T: CommandFactory> CommandFactory for Box<T> {
342
0
    fn command() -> Command {
343
0
        <T as CommandFactory>::command()
344
0
    }
345
0
    fn command_for_update() -> Command {
346
0
        <T as CommandFactory>::command_for_update()
347
0
    }
348
}
349
350
impl<T: FromArgMatches> FromArgMatches for Box<T> {
351
0
    fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
352
0
        <T as FromArgMatches>::from_arg_matches(matches).map(Box::new)
353
0
    }
354
0
    fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
355
0
        <T as FromArgMatches>::from_arg_matches_mut(matches).map(Box::new)
356
0
    }
357
0
    fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
358
0
        <T as FromArgMatches>::update_from_arg_matches(self, matches)
359
0
    }
360
0
    fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
361
0
        <T as FromArgMatches>::update_from_arg_matches_mut(self, matches)
362
0
    }
363
}
364
365
impl<T: Args> Args for Box<T> {
366
0
    fn augment_args(cmd: Command) -> Command {
367
0
        <T as Args>::augment_args(cmd)
368
0
    }
369
0
    fn augment_args_for_update(cmd: Command) -> Command {
370
0
        <T as Args>::augment_args_for_update(cmd)
371
0
    }
372
}
373
374
impl<T: Subcommand> Subcommand for Box<T> {
375
0
    fn augment_subcommands(cmd: Command) -> Command {
376
0
        <T as Subcommand>::augment_subcommands(cmd)
377
0
    }
378
0
    fn augment_subcommands_for_update(cmd: Command) -> Command {
379
0
        <T as Subcommand>::augment_subcommands_for_update(cmd)
380
0
    }
381
0
    fn has_subcommand(name: &str) -> bool {
382
0
        <T as Subcommand>::has_subcommand(name)
383
0
    }
384
}
385
386
0
fn format_error<I: CommandFactory>(err: Error) -> Error {
387
0
    let mut cmd = I::command();
388
0
    err.format(&mut cmd)
389
0
}