use core::ffi::{c_char, c_int, c_uint};
use std::cell::RefCell;
#[allow(unused)]
pub struct Hilogger {
level: log::LevelFilter,
domain: u32,
log_type: LogType,
}
impl Default for Hilogger {
fn default() -> Self {
Self {
level: log::LevelFilter::Info,
domain: 0,
log_type: LOG_APP,
}
}
}
impl Hilogger {
pub fn new(level: log::LevelFilter, domain: u32, log_type: LogType) -> Self {
Self { level, domain, log_type }
}
pub fn init(self) -> Result<(), log::SetLoggerError> {
log::set_max_level(self.level);
log::set_boxed_logger(Box::new(self))
}
}
thread_local! {
static TAG_BUFFER: RefCell<String> = RefCell::new(String::with_capacity(256));
static MSG_BUFFER: RefCell<String> = RefCell::new(String::with_capacity(1024));
}
impl log::Log for Hilogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level().to_level_filter() <= self.level
}
fn log(&self, record: &log::Record) {
let level = match record.level() {
log::Level::Error => LogLevel::ERROR,
log::Level::Warn => LogLevel::WARN,
log::Level::Info => LogLevel::INFO,
log::Level::Debug => LogLevel::DEBUG,
log::Level::Trace => LogLevel::DEBUG,
};
TAG_BUFFER.with(|tag_buf| {
MSG_BUFFER.with(|msg_buf| {
let mut tag = tag_buf.borrow_mut();
let mut msg = msg_buf.borrow_mut();
tag.clear();
msg.clear();
tag.push_str(record.target());
msg.push_str(&record.args().to_string());
tag.push('\0');
msg.push('\0');
let tag_cstr = core::ffi::CStr::from_bytes_with_nul(tag.as_bytes())
.unwrap_or_else(|_| core::ffi::CStr::from_bytes_with_nul(b"tag\0").unwrap());
let msg_cstr = core::ffi::CStr::from_bytes_with_nul(msg.as_bytes())
.unwrap_or_else(|_| core::ffi::CStr::from_bytes_with_nul(b"msg\0").unwrap());
#[cfg(target_env = "ohos")]
unsafe {
OH_LOG_Print(self.log_type, level, self.domain, tag_cstr.as_ptr(), msg_cstr.as_ptr())
};
#[cfg(not(target_env = "ohos"))]
{
eprintln!(
"[{:?}] {}: {}",
level,
tag_cstr.to_str().unwrap_or("tag"),
msg_cstr.to_str().unwrap_or("msg")
);
}
});
});
}
fn flush(&self) {}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct LogType(pub u32);
pub const LOG_APP: LogType = LogType(0);
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum LogLevel {
DEBUG = 3,
INFO = 4,
WARN = 5,
ERROR = 6,
FATAL = 7,
}
#[cfg_attr(target_env = "ohos", link(name = "hilog_ndk.z"))]
#[allow(unused)]
extern "C" {
fn OH_LOG_Print(type_: LogType, level: LogLevel, domain: c_uint, tag: *const c_char, fmt: *const c_char, ...) -> c_int;
}
pub fn init_default() -> Result<(), log::SetLoggerError> {
Hilogger::default().init()
}
pub fn init(level: log::LevelFilter, domain: u32, log_type: LogType) -> Result<(), log::SetLoggerError> {
Hilogger::new(level, domain, log_type).init()
}