#![allow(clippy::not_unsafe_ptr_arg_deref)]
use crate::sys::{
VT_log_critical, VT_log_error, VT_log_info, VT_log_spec_violation, VT_log_unimplemented,
};
use crate::{
simics_exception,
sys::{SIM_log_level, SIM_log_register_groups, SIM_set_log_level},
ConfClass, ConfObject, Error, Result,
};
use std::{ffi::CString, ptr::null};
pub const LOG_GROUP: i32 = 0;
#[repr(i32)]
pub enum LogLevel {
Error = 0,
Warn = 1,
Info = 2,
Debug = 3,
Trace = 4,
}
fn sanitize<S>(s: S) -> String
where
S: AsRef<str>,
{
s.as_ref().replace('%', "%%")
}
#[simics_exception]
pub fn log_info<S>(level: LogLevel, device: *mut ConfObject, msg: S) -> Result<()>
where
S: AsRef<str>,
{
let msg_cstring = CString::new(msg.as_ref())?;
unsafe {
VT_log_info(level as i32, device, LOG_GROUP as u64, msg_cstring.as_ptr());
}
Ok(())
}
#[simics_exception]
pub fn log_error<S>(device: *mut ConfObject, msg: S) -> Result<()>
where
S: AsRef<str>,
{
let msg_cstring = CString::new(sanitize(msg.as_ref()))?;
unsafe {
VT_log_error(device, LOG_GROUP as u64, msg_cstring.as_ptr());
};
Ok(())
}
#[simics_exception]
pub fn log_critical<S>(device: *mut ConfObject, msg: S) -> Result<()>
where
S: AsRef<str>,
{
let msg_cstring = CString::new(sanitize(msg.as_ref()))?;
unsafe {
VT_log_critical(device, LOG_GROUP as u64, msg_cstring.as_ptr());
};
Ok(())
}
#[simics_exception]
pub fn log_spec_violation(level: LogLevel, device: *mut ConfObject, msg: String) -> Result<()> {
let msg_cstring = CString::new(sanitize(msg))?;
unsafe {
VT_log_spec_violation(level as i32, device, LOG_GROUP as u64, msg_cstring.as_ptr());
};
Ok(())
}
#[simics_exception]
pub fn log_unimplemented(level: LogLevel, device: *mut ConfObject, msg: String) -> Result<()> {
let msg_cstring = CString::new(sanitize(msg))?;
unsafe {
VT_log_unimplemented(level as i32, device, LOG_GROUP as u64, msg_cstring.as_ptr());
};
Ok(())
}
#[simics_exception]
pub fn log_level(obj: *mut ConfObject) -> u32 {
unsafe { SIM_log_level(obj as *const ConfObject) }
}
#[simics_exception]
pub fn set_log_level(obj: *mut ConfObject, level: LogLevel) {
unsafe { SIM_set_log_level(obj, level as u32) };
}
#[simics_exception]
pub fn log_register_groups<S>(cls: *mut ConfClass, names: &[S]) -> Result<()>
where
S: AsRef<str>,
{
let name_cstrs = names
.iter()
.map(|n| CString::new(n.as_ref()).map_err(Error::from))
.collect::<Result<Vec<CString>>>()?;
let mut name_ptrs = name_cstrs.iter().map(|n| n.as_ptr()).collect::<Vec<_>>();
name_ptrs.push(null());
unsafe { SIM_log_register_groups(cls, name_ptrs.as_ptr()) };
Ok(())
}