use crate::enums::log_level::LogLevel;
use crate::structs::logger_wasm::LoggerWasm;
use std::cell::RefCell;
use std::io;
use std::sync::OnceLock;
pub struct WasmRefCell<T>(RefCell<T>);
unsafe impl<T> Sync for WasmRefCell<T> {}
impl<T> WasmRefCell<T> {
fn new(value: T) -> Self {
Self(RefCell::new(value))
}
fn borrow(&self) -> std::cell::Ref<T> {
self.0.borrow()
}
fn borrow_mut(&self) -> std::cell::RefMut<T> {
self.0.borrow_mut()
}
}
static GLOBAL_LOGGER: OnceLock<WasmRefCell<LoggerWasm>> = OnceLock::new();
pub fn init_global_logger() -> &'static WasmRefCell<LoggerWasm> {
GLOBAL_LOGGER.get_or_init(|| WasmRefCell::new(LoggerWasm::with_level(LogLevel::Info)))
}
pub fn get_global_logger() -> &'static WasmRefCell<LoggerWasm> {
init_global_logger()
}
pub fn get_global_mut() -> std::cell::RefMut<'static, LoggerWasm> {
GLOBAL_LOGGER
.get_or_init(|| WasmRefCell::new(LoggerWasm::with_level(LogLevel::Info)))
.borrow_mut()
}
pub fn error(message: &str) -> io::Result<()> {
get_global_logger().borrow().error(message)
}
pub fn warning(message: &str) -> io::Result<()> {
get_global_logger().borrow().warning(message)
}
pub fn info(message: &str) -> io::Result<()> {
get_global_logger().borrow().info(message)
}
pub fn debug(message: &str) -> io::Result<()> {
get_global_logger().borrow().debug(message)
}
pub fn trace(message: &str) -> io::Result<()> {
get_global_logger().borrow().trace(message)
}
pub fn log(message: &str) -> io::Result<()> {
get_global_logger().borrow().log(message)
}
pub fn log_with_level(level: LogLevel, message: &str) -> io::Result<()> {
get_global_logger().borrow().log_with_level(level, message)
}
pub fn error_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().error_lazy(message_fn)
}
pub fn warning_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().warning_lazy(message_fn)
}
pub fn info_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().info_lazy(message_fn)
}
pub fn debug_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().debug_lazy(message_fn)
}
pub fn trace_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().trace_lazy(message_fn)
}
pub fn log_lazy<F>(message_fn: F) -> io::Result<()>
where
F: FnOnce() -> String,
{
get_global_logger().borrow().log_lazy(message_fn)
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test_configure!(run_in_browser);
#[test]
fn test_convenience_functions() -> io::Result<()> {
error("Test error")?;
warning("Test warning")?;
info("Test info")?;
debug("Test debug")?;
trace("Test trace")?;
let global_logger = get_global_logger();
let logger = global_logger.borrow();
assert_eq!(logger.level(), LogLevel::Info);
Ok(())
}
#[test]
fn test_lazy_convenience_functions() -> io::Result<()> {
let mut called = false;
debug_lazy(|| {
called = true;
"Debug message".to_string()
})?;
called = false;
info_lazy(|| {
called = true;
"Info message".to_string()
})?;
assert!(
called,
"Lazy closure should have been called for info level"
);
Ok(())
}
#[cfg(target_arch = "wasm32")]
mod wasm_tests {
use super::*;
#[wasm_bindgen_test]
fn test_wasm_logger_initialization() {
let _logger = init_global_logger();
info("Logger initialization test").expect("Logger should be initialized");
}
#[wasm_bindgen_test]
fn test_wasm_logging_functions() {
error("Test error message").expect("Error logging should work");
warning("Test warning message").expect("Warning logging should work");
info("Test info message").expect("Info logging should work");
debug("Test debug message").expect("Debug logging should work");
trace("Test trace message").expect("Trace logging should work");
}
#[wasm_bindgen_test]
fn test_wasm_lazy_logging() {
let mut called = false;
info_lazy(|| {
called = true;
"Lazy info message".to_string()
})
.expect("Lazy info logging should work");
assert!(called, "Lazy closure should have been called");
}
#[wasm_bindgen_test]
fn test_wasm_log_level() {
log("Test message with specific level")
.expect("Logging with specific level should work");
}
}
}