use std::sync::OnceLock;
use libloading::Symbol;
use litert_sys as sys;
use crate::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum LogSeverity {
Debug,
Verbose,
Info,
Warning,
Error,
Silent,
}
impl LogSeverity {
fn to_raw(self) -> sys::LiteRtLogSeverity {
match self {
Self::Debug => sys::kLiteRtLogSeverityDebug,
Self::Verbose => sys::kLiteRtLogSeverityVerbose,
Self::Info => sys::kLiteRtLogSeverityInfo,
Self::Warning => sys::kLiteRtLogSeverityWarning,
Self::Error => sys::kLiteRtLogSeverityError,
Self::Silent => sys::kLiteRtLogSeveritySilent,
}
}
}
pub fn set_global_log_severity(severity: LogSeverity) -> Result<()> {
let hooks = logger_hooks().ok_or(Error::Unsupported("logger-control symbols"))?;
let logger = unsafe { (hooks.get_default)() };
if logger.is_null() {
return Err(Error::NullPointer);
}
crate::check(unsafe { (hooks.set_min_severity)(logger, severity.to_raw()) })
}
struct LoggerHooks {
get_default: unsafe extern "C" fn() -> sys::LiteRtLogger,
set_min_severity:
unsafe extern "C" fn(sys::LiteRtLogger, sys::LiteRtLogSeverity) -> sys::LiteRtStatus,
}
unsafe impl Sync for LoggerHooks {}
unsafe impl Send for LoggerHooks {}
fn logger_hooks() -> Option<&'static LoggerHooks> {
static HOOKS: OnceLock<Option<LoggerHooks>> = OnceLock::new();
HOOKS.get_or_init(resolve_logger_hooks).as_ref()
}
fn resolve_logger_hooks() -> Option<LoggerHooks> {
#[cfg(unix)]
let lib: libloading::Library = libloading::os::unix::Library::this().into();
#[cfg(windows)]
let lib = unsafe { libloading::Library::new("LiteRt.dll") }.ok()?;
unsafe {
let get_default: Symbol<unsafe extern "C" fn() -> sys::LiteRtLogger> =
lib_get(&lib, b"LiteRtGetDefaultLogger\0")?;
let set_min_severity: Symbol<
unsafe extern "C" fn(sys::LiteRtLogger, sys::LiteRtLogSeverity) -> sys::LiteRtStatus,
> = lib_get(&lib, b"LiteRtSetMinLoggerSeverity\0")?;
Some(LoggerHooks {
get_default: *get_default.into_raw(),
set_min_severity: *set_min_severity.into_raw(),
})
}
}
unsafe fn lib_get<'a, T>(lib: &'a libloading::Library, name: &[u8]) -> Option<Symbol<'a, T>> {
lib.get(name).ok()
}