1#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct ParsedCli {
15 pub(crate) command_path: Vec<String>,
16 pub(crate) options: Vec<ParsedOption>,
17 pub(crate) positionals: Vec<String>,
18 pub(crate) passthrough: Vec<String>,
19}
20
21#[derive(Clone, PartialEq, Eq)]
22pub struct ParsedOption {
23 pub(crate) name: String,
24 pub(crate) value: Option<String>,
25}
26
27impl ParsedCli {
28 pub fn command_path(&self) -> &[String] {
29 &self.command_path
30 }
31 pub fn options(&self) -> &[ParsedOption] {
32 &self.options
33 }
34 pub fn positionals(&self) -> &[String] {
35 &self.positionals
36 }
37 pub fn passthrough(&self) -> &[String] {
38 &self.passthrough
39 }
40 pub fn has_flag(&self, name: &str) -> bool {
41 self.options.iter().any(|option| option.name == name)
42 }
43 pub fn option_value(&self, name: &str) -> Option<&str> {
44 self.options
45 .iter()
46 .rev()
47 .find(|option| option.name == name)
48 .and_then(ParsedOption::value)
49 }
50 pub fn option_values<'b>(&'b self, name: &'b str) -> impl Iterator<Item = &'b str> + 'b {
51 self.options
52 .iter()
53 .filter(move |option| option.name == name)
54 .filter_map(ParsedOption::value)
55 }
56 pub fn option_path(&self, name: &str) -> Option<std::path::PathBuf> {
58 self.option_value(name).map(std::path::PathBuf::from)
59 }
60 pub fn option_socket_addr(
62 &self,
63 name: &str,
64 ) -> Result<Option<std::net::SocketAddr>, crate::CliError> {
65 self.option_value(name)
66 .map(|v| {
67 v.parse().map_err(|_| {
68 crate::CliError::new(
69 crate::CliErrorKind::InvalidValue,
70 format!("invalid socket address for --{name}"),
71 )
72 })
73 })
74 .transpose()
75 }
76 pub fn option_occurrences(&self, name: &str) -> usize {
77 self.options
78 .iter()
79 .filter(|option| option.name == name)
80 .count()
81 }
82}
83
84impl ParsedOption {
85 pub fn name(&self) -> &str {
86 &self.name
87 }
88 pub fn value(&self) -> Option<&str> {
89 self.value.as_deref()
90 }
91}
92
93impl std::fmt::Debug for ParsedOption {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 f.debug_struct("ParsedOption")
96 .field("name", &self.name)
97 .field("value", &"[REDACTED]")
98 .finish()
99 }
100}