#![doc = include_str!("../README.md")]
#[doc(hidden)]
pub mod _internal {
#[doc(hidden)]
#[macro_export]
macro_rules! _internal_once {
($expression:expr) => {{
use ::core::sync::atomic::{AtomicBool, Ordering};
static SHOULD_FIRE: AtomicBool = AtomicBool::new(true);
if SHOULD_FIRE.swap(false, Ordering::Relaxed) {
$expression;
}
}};
}
#[doc(hidden)]
pub use tracing::error as _error;
#[doc(hidden)]
pub use super::_internal_once as _once;
#[cfg(not(feature = "no_cache_debugger"))]
pub fn _is_debugger_present() -> bool {
use ::core::sync::atomic::{AtomicBool, Ordering};
static DEBUGGER_CHECKED: AtomicBool = AtomicBool::new(false);
static DEBUGGER_ATTACHED: AtomicBool = AtomicBool::new(false);
if !DEBUGGER_CHECKED.swap(true, Ordering::Relaxed) {
DEBUGGER_ATTACHED.swap(check_debugger(), Ordering::Relaxed);
}
DEBUGGER_ATTACHED.load(Ordering::Relaxed)
}
#[cfg(feature = "no_cache_debugger")]
pub fn _is_debugger_present() -> bool {
check_debugger()
}
fn check_debugger() -> bool {
use ::dbg_breakpoint::{is_debugger_present, DebuggerPresence};
let Some(DebuggerPresence::Detected) = is_debugger_present() else {
return false;
};
true
}
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! breakpoint {
() => {};
}
#[macro_export]
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), debug_assertions))]
macro_rules! breakpoint {
() => {
if $crate::_internal::_is_debugger_present() {
unsafe {
::core::arch::asm!("int3;nop");
}
}
};
}
#[macro_export]
#[cfg(all(target_arch = "aarch64", debug_assertions))]
macro_rules! breakpoint {
() => {
if $crate::_internal::_is_debugger_present() {
unsafe {
::core::arch::asm!("brk#0xF000\nnop");
}
}
};
}
#[macro_export]
#[cfg(all(
not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64",)),
debug_assertions
))]
macro_rules! breakpoint {
() => {
if $crate::_internal::_is_debugger_present() {
unsafe {
::core::arch::breakpoint();
}
}
};
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! ensure_always {
($expression: expr) => {};
($expression: expr, $($argument: tt),+ $(,)?) => {};
}
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! ensure_always {
($expression: expr) => {
if !$expression {
$crate::breakpoint!();
}
};
($expression: expr, $($argument: tt),+ $(,)?) => {
if !$expression {
$crate::_internal::_error!($($argument),+);
$crate::breakpoint!();
}
};
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! ensure {
($expression: expr) => {};
($expression: expr, $($argument: tt),+ $(,)?) => {};
}
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! ensure {
($expression: expr) => {
if !$expression {
$crate::_internal::_once!($crate::breakpoint!());
}
};
($expression: expr, $($argument: tt),+ $(,)?) => {
if !$expression {
$crate::_internal::_once!({
$crate::_internal::_error!($($argument),+);
$crate::breakpoint!();
});
}
};
}
#[macro_export]
#[cfg(not(debug_assertions))]
macro_rules! fail_always {
($($argument: tt),+ $(,)?) => {
$crate::_internal::_error!($($argument),+);
};
}
#[macro_export]
#[cfg(debug_assertions)]
macro_rules! fail_always {
($($argument: tt),+ $(,)?) => {
$crate::_internal::_error!($($argument),+);
$crate::breakpoint!();
};
}
#[macro_export]
macro_rules! fail {
($($argument: tt),+ $(,)?) => {
$crate::_internal::_once!($crate::fail_always!($($argument),+));
};
}
pub mod prelude {
pub use super::{breakpoint, ensure, ensure_always, fail, fail_always};
}