1use std::fmt;
7
8#[macro_export]
33macro_rules! assert_match {
34 ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => {
35 match $left {
36 $( $pattern )|+ $( if $guard )? => {}
37 ref left_val => {
38 $crate::assert::assert_matches_failed(
39 left_val,
40 stringify!($($pattern)|+ $(if $guard)?),
41 core::option::Option::None
42 );
43 }
44 }
45 };
46 ($left:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $($arg:tt)+) => {
47 match $left {
48 $( $pattern )|+ $( if $guard )? => {}
49 ref left_val => {
50 $crate::assert::assert_matches_failed(
51 left_val,
52 stringify!($($pattern)|+ $(if $guard)?),
53 std::option::Option::Some(std::format_args!($($arg)+))
54 );
55 }
56 }
57 };
58}
59
60#[derive(Debug)]
61#[doc(hidden)]
62pub enum AssertKind {
63 Eq,
64 Ne,
65 Match,
66}
67
68#[cold]
70#[track_caller]
71#[doc(hidden)]
72pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(left: &T, right: &str, args: Option<fmt::Arguments<'_>>) -> ! {
73 struct Pattern<'a>(&'a str);
75 impl fmt::Debug for Pattern<'_> {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 fmt::Display::fmt(self.0, f)
78 }
79 }
80 assert_failed_inner(AssertKind::Match, &left, &Pattern(right), args);
81}
82
83#[track_caller]
85fn assert_failed_inner(kind: AssertKind, left: &dyn fmt::Debug, right: &dyn fmt::Debug, args: Option<fmt::Arguments<'_>>) -> ! {
86 let op = match kind {
87 AssertKind::Eq => "==",
88 AssertKind::Ne => "!=",
89 AssertKind::Match => "matches",
90 };
91
92 match args {
93 Some(args) => panic!(
94 r#"assertion failed: `(left {op} right)`
95 left: `{left:?}`,
96 right: `{right:?}`: {args}"#
97 ),
98 None => panic!(
99 r#"assertion failed: `(left {op} right)`
100 left: `{left:?}`,
101 right: `{right:?}`"#,
102 ),
103 }
104}