1use crate::util::AnyValueId;
2
3/// Violation of [`ArgMatches`][crate::ArgMatches] assumptions
4#[derive(Clone, Debug)]
5#[allow(missing_copy_implementations)] // We might add non-Copy types in the future
6#[non_exhaustive]
7pub enum MatchesError {
8 /// Failed to downcast `AnyValue` to the specified type
9 #[non_exhaustive]
10 Downcast {
11 /// Type for value stored in [`ArgMatches`][crate::ArgMatches]
12 actual: AnyValueId,
13 /// The target type to downcast to
14 expected: AnyValueId,
15 },
16 /// Argument not defined in [`Command`][crate::Command]
17 #[non_exhaustive]
18 UnknownArgument {
19 // Missing `id` but blocked on a public id type which will hopefully come with `unstable-v4`
20 },
21}
22
23impl MatchesError {
24 #[cfg_attr(debug_assertions, track_caller)]
25 pub(crate) fn unwrap<T>(id: &str, r: Result<T, MatchesError>) -> T {
26 let err: MatchesError = match r {
27 Ok(t: T) => {
28 return t;
29 }
30 Err(err: MatchesError) => err,
31 };
32 panic!("Mismatch between definition and access of `{id}`. {err}",)
33 }
34}
35
36impl std::error::Error for MatchesError {}
37
38impl std::fmt::Display for MatchesError {
39 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40 match self {
41 Self::Downcast { actual: &AnyValueId, expected: &AnyValueId } => {
42 writeln!(
43 f,
44 "Could not downcast to {expected:?}, need to downcast to {actual:?}"
45 )
46 }
47 Self::UnknownArgument {} => {
48 writeln!(f, "Unknown argument or group id. Make sure you are using the argument id and not the short or long flags")
49 }
50 }
51 }
52}
53
54#[test]
55fn check_auto_traits() {
56 static_assertions::assert_impl_all!(
57 MatchesError: Send,
58 Sync,
59 std::panic::RefUnwindSafe,
60 std::panic::UnwindSafe,
61 Unpin
62 );
63}
64