rust: add abstraction for vlc_Logger in vlcrs-messages

This patch adds abstraction for vlc_Logger, via the Rust Logger type and
similar macros as the C side with: debug!, info!, warn! and error!.
This commit is contained in:
Loïc Branstett 2023-08-03 17:31:39 +02:00 committed by Felix Paul Kühne
parent 28957228da
commit 25b39a43a5
3 changed files with 147 additions and 0 deletions

View File

@ -1,4 +1,5 @@
[workspace]
members = [
"vlcrs-messages",
"vlcrs-sys-generator"
]

View File

@ -0,0 +1,8 @@
[package]
name = "vlcrs-messages"
version = "0.0.0"
edition = "2021"
license = "LGPL-2.1-or-later"
[dependencies]
vlcrs-utils = { path = "../vlcrs-utils" }

View File

@ -0,0 +1,138 @@
//! Messages facilities.
use std::{ffi::CStr, ptr::NonNull};
mod sys;
use sys::{vlc_Log, vlc_logger};
pub use sys::vlc_log_type as LogType;
/// Logger object to be used with the warn!, error!, log! macros
#[repr(transparent)]
pub struct Logger(pub(crate) NonNull<vlc_logger>);
impl Logger {
/// Log message to the logger
pub fn log(
&self,
priority: LogType,
logger: &CStr,
file: &CStr,
func: &CStr,
line: u32,
msg: &str,
) {
const GENERIC: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"generic\0") };
const PRINTF_S: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"%.*s\0") };
// SAFETY: All the pointers are non-null and points to initialized structs.
unsafe {
vlc_Log(
&self.0.as_ptr(),
priority as i32,
GENERIC.as_ptr(),
logger.as_ptr(),
file.as_ptr(),
line,
func.as_ptr(),
// We do this to avoid manipulating the original formatted string to be printf
// escaped. Using %s is just way simpler.
PRINTF_S.as_ptr(),
msg.len(),
msg.as_ptr(),
)
}
}
}
/// Log for a VLC Object
#[macro_export]
macro_rules! log {
($logger:expr, $level:expr, $format:expr, $($args:expr),*) => {{
// SAFETY: The file name cannot be nul and doens't contains nul byte.
// With the concat of the nul byte the slice is now a C-style array.
let file = unsafe { ::std::ffi::CStr::from_bytes_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) };
let func = ::std::ffi::CString::new(::vlcrs_utils::func!())
.expect("should always be valid utf-8");
let logger = ::std::ffi::CString::new(option_env!("VLC_logger_NAME").unwrap_or("<unknown rust logger>"))
.expect("unable to create the rust module name");
let formatted = ::std::fmt::format(format_args!("{}\0", format_args!($format, $($args),*)));
::vlcrs_messages::Logger::log(
$logger,
$level,
logger.as_c_str(),
file,
func.as_c_str(),
line!(),
&formatted
)
}};
}
/// Debug-level log for a VLC Object
///
/// ```ignore
/// // let logger = ...;
/// vlcrs_messages::debug!(logger, "test");
/// ```
#[macro_export]
#[doc(alias = "msg_Dbg")]
macro_rules! debug {
($logger:expr, $format:expr $(,)?) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_DBG, $format,)
}};
($logger:expr, $format:expr, $($args:tt)*) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_DBG, $format, $($args)*)
}};
}
/// Info-level log for a VLC Object
///
/// ```ignore
/// // let logger = ...;
/// vlcrs_messages::info!(logger, "test");
/// ```
#[macro_export]
#[doc(alias = "msg_Err")]
macro_rules! info {
($logger:expr, $format:expr $(,)?) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_INFO, $format,)
}};
($logger:expr, $format:expr, $($args:tt)*) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_INFO, $format, $($args)*)
}};
}
/// Warning-level log for a VLC Object
///
/// ```ignore
/// // let logger = ...;
/// vlcrs_messages::warn!(logger, "test");
/// ```
#[macro_export]
#[doc(alias = "msg_Warn")]
macro_rules! warn {
($logger:expr, $format:expr $(,)?) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_WARN, $format,)
}};
($logger:expr, $format:expr, $($args:tt)*) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_WARN, $format, $($args)*)
}};
}
/// Error-level log for a VLC Object
///
/// ```ignore
/// // let logger = ...;
/// vlcrs_messages::error!(logger, "test");
/// ```
#[macro_export]
#[doc(alias = "msg_Err")]
macro_rules! error {
($logger:expr, $format:expr $(,)?) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_ERR, $format,)
}};
($logger:expr, $format:expr, $($args:tt)*) => {{
$crate::log!($logger, $crate::LogType::VLC_MSG_ERR, $format, $($args)*)
}};
}