#[macro_export]
macro_rules! build_unwind_context_data {
( fn $name:ident ( $( $args:tt )* ) ) => {
$crate::build_unwind_context_data_impl!( @fn ::core::stringify!($name), $($args)* )
};
( fn $name:literal ( $( $args:tt )* ) ) => {
$crate::build_unwind_context_data_impl!( @fn $name, $($args)* )
};
( fn ( $( $args:tt )* ) ) => {
$crate::build_unwind_context_data_impl!( @fn $crate::func_name!(), $($args)* )
};
( $( $vars:tt )* ) => {
$crate::UnwindContextArgs::new(
$crate::build_unwind_context_data_impl!( @args $($vars)* )
)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! build_unwind_context_data_impl {
( @fn $name:expr, $( $args:tt )* ) => {
$crate::UnwindContextFunc::new(
$name,
$crate::build_unwind_context_data_impl!( @args $($args)* )
)
};
( @args ... $(, $( $args:tt )* )? ) => {
(
$crate::UnwindContextArg::new( None, $crate::NonExhaustiveMarker ),
$crate::build_unwind_context_data_impl!( @args $( $($args)* )? ),
)
};
( @args $value:literal $(, $( $args:tt )* )? ) => {
(
$crate::UnwindContextArg::new( None, $value ),
$crate::build_unwind_context_data_impl!( @args $( $($args)* )? ),
)
};
( @args $arg:expr $(, $( $args:tt )* )? ) => {
(
$crate::UnwindContextArg::new( Some(::core::stringify!($arg)), $arg ),
$crate::build_unwind_context_data_impl!( @args $( $($args)* )? ),
)
};
( @args ) => {
()
};
}
#[cfg(test)]
mod tests {
use core::fmt::Debug;
use crate::test_util::buf_fmt;
#[allow(clippy::similar_names)]
#[test]
fn test_unwind_context_data() {
fn inner_context1(foo: i32, bar: &str) -> impl '_ + Debug {
build_unwind_context_data!(fn(foo, bar))
}
fn inner_context2(foo: i32, bar: &str, _extra_data: ()) -> impl '_ + Debug {
build_unwind_context_data!(fn(foo, bar, ...))
}
let mut buffer = [0; 128];
let foo = 123;
let bar = "value";
let context = build_unwind_context_data!(foo);
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "foo: 123");
let context = build_unwind_context_data!(foo, 234);
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "foo: 123, 234");
let context = build_unwind_context_data!(foo, 234, bar);
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "foo: 123, 234, bar: \"value\"");
let context = build_unwind_context_data!(fn func(foo, 234, bar));
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "fn func(foo: 123, 234, bar: \"value\")");
let context = build_unwind_context_data!(fn "mod::func"(foo, 234, bar));
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "fn mod::func(foo: 123, 234, bar: \"value\")");
let context = build_unwind_context_data!(fn func(..., foo, 234, bar));
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "fn func(..., foo: 123, 234, bar: \"value\")");
let context = build_unwind_context_data!(fn func(foo, ..., 234, bar));
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "fn func(foo: 123, ..., 234, bar: \"value\")");
let context = build_unwind_context_data!(fn func(foo, 234, bar, ...));
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert_eq!(formatted, "fn func(foo: 123, 234, bar: \"value\", ...)");
let context = inner_context1(foo, bar);
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert!(formatted.starts_with("fn "));
assert!(formatted.contains("inner_context1"));
assert!(formatted.ends_with("(foo: 123, bar: \"value\")"));
let context = inner_context2(foo, bar, ());
let formatted = buf_fmt(&mut buffer, format_args!("{context:?}")).unwrap();
assert!(formatted.starts_with("fn "));
assert!(formatted.contains("inner_context2"));
assert!(formatted.ends_with("(foo: 123, bar: \"value\", ...)"));
}
}