• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::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)]
32 pub enum Resettable<T> {
33     /// Overwrite builder value
34     Value(T),
35     /// Reset builder value
36     Reset,
37 }
38 
39 impl<T> Resettable<T> {
into_option(self) -> Option<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 
48 impl<T> From<T> for Resettable<T> {
from(other: T) -> Self49     fn from(other: T) -> Self {
50         Self::Value(other)
51     }
52 }
53 
54 impl<T> From<Option<T>> for Resettable<T> {
from(other: Option<T>) -> Self55     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
64 pub trait IntoResettable<T> {
65     /// Convert to the intended resettable type
into_resettable(self) -> Resettable<T>66     fn into_resettable(self) -> Resettable<T>;
67 }
68 
69 impl IntoResettable<char> for Option<char> {
into_resettable(self) -> Resettable<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 
78 impl IntoResettable<usize> for Option<usize> {
into_resettable(self) -> Resettable<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 
87 impl IntoResettable<ArgAction> for Option<ArgAction> {
into_resettable(self) -> Resettable<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 
96 impl IntoResettable<ValueHint> for Option<ValueHint> {
into_resettable(self) -> Resettable<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 
105 impl IntoResettable<ValueParser> for Option<ValueParser> {
into_resettable(self) -> Resettable<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 
114 impl IntoResettable<StyledStr> for Option<&'static str> {
into_resettable(self) -> Resettable<StyledStr>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 
123 impl IntoResettable<OsStr> for Option<&'static str> {
into_resettable(self) -> Resettable<OsStr>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 
132 impl IntoResettable<Str> for Option<&'static str> {
into_resettable(self) -> Resettable<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 
141 impl<T> IntoResettable<T> for Resettable<T> {
into_resettable(self) -> Resettable<T>142     fn into_resettable(self) -> Resettable<T> {
143         self
144     }
145 }
146 
147 impl IntoResettable<char> for char {
into_resettable(self) -> Resettable<char>148     fn into_resettable(self) -> Resettable<char> {
149         Resettable::Value(self)
150     }
151 }
152 
153 impl IntoResettable<usize> for usize {
into_resettable(self) -> Resettable<usize>154     fn into_resettable(self) -> Resettable<usize> {
155         Resettable::Value(self)
156     }
157 }
158 
159 impl IntoResettable<ArgAction> for ArgAction {
into_resettable(self) -> Resettable<ArgAction>160     fn into_resettable(self) -> Resettable<ArgAction> {
161         Resettable::Value(self)
162     }
163 }
164 
165 impl IntoResettable<ValueHint> for ValueHint {
into_resettable(self) -> Resettable<ValueHint>166     fn into_resettable(self) -> Resettable<ValueHint> {
167         Resettable::Value(self)
168     }
169 }
170 
171 impl<I: Into<ValueRange>> IntoResettable<ValueRange> for I {
into_resettable(self) -> Resettable<ValueRange>172     fn into_resettable(self) -> Resettable<ValueRange> {
173         Resettable::Value(self.into())
174     }
175 }
176 
177 impl<I: Into<ValueParser>> IntoResettable<ValueParser> for I {
into_resettable(self) -> Resettable<ValueParser>178     fn into_resettable(self) -> Resettable<ValueParser> {
179         Resettable::Value(self.into())
180     }
181 }
182 
183 impl<I: Into<String>> IntoResettable<String> for I {
into_resettable(self) -> Resettable<String>184     fn into_resettable(self) -> Resettable<String> {
185         Resettable::Value(self.into())
186     }
187 }
188 
189 impl<I: Into<StyledStr>> IntoResettable<StyledStr> for I {
into_resettable(self) -> Resettable<StyledStr>190     fn into_resettable(self) -> Resettable<StyledStr> {
191         Resettable::Value(self.into())
192     }
193 }
194 
195 impl<I: Into<OsStr>> IntoResettable<OsStr> for I {
into_resettable(self) -> Resettable<OsStr>196     fn into_resettable(self) -> Resettable<OsStr> {
197         Resettable::Value(self.into())
198     }
199 }
200 
201 impl<I: Into<Str>> IntoResettable<Str> for I {
into_resettable(self) -> Resettable<Str>202     fn into_resettable(self) -> Resettable<Str> {
203         Resettable::Value(self.into())
204     }
205 }
206 
207 impl<I: Into<crate::Id>> IntoResettable<crate::Id> for I {
into_resettable(self) -> Resettable<crate::Id>208     fn into_resettable(self) -> Resettable<crate::Id> {
209         Resettable::Value(self.into())
210     }
211 }
212