use supernovas_ffi::novas_debug_mode;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DebugMode {
Off,
On,
Extra,
}
impl DebugMode {
fn to_sys(self) -> novas_debug_mode {
match self {
DebugMode::Off => novas_debug_mode::NOVAS_DEBUG_OFF,
DebugMode::On => novas_debug_mode::NOVAS_DEBUG_ON,
DebugMode::Extra => novas_debug_mode::NOVAS_DEBUG_EXTRA,
}
}
fn from_sys(m: novas_debug_mode) -> Self {
match m {
novas_debug_mode::NOVAS_DEBUG_ON => DebugMode::On,
novas_debug_mode::NOVAS_DEBUG_EXTRA => DebugMode::Extra,
novas_debug_mode::NOVAS_DEBUG_OFF => DebugMode::Off,
}
}
}
#[cfg(feature = "std")]
unsafe extern "C" fn capture_handler(
fmt: *const ::std::os::raw::c_char,
_args: *mut supernovas_ffi::__va_list_tag,
) {
use std::ffi::CStr;
let Ok(s) = unsafe { CStr::from_ptr(fmt) }.to_str() else {
return;
};
if s.starts_with('\n') || s.starts_with(" [=>") || s.starts_with(" @") {
return;
}
crate::error::set_provider_error(s);
}
pub fn enable_debug_mode(mode: DebugMode) {
unsafe {
if mode == DebugMode::Off {
supernovas_ffi::novas_debug(novas_debug_mode::NOVAS_DEBUG_OFF);
#[cfg(feature = "std")]
supernovas_ffi::novas_set_error_handler(None);
} else {
#[cfg(feature = "std")]
supernovas_ffi::novas_set_error_handler(Some(capture_handler));
supernovas_ffi::novas_debug(mode.to_sys());
}
}
}
#[must_use]
pub fn get_debug_mode() -> DebugMode {
DebugMode::from_sys(unsafe { supernovas_ffi::novas_get_debug_mode() })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_all_modes() {
for mode in [DebugMode::Off, DebugMode::On, DebugMode::Extra] {
enable_debug_mode(mode);
assert_eq!(get_debug_mode(), mode);
}
enable_debug_mode(DebugMode::Off);
}
#[test]
fn debug_mode_eq_and_clone() {
assert_eq!(DebugMode::On, DebugMode::On);
assert_ne!(DebugMode::On, DebugMode::Extra);
let _ = DebugMode::Off;
}
#[test]
fn debug_mode_debug_format() {
assert_eq!(format!("{:?}", DebugMode::On), "On");
assert_eq!(format!("{:?}", DebugMode::Extra), "Extra");
assert_eq!(format!("{:?}", DebugMode::Off), "Off");
}
}