#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum LogLevel {
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
}
#[cfg(target_arch = "wasm32")]
extern "C" {
fn host_log_impl(level: u8, ptr: *const u8, len: u32);
}
#[cfg(target_arch = "wasm32")]
#[inline(always)]
fn host_log(level: u8, ptr: *const u8, len: u32) {
unsafe {
host_log_impl(level, ptr, len);
}
}
#[cfg(not(target_arch = "wasm32"))]
#[inline(always)]
fn host_log(_level: u8, _ptr: *const u8, _len: u32) {}
pub use self::log::{debug_fmt, error_fmt, info_fmt, log_fmt, warn_fmt};
pub mod log {
use super::LogLevel;
use core::fmt::Write;
struct LogBuf {
buf: [u8; 255],
pos: usize,
}
impl LogBuf {
#[inline(always)]
const fn new() -> Self {
Self {
buf: [0u8; 255],
pos: 0,
}
}
#[inline(always)]
fn as_slice(&self) -> &[u8] {
&self.buf[..self.pos]
}
}
impl Write for LogBuf {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
let bytes = s.as_bytes();
let space = self.buf.len() - self.pos;
let n = bytes.len().min(space);
self.buf[self.pos..self.pos + n].copy_from_slice(&bytes[..n]);
self.pos += n;
Ok(())
}
}
#[inline(always)]
fn send(level: LogLevel, msg: &[u8]) {
super::host_log(level as u8, msg.as_ptr(), msg.len() as u32);
}
#[inline(always)]
pub fn trace(msg: &str) {
send(LogLevel::Trace, msg.as_bytes());
}
#[inline(always)]
pub fn debug(msg: &str) {
send(LogLevel::Debug, msg.as_bytes());
}
#[inline(always)]
pub fn info(msg: &str) {
send(LogLevel::Info, msg.as_bytes());
}
#[inline(always)]
pub fn warn(msg: &str) {
send(LogLevel::Warn, msg.as_bytes());
}
#[inline(always)]
pub fn error(msg: &str) {
send(LogLevel::Error, msg.as_bytes());
}
#[inline]
pub fn log_fmt(level: LogLevel, args: core::fmt::Arguments<'_>) {
let mut buf = LogBuf::new();
let _ = buf.write_fmt(args);
send(level, buf.as_slice());
}
#[inline]
pub fn info_fmt(args: core::fmt::Arguments<'_>) {
log_fmt(LogLevel::Info, args);
}
#[inline]
pub fn warn_fmt(args: core::fmt::Arguments<'_>) {
log_fmt(LogLevel::Warn, args);
}
#[inline]
pub fn error_fmt(args: core::fmt::Arguments<'_>) {
log_fmt(LogLevel::Error, args);
}
#[inline]
pub fn debug_fmt(args: core::fmt::Arguments<'_>) {
log_fmt(LogLevel::Debug, args);
}
}