Skip to main content

coreshift_core/log/
mod.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/
4
5//! Backend-agnostic logging facade.
6
7mod android;
8mod null;
9mod stderr;
10
11/// Log severity levels.
12#[repr(i32)]
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum LogLevel {
15    Verbose = 2,
16    Debug = 3,
17    Info = 4,
18    Warn = 5,
19    Error = 6,
20    Fatal = 7,
21}
22
23/// Legacy alias for [`LogLevel`].
24pub type LogPriority = LogLevel;
25
26/// Available logging backends.
27#[repr(u8)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum LogBackend {
30    /// Android system log (liblog).
31    Android = 0,
32    /// Standard error.
33    Stderr = 1,
34    /// Discard all messages.
35    Null = 2,
36}
37
38/// A handle for writing messages to a specific log backend.
39///
40/// Core follows a "no global mutable state" architecture. Callers that require
41/// a non-default logging backend must create a [`Logger`] instance and use
42/// it directly.
43///
44/// By default, macros like [`alog_info!`] use a platform-appropriate default
45/// logger ([`LogBackend::Android`] on Android, [`LogBackend::Stderr`] otherwise).
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub struct Logger {
48    backend: LogBackend,
49}
50
51impl Default for Logger {
52    fn default() -> Self {
53        #[cfg(target_os = "android")]
54        {
55            Self::new(LogBackend::Android)
56        }
57        #[cfg(not(target_os = "android"))]
58        {
59            Self::new(LogBackend::Stderr)
60        }
61    }
62}
63
64impl Logger {
65    /// Create a new logger with the specified backend.
66    pub fn new(backend: LogBackend) -> Self {
67        Self { backend }
68    }
69
70    /// Write a message to the logger's active backend.
71    pub fn log(&self, level: LogLevel, tag: &str, msg: &str) {
72        match self.backend {
73            LogBackend::Android => android::log(level, tag, msg),
74            LogBackend::Stderr => stderr::log(level, tag, msg),
75            LogBackend::Null => null::log(level, tag, msg),
76        }
77    }
78}
79
80/// Write a message using the platform default logger.
81///
82/// This maintains compatibility with legacy callers and existing macros.
83/// It uses direct compile-time dispatch to the appropriate platform backend.
84pub fn log(level: LogLevel, tag: &str, msg: &str) {
85    #[cfg(target_os = "android")]
86    {
87        android::log(level, tag, msg);
88    }
89    #[cfg(not(target_os = "android"))]
90    {
91        stderr::log(level, tag, msg);
92    }
93}
94
95/// Legacy alias for [`log`].
96pub fn log_write(level: LogLevel, tag: &str, msg: &str) {
97    log(level, tag, msg);
98}
99
100#[macro_export]
101macro_rules! alog_verbose {
102    ($tag:expr, $($arg:tt)*) => {
103        $crate::log::log($crate::log::LogLevel::Verbose, $tag, &format!($($arg)*))
104    };
105    ($tag:expr) => {
106        $crate::log::log($crate::log::LogLevel::Verbose, $tag, "")
107    };
108}
109
110#[macro_export]
111macro_rules! alog_debug {
112    ($tag:expr, $($arg:tt)*) => {
113        $crate::log::log($crate::log::LogLevel::Debug, $tag, &format!($($arg)*))
114    };
115    ($tag:expr) => {
116        $crate::log::log($crate::log::LogLevel::Debug, $tag, "")
117    };
118}
119
120#[macro_export]
121macro_rules! alog_info {
122    ($tag:expr, $($arg:tt)*) => {
123        $crate::log::log($crate::log::LogLevel::Info, $tag, &format!($($arg)*))
124    };
125    ($tag:expr) => {
126        $crate::log::log($crate::log::LogLevel::Info, $tag, "")
127    };
128}
129
130#[macro_export]
131macro_rules! alog_warn {
132    ($tag:expr, $($arg:tt)*) => {
133        $crate::log::log($crate::log::LogLevel::Warn, $tag, &format!($($arg)*))
134    };
135    ($tag:expr) => {
136        $crate::log::log($crate::log::LogLevel::Warn, $tag, "")
137    };
138}
139
140#[macro_export]
141macro_rules! alog_error {
142    ($tag:expr, $($arg:tt)*) => {
143        $crate::log::log($crate::log::LogLevel::Error, $tag, &format!($($arg)*))
144    };
145    ($tag:expr) => {
146        $crate::log::log($crate::log::LogLevel::Error, $tag, "")
147    };
148}
149
150#[macro_export]
151macro_rules! alog_fatal {
152    ($tag:expr, $($arg:tt)*) => {
153        $crate::log::log($crate::log::LogLevel::Fatal, $tag, &format!($($arg)*))
154    };
155    ($tag:expr) => {
156        $crate::log::log($crate::log::LogLevel::Fatal, $tag, "")
157    };
158}
159
160#[macro_export]
161macro_rules! log_verbose {
162    ($tag:expr, $($arg:tt)*) => {
163        $crate::log::log($crate::log::LogLevel::Verbose, $tag, &format!($($arg)*))
164    };
165    ($tag:expr) => {
166        $crate::log::log($crate::log::LogLevel::Verbose, $tag, "")
167    };
168}
169
170#[macro_export]
171macro_rules! log_debug {
172    ($tag:expr, $($arg:tt)*) => {
173        $crate::log::log($crate::log::LogLevel::Debug, $tag, &format!($($arg)*))
174    };
175    ($tag:expr) => {
176        $crate::log::log($crate::log::LogLevel::Debug, $tag, "")
177    };
178}
179
180#[macro_export]
181macro_rules! log_info {
182    ($tag:expr, $($arg:tt)*) => {
183        $crate::log::log($crate::log::LogLevel::Info, $tag, &format!($($arg)*))
184    };
185    ($tag:expr) => {
186        $crate::log::log($crate::log::LogLevel::Info, $tag, "")
187    };
188}
189
190#[macro_export]
191macro_rules! log_warn {
192    ($tag:expr, $($arg:tt)*) => {
193        $crate::log::log($crate::log::LogLevel::Warn, $tag, &format!($($arg)*))
194    };
195    ($tag:expr) => {
196        $crate::log::log($crate::log::LogLevel::Warn, $tag, "")
197    };
198}
199
200#[macro_export]
201macro_rules! log_error {
202    ($tag:expr, $($arg:tt)*) => {
203        $crate::log::log($crate::log::LogLevel::Error, $tag, &format!($($arg)*))
204    };
205    ($tag:expr) => {
206        $crate::log::log($crate::log::LogLevel::Error, $tag, "")
207    };
208}
209
210#[macro_export]
211macro_rules! log_fatal {
212    ($tag:expr, $($arg:tt)*) => {
213        $crate::log::log($crate::log::LogLevel::Fatal, $tag, &format!($($arg)*))
214    };
215    ($tag:expr) => {
216        $crate::log::log($crate::log::LogLevel::Fatal, $tag, "")
217    };
218}