clap_config_fallback/
arg.rs1use std::ffi::OsString;
2
3use clap::ArgMatches;
4
5use crate::format::{CustomFormat, DefaultFormat, FormatArg};
6
7pub trait IntoArgs: Sized {
11 fn into_args(self) -> impl Iterator<Item = OsString> {
12 let mut args = Vec::new();
13
14 self.extend_args(&mut args);
15
16 args.into_iter()
17 }
18
19 fn extend_args(self, args: &mut Vec<OsString>);
20}
21
22pub trait FromArgs: Sized {
26 fn from_args(args: &ArgMatches) -> Option<Self>;
27}
28
29pub enum ArgValue<T> {
30 Scalar(T),
31 Repeated(Vec<T>),
32 Flag(bool),
33}
34
35pub struct Arg<T, F = DefaultFormat> {
36 value: ArgValue<T>,
37 name: Option<OsString>,
38 formatter: F,
39}
40
41impl<T> Arg<T> {
42 pub fn scalar(value: T) -> Self {
43 Self {
44 value: ArgValue::Scalar(value),
45 name: None,
46 formatter: DefaultFormat,
47 }
48 }
49
50 pub fn repeated(value: Vec<T>) -> Self {
51 Self {
52 value: ArgValue::Repeated(value),
53 name: None,
54 formatter: DefaultFormat,
55 }
56 }
57}
58
59impl Arg<bool, DefaultFormat> {
60 pub fn flag(value: bool) -> Self {
61 Self {
62 value: ArgValue::Flag(value),
63 name: None,
64 formatter: DefaultFormat,
65 }
66 }
67}
68
69impl<T, F> Arg<T, F> {
70 pub fn name(mut self, name: impl Into<OsString>) -> Self {
71 self.name = Some(name.into());
72
73 self
74 }
75
76 pub fn value_format<U>(self, formatter: U) -> Arg<T, CustomFormat<U>> {
77 Arg {
78 value: self.value,
79 name: self.name,
80 formatter: CustomFormat(formatter),
81 }
82 }
83}
84
85impl<T, F> IntoArgs for Arg<T, F>
86where
87 F: FormatArg<T>,
88{
89 fn extend_args(self, args: &mut Vec<OsString>) {
90 match self.value {
91 ArgValue::Scalar(value) => {
92 if let Some(name) = self.name {
93 args.push(name);
94 }
95
96 args.push(self.formatter.format(value));
97 }
98 ArgValue::Repeated(values) => {
99 for value in values {
100 if let Some(name) = &self.name {
101 args.push(name.clone());
102 }
103
104 args.push(self.formatter.format(value));
105 }
106 }
107 ArgValue::Flag(value) => {
108 if value && let Some(name) = self.name {
109 args.push(name);
110 }
111 }
112 }
113 }
114}
115
116impl<T> IntoArgs for Option<T>
117where
118 T: IntoArgs,
119{
120 fn extend_args(self, args: &mut Vec<OsString>) {
121 if let Some(value) = self {
122 value.extend_args(args);
123 }
124 }
125}