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