hilogger 0.1.1

a ohos hilog bind to log.
Documentation
use core::ffi::{c_char, c_int, c_uint};
use std::cell::RefCell;

/// Simplified logger for HarmonyOS hilog system
#[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 {
	/// Create a new logger with custom settings
	pub fn new(level: log::LevelFilter, domain: u32, log_type: LogType) -> Self {
		Self { level, domain, log_type }
	}

	/// Initialize the logger
	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());

				// Add null terminators
				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) {}
}

/// Log type wrapper
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct LogType(pub u32);

/// Application log type
pub const LOG_APP: LogType = LogType(0);

/// Log levels
#[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;
}

/// Convenience function to initialize default logger
pub fn init_default() -> Result<(), log::SetLoggerError> {
	Hilogger::default().init()
}

/// Convenience function to initialize logger with custom settings
pub fn init(level: log::LevelFilter, domain: u32, log_type: LogType) -> Result<(), log::SetLoggerError> {
	Hilogger::new(level, domain, log_type).init()
}