#[cfg(feature = "full")]
#[doc(hidden)]
#[macro_export]
macro_rules! function {
($static:ident) => {
use $crate::once_cell::sync::Lazy;
fn _f() {}
static $static: $crate::once_cell::sync::Lazy<&'static str> =
$crate::once_cell::sync::Lazy::new(|| {
fn type_name_of<T>(_: T) -> &'static str {
::std::any::type_name::<T>()
}
let name = type_name_of(_f);
&name[..name.len() - 4]
});
};
}
#[cfg(feature = "full")]
#[doc(hidden)]
#[macro_export]
macro_rules! assert_helper {
(condition = $condition:expr, $message:literal, $(details = $details:expr)?, $assert_type:path, $display_type:literal, must_hit = $must_hit:literal) => {{
let condition = $condition;
let details = &$crate::serde_json::json!({});
$(let details = $details;)?
$crate::function!(FUN_NAME);
use $crate::assert::AssertionCatalogInfo;
#[$crate::linkme::distributed_slice($crate::assert::ANTITHESIS_CATALOG)]
#[linkme(crate = $crate::linkme)] static ALWAYS_CATALOG_ITEM: AssertionCatalogInfo = AssertionCatalogInfo {
assert_type: $assert_type,
display_type: $display_type,
condition: false,
message: $message,
class: ::std::module_path!(),
function: &FUN_NAME,
file: ::std::file!(),
begin_line: ::std::line!(),
begin_column: ::std::column!(),
must_hit: $must_hit,
id: $message,
};
let ptr_function = Lazy::force(&FUN_NAME);
static TRACKER: $crate::assert::TrackingInfo = $crate::assert::TrackingInfo::new();
$crate::assert::assert_impl(
$assert_type,
$display_type,
condition,
$message,
::std::module_path!(),
*ptr_function,
::std::file!(),
::std::line!(),
::std::column!(),
true,
$must_hit,
$message,
details,
Some(&TRACKER),
)
}}; }
#[cfg(not(feature = "full"))]
#[doc(hidden)]
#[macro_export]
macro_rules! assert_helper {
(condition = $condition:expr, $message:literal, $(details = $details:expr)?, $assert_type:path, $display_type:literal, must_hit = $must_hit:literal) => {{
let condition = $condition;
$(let details = $details;)?
}};
}
#[macro_export]
macro_rules! assert_always {
($condition:expr, $message:literal$(, $details:expr)?) => {
$crate::assert_helper!(
condition = $condition,
$message,
$(details = $details)?,
$crate::assert::AssertType::Always,
"Always",
must_hit = true
)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always`.
Example usage:
`assert_always!(condition_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_always_or_unreachable {
($condition:expr, $message:literal$(, $details:expr)?) => {
$crate::assert_helper!(
condition = $condition,
$message,
$(details = $details)?,
$crate::assert::AssertType::Always,
"AlwaysOrUnreachable",
must_hit = false
)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_or_unreachable`.
Example usage:
`assert_always_or_unreachable!(condition_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes {
($condition:expr, $message:literal$(, $details:expr)?) => {
$crate::assert_helper!(
condition = $condition,
$message,
$(details = $details)?,
$crate::assert::AssertType::Sometimes,
"Sometimes",
must_hit = true
)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes`.
Example usage:
`assert_sometimes!(condition_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_reachable {
($message:literal$(, $details:expr)?) => {
$crate::assert_helper!(
condition = true,
$message,
$(details = $details)?,
$crate::assert::AssertType::Reachability,
"Reachable",
must_hit = true
)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_reachable`.
Example usage:
`assert_reachable!("assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_unreachable {
($message:literal$(, $details:expr)?) => {
$crate::assert_helper!(
condition = false,
$message,
$(details = $details)?,
$crate::assert::AssertType::Reachability,
"Unreachable",
must_hit = false
)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_unreachable`.
Example usage:
`assert_unreachable!("assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[cfg(feature = "full")]
#[doc(hidden)]
#[macro_export]
macro_rules! guidance_helper {
($guidance_type:expr, $message:literal, $maximize:literal, $guidance_data:expr) => {
$crate::function!(FUN_NAME);
use $crate::assert::guidance::{GuidanceCatalogInfo, GuidanceType};
#[$crate::linkme::distributed_slice($crate::assert::ANTITHESIS_GUIDANCE_CATALOG)]
#[linkme(crate = $crate::linkme)] static GUIDANCE_CATALOG_ITEM: GuidanceCatalogInfo = GuidanceCatalogInfo {
guidance_type: $guidance_type,
message: $message,
id: $message,
class: ::std::module_path!(),
function: &FUN_NAME,
file: ::std::file!(),
begin_line: ::std::line!(),
begin_column: ::std::column!(),
maximize: $maximize,
};
$crate::assert::guidance::guidance_impl(
$guidance_type,
$message,
$message,
::std::module_path!(),
*Lazy::force(&FUN_NAME),
::std::file!(),
::std::line!(),
::std::column!(),
$maximize,
$guidance_data,
true,
)
};
}
#[cfg(feature = "full")]
#[doc(hidden)]
#[macro_export]
macro_rules! numeric_guidance_helper {
($assert:path, $op:tt, $maximize:literal, $left:expr, $right:expr, $message:literal$(, $details:expr)?) => {{
let left = $left;
let right = $right;
let details = &$crate::serde_json::json!({});
$(let details = $details;)?
let mut details = details.clone();
details["left"] = left.into();
details["right"] = right.into();
$assert!(left $op right, $message, &details);
let guidance_data = $crate::serde_json::json!({
"left": left,
"right": right,
});
let diff = $crate::assert::guidance::Diff::diff(&left, right);
type Guard<T> = $crate::assert::guidance::Guard<$maximize, T>;
type Distance = f64;
static GUARD: Guard<Distance> = Guard::init();
if GUARD.should_emit(diff) {
$crate::guidance_helper!($crate::assert::guidance::GuidanceType::Numeric, $message, $maximize, guidance_data);
}
}};
}
#[cfg(not(feature = "full"))]
#[doc(hidden)]
#[macro_export]
macro_rules! numeric_guidance_helper {
($assert:path, $op:tt, $maximize:literal, $left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
assert!($left $op $right, $message$(, $details)?);
};
}
#[cfg(feature = "full")]
#[doc(hidden)]
#[macro_export]
macro_rules! boolean_guidance_helper {
($assert:path, $all:literal, {$($name:ident: $cond:expr),*}, $message:literal$(, $details:expr)?) => {{
let details = &$crate::serde_json::json!({});
$(let details = $details;)?
let mut details = details.clone();
let (cond, guidance_data) = {
$(let $name = $cond;)*
$(details[::std::stringify!($name)] = $name.into();)*
(
if $all { true $(&& $name)* } else { false $(|| $name)* },
$crate::serde_json::json!({$(::std::stringify!($name): $name),*})
)
};
$assert!(cond, $message, &details);
$crate::guidance_helper!($crate::assert::guidance::GuidanceType::Boolean, $message, $all, guidance_data);
}};
}
#[cfg(not(feature = "full"))]
#[doc(hidden)]
#[macro_export]
macro_rules! boolean_guidance_helper {
($assert:path, $all:literal, {$($name:ident: $cond:expr),*}, $message:literal$(, $details:expr)?) => {{
let cond = {
$(let $name = $cond;)*
if $all { true $(&& $name)* } else { false $(|| $name)* }
};
$assert!(cond, $message$(, $details)?);
}};
}
#[macro_export]
macro_rules! assert_always_greater_than {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_always, >, false, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_greater_than`.
Example usage:
`assert_always_greater_than!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_always_greater_than_or_equal_to {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_always, >=, false, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_greater_than_or_equal_to`.
Example usage:
`assert_always_greater_than_or_equal_to!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_always_less_than {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_always, <, true, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_less_than`.
Example usage:
`assert_always_less_than!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_always_less_than_or_equal_to {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_always, <=, true, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_less_than_or_equal_to`.
Example usage:
`assert_always_less_than_or_equal_to!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes_greater_than {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_sometimes, >, true, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes_greater_than`.
Example usage:
`assert_sometimes_greater_than!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes_greater_than_or_equal_to {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_sometimes, >=, true, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes_greater_than_or_equal_to`.
Example usage:
`assert_sometimes_greater_than_or_equal_to!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes_less_than {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_sometimes, <, false, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes_less_than`.
Example usage:
`assert_sometimes_less_than!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes_less_than_or_equal_to {
($left:expr, $right:expr, $message:literal$(, $details:expr)?) => {
$crate::numeric_guidance_helper!($crate::assert_sometimes, <=, false, $left, $right, $message$(, $details)?)
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes_less_than_or_equal_to`.
Example usage:
`assert_sometimes_less_than_or_equal_to!(left_expr, right_expr, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_always_some {
({$($($name:ident: $cond:expr),+ $(,)?)?}, $message:literal$(, $details:expr)?) => {
$crate::boolean_guidance_helper!($crate::assert_always, false, {$($($name: $cond),+)?}, $message$(, $details)?);
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_always_some`.
Example usage:
`assert_always_some!({field1: cond1, field2: cond2, ...}, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}
#[macro_export]
macro_rules! assert_sometimes_all {
({$($($name:ident: $cond:expr),+ $(,)?)?}, $message:literal$(, $details:expr)?) => {
$crate::boolean_guidance_helper!($crate::assert_sometimes, true, {$($($name: $cond),+)?}, $message$(, $details)?);
};
($($rest:tt)*) => {
::std::compile_error!(
r#"Invalid syntax when calling macro `assert_sometimes_all`.
Example usage:
`assert_sometimes_all!({field1: cond1, field2: cond2, ...}, "assertion message (static literal)", &details_json_value_expr)`
"#
);
};
}