1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9#[repr(u8)]
10pub enum LogLevel {
11 Trace = 0,
12 Debug = 1,
13 Info = 2,
14 Warn = 3,
15 Error = 4,
16}
17
18#[cfg(target_arch = "wasm32")]
20extern "C" {
21 fn host_log_impl(level: u8, ptr: *const u8, len: u32);
22}
23
24#[cfg(target_arch = "wasm32")]
25#[inline(always)]
26fn host_log(level: u8, ptr: *const u8, len: u32) {
27 unsafe {
28 host_log_impl(level, ptr, len);
29 }
30}
31
32#[cfg(not(target_arch = "wasm32"))]
34#[inline(always)]
35fn host_log(_level: u8, _ptr: *const u8, _len: u32) {}
36
37pub use self::log::{debug_fmt, error_fmt, info_fmt, log_fmt, warn_fmt};
40
41pub mod log {
44 use super::LogLevel;
45 use core::fmt::Write;
46
47 struct LogBuf {
49 buf: [u8; 255],
50 pos: usize,
51 }
52
53 impl LogBuf {
54 #[inline(always)]
55 const fn new() -> Self {
56 Self {
57 buf: [0u8; 255],
58 pos: 0,
59 }
60 }
61
62 #[inline(always)]
63 fn as_slice(&self) -> &[u8] {
64 &self.buf[..self.pos]
65 }
66 }
67
68 impl Write for LogBuf {
69 fn write_str(&mut self, s: &str) -> core::fmt::Result {
70 let bytes = s.as_bytes();
71 let space = self.buf.len() - self.pos;
72 let n = bytes.len().min(space);
73 self.buf[self.pos..self.pos + n].copy_from_slice(&bytes[..n]);
74 self.pos += n;
75 Ok(())
76 }
77 }
78
79 #[inline(always)]
80 fn send(level: LogLevel, msg: &[u8]) {
81 super::host_log(level as u8, msg.as_ptr(), msg.len() as u32);
82 }
83
84 #[inline(always)]
86 pub fn trace(msg: &str) {
87 send(LogLevel::Trace, msg.as_bytes());
88 }
89
90 #[inline(always)]
92 pub fn debug(msg: &str) {
93 send(LogLevel::Debug, msg.as_bytes());
94 }
95
96 #[inline(always)]
98 pub fn info(msg: &str) {
99 send(LogLevel::Info, msg.as_bytes());
100 }
101
102 #[inline(always)]
104 pub fn warn(msg: &str) {
105 send(LogLevel::Warn, msg.as_bytes());
106 }
107
108 #[inline(always)]
110 pub fn error(msg: &str) {
111 send(LogLevel::Error, msg.as_bytes());
112 }
113
114 #[inline]
116 pub fn log_fmt(level: LogLevel, args: core::fmt::Arguments<'_>) {
117 let mut buf = LogBuf::new();
118 let _ = buf.write_fmt(args);
119 send(level, buf.as_slice());
120 }
121
122 #[inline]
124 pub fn info_fmt(args: core::fmt::Arguments<'_>) {
125 log_fmt(LogLevel::Info, args);
126 }
127
128 #[inline]
130 pub fn warn_fmt(args: core::fmt::Arguments<'_>) {
131 log_fmt(LogLevel::Warn, args);
132 }
133
134 #[inline]
136 pub fn error_fmt(args: core::fmt::Arguments<'_>) {
137 log_fmt(LogLevel::Error, args);
138 }
139
140 #[inline]
142 pub fn debug_fmt(args: core::fmt::Arguments<'_>) {
143 log_fmt(LogLevel::Debug, args);
144 }
145}