use log::{Level, LevelFilter, Log, Metadata, Record};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = log)]
fn console_log(s: &str);
#[wasm_bindgen(js_namespace = console, js_name = warn)]
fn console_warn(s: &str);
#[wasm_bindgen(js_namespace = console, js_name = error)]
fn console_error(s: &str);
}
struct ConsoleLogger;
impl Log for ConsoleLogger {
fn enabled(&self, metadata: &Metadata) -> bool {
metadata.level() <= log::max_level()
}
fn log(&self, record: &Record) {
if !self.enabled(record.metadata()) {
return;
}
let msg = format!("[brepkit:{}] {}", record.target(), record.args());
match record.level() {
Level::Error => console_error(&msg),
Level::Warn => console_warn(&msg),
_ => console_log(&msg),
}
}
fn flush(&self) {}
}
static LOGGER: ConsoleLogger = ConsoleLogger;
fn set_log_level(level: LevelFilter) {
let _ = log::set_logger(&LOGGER);
log::set_max_level(level);
}
fn parse_level(s: &str) -> Option<LevelFilter> {
Some(match s.to_ascii_lowercase().as_str() {
"off" => LevelFilter::Off,
"error" => LevelFilter::Error,
"warn" => LevelFilter::Warn,
"info" => LevelFilter::Info,
"debug" => LevelFilter::Debug,
"trace" => LevelFilter::Trace,
_ => return None,
})
}
#[wasm_bindgen(js_name = "setLogLevel")]
pub fn js_set_log_level(level: &str) -> Result<(), JsError> {
let parsed = parse_level(level).ok_or_else(|| {
JsError::new(&format!(
"setLogLevel: unknown level {level:?}; expected one of \
\"off\", \"error\", \"warn\", \"info\", \"debug\", \"trace\""
))
})?;
set_log_level(parsed);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_level_known_values() {
assert_eq!(parse_level("off"), Some(LevelFilter::Off));
assert_eq!(parse_level("error"), Some(LevelFilter::Error));
assert_eq!(parse_level("warn"), Some(LevelFilter::Warn));
assert_eq!(parse_level("info"), Some(LevelFilter::Info));
assert_eq!(parse_level("debug"), Some(LevelFilter::Debug));
assert_eq!(parse_level("trace"), Some(LevelFilter::Trace));
}
#[test]
fn parse_level_is_case_insensitive() {
assert_eq!(parse_level("WARN"), Some(LevelFilter::Warn));
assert_eq!(parse_level("Warn"), Some(LevelFilter::Warn));
assert_eq!(parse_level("Trace"), Some(LevelFilter::Trace));
}
#[test]
fn parse_level_unknown_returns_none() {
assert_eq!(parse_level("warnn"), None);
assert_eq!(parse_level(""), None);
assert_eq!(parse_level(" warn"), None);
assert_eq!(parse_level("verbose"), None);
}
}