1 // Unlike `impl Into<Option<T>>` or `Option<impl Into<T>>`, this isn't ambiguous for the `None`
2 // case.
3 
4 use crate::builder::ArgAction;
5 use crate::builder::OsStr;
6 use crate::builder::Str;
7 use crate::builder::StyledStr;
8 use crate::builder::ValueHint;
9 use crate::builder::ValueParser;
10 use crate::builder::ValueRange;
11 
12 /// Clearable builder value
13 ///
14 /// This allows a builder function to both accept any value that can [`Into::into`] `T` (like
15 /// `&str` into `OsStr`) as well as `None` to reset it to the default.  This is needed to
16 /// workaround a limitation where you can't have a function argument that is `impl Into<Option<T>>`
17 /// where `T` is `impl Into<S>` accept `None` as its type is ambiguous.
18 ///
19 /// # Example
20 ///
21 /// ```rust
22 /// # use clap_builder as clap;
23 /// # use clap::Command;
24 /// # use clap::Arg;
25 /// fn common() -> Command {
26 ///     Command::new("cli")
27 ///         .arg(Arg::new("input").short('i').long("input"))
28 /// }
29 /// let mut command = common();
30 /// command.mut_arg("input", |arg| arg.short(None));
31 /// ```
32 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
33 pub enum Resettable<T> {
34     /// Overwrite builder value
35     Value(T),
36     /// Reset builder value
37     Reset,
38 }
39 
40 impl<T> Resettable<T> {
into_option(self) -> Option<T>41     pub(crate) fn into_option(self) -> Option<T> {
42         match self {
43             Self::Value(t) => Some(t),
44             Self::Reset => None,
45         }
46     }
47 }
48 
49 impl<T> From<T> for Resettable<T> {
from(other: T) -> Self50     fn from(other: T) -> Self {
51         Self::Value(other)
52     }
53 }
54 
55 impl<T> From<Option<T>> for Resettable<T> {
from(other: Option<T>) -> Self56     fn from(other: Option<T>) -> Self {
57         match other {
58             Some(inner) => Self::Value(inner),
59             None => Self::Reset,
60         }
61     }
62 }
63 
64 /// Convert to the intended resettable type
65 pub trait IntoResettable<T> {
66     /// Convert to the intended resettable type
into_resettable(self) -> Resettable<T>67     fn into_resettable(self) -> Resettable<T>;
68 }
69 
70 impl IntoResettable<char> for Option<char> {
into_resettable(self) -> Resettable<char>71     fn into_resettable(self) -> Resettable<char> {
72         match self {
73             Some(s) => Resettable::Value(s),
74             None => Resettable::Reset,
75         }
76     }
77 }
78 
79 impl IntoResettable<usize> for Option<usize> {
into_resettable(self) -> Resettable<usize>80     fn into_resettable(self) -> Resettable<usize> {
81         match self {
82             Some(s) => Resettable::Value(s),
83             None => Resettable::Reset,
84         }
85     }
86 }
87 
88 impl IntoResettable<ArgAction> for Option<ArgAction> {
into_resettable(self) -> Resettable<ArgAction>89     fn into_resettable(self) -> Resettable<ArgAction> {
90         match self {
91             Some(s) => Resettable::Value(s),
92             None => Resettable::Reset,
93         }
94     }
95 }
96 
97 impl IntoResettable<ValueHint> for Option<ValueHint> {
into_resettable(self) -> Resettable<ValueHint>98     fn into_resettable(self) -> Resettable<ValueHint> {
99         match self {
100             Some(s) => Resettable::Value(s),
101             None => Resettable::Reset,
102         }
103     }
104 }
105 
106 impl IntoResettable<ValueParser> for Option<ValueParser> {
into_resettable(self) -> Resettable<ValueParser>107     fn into_resettable(self) -> Resettable<ValueParser> {
108         match self {
109             Some(s) => Resettable::Value(s),
110             None => Resettable::Reset,
111         }
112     }
113 }
114 
115 impl IntoResettable<StyledStr> for Option<&'static str> {
into_resettable(self) -> Resettable<StyledStr>116     fn into_resettable(self) -> Resettable<StyledStr> {
117         match self {
118             Some(s) => Resettable::Value(s.into()),
119             None => Resettable::Reset,
120         }
121     }
122 }
123 
124 impl IntoResettable<OsStr> for Option<&'static str> {
into_resettable(self) -> Resettable<OsStr>125     fn into_resettable(self) -> Resettable<OsStr> {
126         match self {
127             Some(s) => Resettable::Value(s.into()),
128             None => Resettable::Reset,
129         }
130     }
131 }
132 
133 impl IntoResettable<Str> for Option<&'static str> {
into_resettable(self) -> Resettable<Str>134     fn into_resettable(self) -> Resettable<Str> {
135         match self {
136             Some(s) => Resettable::Value(s.into()),
137             None => Resettable::Reset,
138         }
139     }
140 }
141 
142 impl<T> IntoResettable<T> for Resettable<T> {
into_resettable(self) -> Resettable<T>143     fn into_resettable(self) -> Resettable<T> {
144         self
145     }
146 }
147 
148 impl IntoResettable<char> for char {
into_resettable(self) -> Resettable<char>149     fn into_resettable(self) -> Resettable<char> {
150         Resettable::Value(self)
151     }
152 }
153 
154 impl IntoResettable<usize> for usize {
into_resettable(self) -> Resettable<usize>155     fn into_resettable(self) -> Resettable<usize> {
156         Resettable::Value(self)
157     }
158 }
159 
160 impl IntoResettable<ArgAction> for ArgAction {
into_resettable(self) -> Resettable<ArgAction>161     fn into_resettable(self) -> Resettable<ArgAction> {
162         Resettable::Value(self)
163     }
164 }
165 
166 impl IntoResettable<ValueHint> for ValueHint {
into_resettable(self) -> Resettable<ValueHint>167     fn into_resettable(self) -> Resettable<ValueHint> {
168         Resettable::Value(self)
169     }
170 }
171 
172 impl<I: Into<ValueRange>> IntoResettable<ValueRange> for I {
into_resettable(self) -> Resettable<ValueRange>173     fn into_resettable(self) -> Resettable<ValueRange> {
174         Resettable::Value(self.into())
175     }
176 }
177 
178 impl<I: Into<ValueParser>> IntoResettable<ValueParser> for I {
into_resettable(self) -> Resettable<ValueParser>179     fn into_resettable(self) -> Resettable<ValueParser> {
180         Resettable::Value(self.into())
181     }
182 }
183 
184 impl<I: Into<String>> IntoResettable<String> for I {
into_resettable(self) -> Resettable<String>185     fn into_resettable(self) -> Resettable<String> {
186         Resettable::Value(self.into())
187     }
188 }
189 
190 impl<I: Into<StyledStr>> IntoResettable<StyledStr> for I {
into_resettable(self) -> Resettable<StyledStr>191     fn into_resettable(self) -> Resettable<StyledStr> {
192         Resettable::Value(self.into())
193     }
194 }
195 
196 impl<I: Into<OsStr>> IntoResettable<OsStr> for I {
into_resettable(self) -> Resettable<OsStr>197     fn into_resettable(self) -> Resettable<OsStr> {
198         Resettable::Value(self.into())
199     }
200 }
201 
202 impl<I: Into<Str>> IntoResettable<Str> for I {
into_resettable(self) -> Resettable<Str>203     fn into_resettable(self) -> Resettable<Str> {
204         Resettable::Value(self.into())
205     }
206 }
207 
208 impl<I: Into<crate::Id>> IntoResettable<crate::Id> for I {
into_resettable(self) -> Resettable<crate::Id>209     fn into_resettable(self) -> Resettable<crate::Id> {
210         Resettable::Value(self.into())
211     }
212 }
213