1use std::{ffi::CString, fmt};
2
3use crate::sys;
4
5macro_rules! call_ffi {
6 ($call:expr) => {{
7 unsafe { $call }
9 }};
10}
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub enum LogLevel {
14 Disable,
15 Console,
16 Alert,
17 Critical,
18 Error,
19 Warning,
20 Notice,
21 Info,
22 Debug,
23 Debug1,
24 Debug2,
25 Debug3,
26 Debug4,
27 Debug5,
28 Debug6,
29 Debug7,
30 Debug8,
31 Debug9,
32 Debug10,
33 Invalid,
34 Uninit,
35}
36
37impl LogLevel {
38 pub const fn as_raw(self) -> sys::switch_log_level_t {
39 match self {
40 Self::Disable => sys::switch_log_level_t_SWITCH_LOG_DISABLE,
41 Self::Console => sys::switch_log_level_t_SWITCH_LOG_CONSOLE,
42 Self::Alert => sys::switch_log_level_t_SWITCH_LOG_ALERT,
43 Self::Critical => sys::switch_log_level_t_SWITCH_LOG_CRIT,
44 Self::Error => sys::switch_log_level_t_SWITCH_LOG_ERROR,
45 Self::Warning => sys::switch_log_level_t_SWITCH_LOG_WARNING,
46 Self::Notice => sys::switch_log_level_t_SWITCH_LOG_NOTICE,
47 Self::Info => sys::switch_log_level_t_SWITCH_LOG_INFO,
48 Self::Debug => sys::switch_log_level_t_SWITCH_LOG_DEBUG,
49 Self::Debug1 => sys::switch_log_level_t_SWITCH_LOG_DEBUG1,
50 Self::Debug2 => sys::switch_log_level_t_SWITCH_LOG_DEBUG2,
51 Self::Debug3 => sys::switch_log_level_t_SWITCH_LOG_DEBUG3,
52 Self::Debug4 => sys::switch_log_level_t_SWITCH_LOG_DEBUG4,
53 Self::Debug5 => sys::switch_log_level_t_SWITCH_LOG_DEBUG5,
54 Self::Debug6 => sys::switch_log_level_t_SWITCH_LOG_DEBUG6,
55 Self::Debug7 => sys::switch_log_level_t_SWITCH_LOG_DEBUG7,
56 Self::Debug8 => sys::switch_log_level_t_SWITCH_LOG_DEBUG8,
57 Self::Debug9 => sys::switch_log_level_t_SWITCH_LOG_DEBUG9,
58 Self::Debug10 => sys::switch_log_level_t_SWITCH_LOG_DEBUG10,
59 Self::Invalid => sys::switch_log_level_t_SWITCH_LOG_INVALID,
60 Self::Uninit => sys::switch_log_level_t_SWITCH_LOG_UNINIT,
61 }
62 }
63}
64
65#[inline]
66pub fn log(module: &str, level: LogLevel, message: impl fmt::Display) {
67 log_at(level.as_raw(), module, message);
68}
69
70pub fn log_console(module: &str, message: impl fmt::Display) {
71 log(module, LogLevel::Console, message);
72}
73
74pub fn log_alert(module: &str, message: impl fmt::Display) {
75 log(module, LogLevel::Alert, message);
76}
77
78pub fn log_critical(module: &str, message: impl fmt::Display) {
79 log(module, LogLevel::Critical, message);
80}
81
82pub fn log_error(module: &str, message: impl fmt::Display) {
83 log(module, LogLevel::Error, message);
84}
85
86pub fn log_warning(module: &str, message: impl fmt::Display) {
87 log(module, LogLevel::Warning, message);
88}
89
90pub fn log_notice(module: &str, message: impl fmt::Display) {
91 log(module, LogLevel::Notice, message);
92}
93
94pub fn log_info(module: &str, message: impl fmt::Display) {
95 log(module, LogLevel::Info, message);
96}
97
98pub fn log_debug(module: &str, message: impl fmt::Display) {
99 log(module, LogLevel::Debug, message);
100}
101
102pub fn log_debug1(module: &str, message: impl fmt::Display) {
103 log(module, LogLevel::Debug1, message);
104}
105
106pub fn log_debug2(module: &str, message: impl fmt::Display) {
107 log(module, LogLevel::Debug2, message);
108}
109
110pub fn log_debug3(module: &str, message: impl fmt::Display) {
111 log(module, LogLevel::Debug3, message);
112}
113
114pub fn log_debug4(module: &str, message: impl fmt::Display) {
115 log(module, LogLevel::Debug4, message);
116}
117
118pub fn log_debug5(module: &str, message: impl fmt::Display) {
119 log(module, LogLevel::Debug5, message);
120}
121
122pub fn log_debug6(module: &str, message: impl fmt::Display) {
123 log(module, LogLevel::Debug6, message);
124}
125
126pub fn log_debug7(module: &str, message: impl fmt::Display) {
127 log(module, LogLevel::Debug7, message);
128}
129
130pub fn log_debug8(module: &str, message: impl fmt::Display) {
131 log(module, LogLevel::Debug8, message);
132}
133
134pub fn log_debug9(module: &str, message: impl fmt::Display) {
135 log(module, LogLevel::Debug9, message);
136}
137
138pub fn log_debug10(module: &str, message: impl fmt::Display) {
139 log(module, LogLevel::Debug10, message);
140}
141
142pub fn log_example(module: &str, message: impl fmt::Display) {
143 log_info(module, message);
144}
145
146pub fn log_example_error(module: &str, message: impl fmt::Display) {
147 log_error(module, message);
148}
149
150fn log_at(level: sys::switch_log_level_t, module: &str, message: impl fmt::Display) {
151 let text = format!("[fswtch:{module}] {message}");
152 let text = text.replace('\0', "\\0");
153 let Ok(text) = CString::new(text) else {
154 return;
155 };
156
157 unsafe { log_printf(level, text.as_ptr()) };
159}
160
161unsafe fn log_printf(level: sys::switch_log_level_t, text: *const std::ffi::c_char) {
166 let log = sys::switch_log_printf;
167 let channel = sys::switch_text_channel_t_SWITCH_CHANNEL_ID_LOG;
168 call_ffi!(log(
169 channel,
170 c"fswtch-rs".as_ptr(),
171 c"log".as_ptr(),
172 line!() as _,
173 std::ptr::null(),
174 level,
175 c"%s\n".as_ptr(),
176 text,
177 ));
178}