use log::{debug, error, info, warn};
use rustsynth_sys as ffi;
use std::{
ffi::{c_char, c_void, CStr},
ptr::NonNull,
};
#[derive(Debug, Clone, Copy)]
pub enum MessageType {
Debug = 0,
Information = 1,
Warning = 2,
Critical = 3,
Fatal = 4,
}
impl From<i32> for MessageType {
fn from(value: i32) -> Self {
match value {
0 => Self::Debug,
1 => Self::Information,
2 => Self::Warning,
3 => Self::Critical,
4 => Self::Fatal,
_ => Self::Debug, }
}
}
impl From<MessageType> for i32 {
fn from(msg: MessageType) -> Self {
match msg {
MessageType::Debug => 0,
MessageType::Information => 1,
MessageType::Warning => 2,
MessageType::Critical => 3,
MessageType::Fatal => 4,
}
}
}
pub struct LogHandle<H: LogHandler> {
handle: NonNull<ffi::VSLogHandle>,
_handler: H,
}
impl<H: LogHandler> LogHandle<H> {
pub const unsafe fn from_ptr(ptr: *mut ffi::VSLogHandle, handler: H) -> Self {
Self {
handle: NonNull::new_unchecked(ptr),
_handler: handler,
}
}
pub const fn as_ptr(&self) -> *mut ffi::VSLogHandle {
self.handle.as_ptr()
}
}
pub trait LogHandler: Send + Sync {
fn handle(&self, msg_type: MessageType, msg: &str);
}
pub(crate) unsafe extern "C" fn log_handler_callback(
msg_type: i32,
msg: *const c_char,
userdata: *mut c_void,
) {
if userdata.is_null() || msg.is_null() {
return;
}
let handler = *(userdata as *const &dyn LogHandler);
let message_type = MessageType::from(msg_type);
if let Ok(message_str) = CStr::from_ptr(msg).to_str() {
handler.handle(message_type, message_str);
}
}
pub struct LogRS {}
impl LogHandler for LogRS {
fn handle(&self, msg_type: MessageType, msg: &str) {
match msg_type {
MessageType::Debug => debug!("{msg}"),
MessageType::Information => info!("{msg}"),
MessageType::Warning => warn!("{msg}"),
MessageType::Critical => error!("{msg}"),
MessageType::Fatal => error!("{msg}"),
}
}
}