cgl_rs/
logger.rs

1//! This module contains functions for logging.
2
3#![allow(non_camel_case_types)]
4use libc::{c_void, c_int, c_char, c_float, c_uchar};
5
6
7/// A struct representing a logger context (internal use only, c side)
8#[repr(C)]
9pub struct CGL_logger_context {
10    _private: c_void
11}
12
13extern {
14    fn CGL_console_set_color(color: c_uchar) -> c_void;
15
16    fn CGL_printf_red(log_format: *const c_char, ...) -> c_void;
17    fn CGL_printf_green(log_format: *const c_char, ...) -> c_void;
18    fn CGL_printf_gray(log_format: *const c_char, ...) -> c_void;
19    fn CGL_printf_blue(log_format: *const c_char, ...) -> c_void;
20    fn CGL_console_progress_bar(progress: c_float, width: c_int, prefix: *const c_char, suffix: *const c_char, complete_char: c_char, incomplete_char: c_char) -> c_void;
21
22    
23    fn CGL_logger_init(enable_console_logging: c_int) -> c_void;
24    fn CGL_logger_shutdown() -> c_void;
25    fn CGL_logger_get_context() -> *const CGL_logger_context;
26    fn CGL_logger_set_context(context: *const CGL_logger_context) -> c_void;
27    fn CGL_logger_attach_log_file(log_file_path: *const c_char) -> c_int;
28    fn CGL_logger_detach_log_file(log_file_path: *const c_char) -> c_int;
29    fn CGL_logger_flush() -> c_void;
30    fn CGL_logger_disable_console_logging() -> c_void;
31    fn CGL_logger_enable_console_logging() -> c_void;
32    fn CGL_logger_log(level: c_int, log_format: *const c_char, ...) -> c_void;    
33}
34
35
36/// An enum representing console colors.
37#[repr(C)] #[derive(Debug)]
38pub enum ConsoleColor {
39    Reset = 0,
40    Red   = 1,
41    Green = 2,
42    Gray  = 3,
43    Blue  = 4
44}
45
46/// An enum representing log levels.
47#[repr(C)] #[derive(Debug)]
48pub enum LogLevel {
49    Trace    = 0,
50    Info     = 1,
51    Warning  = 2,
52    Error    = 3,
53    Internal = 4
54}
55
56/// This is a temporary thing. This has already been implemented in the c side.
57/// Just the API is not public yet, so I'm using this for now.
58static mut AUTO_FLUSH_ON_LOG: bool = false;
59
60
61/// Initializes the logger.
62///
63/// NOTE: This is automatically called when you call cgl_rs::init().
64///       So it's not necessary to call this function manually, unless you are 
65///       doing something special, like creating a seperate context for some dll or stuff.
66/// 
67/// # Arguments
68///
69/// * `enable_console_logging` - A boolean value indicating whether to enable console logging or not.
70///
71/// # Example
72///
73/// ```
74/// cgl_rs::logger::init(true);
75/// // ...
76/// cgl_rs::logger::shutdown();
77/// ```
78pub fn init(enable_console_logging: bool) -> () {
79    unsafe {
80        CGL_logger_init(enable_console_logging as c_int);
81    }
82}
83
84/// Shuts down the logger.
85///
86/// NOTE: This is automatically called when you call cgl_rs::shutdown().
87/// 
88/// # Example
89///
90/// ```
91/// cgl_rs::logger::init(true);
92/// // ...
93/// cgl_rs::logger::shutdown();
94/// ```
95pub fn shutdown() -> () {
96    unsafe {
97        CGL_logger_shutdown();
98    }
99}
100
101/// Returns a pointer to the logger context.
102///
103/// # Safety
104///
105/// This function is unsafe because it returns a raw pointer to the logger context.
106///
107/// # Example
108///
109/// ```
110/// cgl_rs::logger::init(true);
111/// let context = cgl_rs::logger::get_context();
112/// // ...
113/// cgl_rs::logger::shutdown();
114/// ```
115pub fn get_context() -> *const CGL_logger_context {
116    unsafe {
117        CGL_logger_get_context()
118    }
119}
120
121/// Sets the logger context.
122/// 
123/// # Safety
124/// 
125/// This function is unsafe because it takes a raw pointer to the logger context.
126/// 
127/// # Arguments
128/// 
129/// * `context` - A raw pointer to the logger context.
130/// 
131/// # Example
132/// 
133/// ```
134/// cgl_rs::logger::init(true);
135/// let context = cgl_rs::logger::get_context();
136/// cgl_rs::logger::set_context(context);
137/// // ...
138/// cgl_rs::logger::shutdown();
139/// ```
140pub fn set_context(context: *const CGL_logger_context) -> () {
141    unsafe {
142        CGL_logger_set_context(context);
143    }
144}
145
146
147/// Attaches a log file to the logger. If the log file already exists, it will be appended to, otherwise it will be created.
148/// Also note that there is a limit of 32 (may change in the future) log files that can be attached at the same time.
149///
150/// # Arguments
151///
152/// * `log_file_path` - A string slice containing the path to the log file.
153///
154/// # Returns
155///
156/// A boolean value indicating whether the log file was successfully attached or not.
157///
158/// # Example
159///
160/// ```
161/// cgl_rs::logger::init(true);
162/// let log_file_path = "log.txt";
163/// let attached = cgl_rs::logger::attach_log_file(log_file_path);
164/// // ...
165/// cgl_rs::logger::shutdown();
166/// ```
167pub fn attach_log_file(log_file_path: &str) -> bool {
168    let c_log_file_path = std::ffi::CString::new(log_file_path).unwrap();
169    unsafe {
170        CGL_logger_attach_log_file(c_log_file_path.as_ptr()) != 0
171    }
172}
173
174/// Detaches a log file from the logger.
175///
176/// # Arguments
177///
178/// * `log_file_path` - A string slice containing the path to the log file.
179///
180/// # Returns
181///
182/// A boolean value indicating whether the log file was successfully detached or not.
183///
184/// # Example
185///
186/// ```
187/// cgl_rs::logger::init(true);
188/// let log_file_path = "log.txt";
189/// cgl_rs::logger::attach_log_file(log_file_path);
190/// let detached = cgl_rs::logger::detach_log_file(log_file_path);
191/// // ...
192/// cgl_rs::logger::shutdown();
193/// ```
194pub fn detach_log_file(log_file_path: &str) -> bool {
195    let c_log_file_path = std::ffi::CString::new(log_file_path).unwrap();
196    unsafe {
197        CGL_logger_detach_log_file(c_log_file_path.as_ptr()) != 0
198    }
199}
200
201/// Flushes all log messages to their respective log files.
202///
203/// # Example
204///
205/// ```
206/// cgl_rs::logger::init(true);
207/// // ...
208/// cgl_rs::logger::flush();
209/// // ...
210/// cgl_rs::logger::shutdown();
211/// ```
212pub fn flush() -> () {
213    unsafe {
214        CGL_logger_flush();
215    }
216}
217/// Disables console logging.
218///
219/// # Example
220///
221/// ```
222/// cgl_rs::logger::init(true);
223/// cgl_rs::logger::disable_console_logging();
224/// // ...
225/// cgl_rs::logger::shutdown();
226/// ```
227pub fn disable_console_logging() -> () {
228    unsafe {
229        CGL_logger_disable_console_logging();
230    }
231}
232
233/// Enables console logging.
234///
235/// # Example
236///
237/// ```
238/// cgl_rs::logger::init(true);
239/// cgl_rs::logger::enable_console_logging();
240/// // ...
241/// cgl_rs::logger::shutdown();
242/// ```
243pub fn enable_console_logging() -> () {
244    unsafe {
245        CGL_logger_enable_console_logging();
246    }
247}
248
249/// Sets whether the logger should automatically flush all log messages to their respective log files after each log message.
250///
251/// # Arguments
252///
253/// * `auto_flush_on_log` - A boolean value indicating whether the logger should automatically flush all log messages to their respective log files after each log message.
254///
255/// # Example
256///
257/// ```
258/// cgl_rs::logger::init(true);
259/// cgl_rs::logger::set_auto_flush_on_log(true);
260/// // ...
261/// cgl_rs::logger::shutdown();
262/// ```
263pub fn set_auto_flush_on_log(auto_flush_on_log: bool) -> () {
264    unsafe {
265        AUTO_FLUSH_ON_LOG = auto_flush_on_log;
266    }
267}
268
269
270/// Logs a message with the specified log level.
271///
272/// # Arguments
273///
274/// * `level` - The log level of the message.
275/// * `message` - A string slice containing the message to log.
276///
277/// # Example
278///
279/// ```
280/// cgl_rs::logger::init(true);
281/// cgl_rs::logger::log(cgl_rs::logger::LogLevel::Info, "This is an info message.");
282/// // ...
283/// cgl_rs::logger::shutdown();
284/// ```
285pub fn log(level: LogLevel, message: &str) -> () {
286    let c_message = std::ffi::CString::new(message).unwrap();
287    unsafe {
288        CGL_logger_log(level as c_int, c_message.as_ptr());
289
290        if AUTO_FLUSH_ON_LOG {
291            flush();
292        }
293    }
294}
295
296/// Logs a trace message with the specified format string and arguments.
297///
298/// # Arguments
299///
300/// * `format` - A format string for the trace message.
301/// * `args` - Arguments to be formatted into the trace message.
302///
303/// # Example
304///
305/// ```
306/// cgl_rs::logger::init(true);
307/// cgl_rs::log_trace!("This is a trace message with an argument: {}", 42);
308/// // ...
309/// cgl_rs::logger::shutdown();
310/// ```
311#[macro_export]
312macro_rules! log_trace {
313    ($($arg:tt)*) => ($crate::logger::log($crate::logger::LogLevel::Trace, &format!($($arg)*)));
314}
315
316/// Logs a warning message with the specified format string and arguments.
317///
318/// # Arguments
319///
320/// * `format` - A format string for the warning message.
321/// * `args` - Arguments to be formatted into the warning message.
322///
323/// # Example
324///
325/// ```
326/// cgl_rs::logger::init(true);
327/// cgl_rs::log_warning!("This is a warning message with an argument: {}", 42);
328/// // ...
329/// cgl_rs::logger::shutdown();
330/// ```
331#[macro_export]
332macro_rules! log_warning {
333    ($($arg:tt)*) => ($crate::logger::log($crate::logger::LogLevel::Warning, &format!($($arg)*)));
334}
335
336
337/// Logs an error message with the specified format string and arguments.
338/// 
339/// # Arguments
340/// 
341/// * `format` - A format string for the error message.
342/// * `args` - Arguments to be formatted into the error message.
343/// 
344/// # Example
345/// 
346/// ```
347/// cgl_rs::logger::init(true);
348/// cgl_rs::log_error!("This is an error message with an argument: {}", 42);
349/// // ...
350/// cgl_rs::logger::shutdown();
351/// ```
352#[macro_export]
353macro_rules! log_error {
354    ($($arg:tt)*) => ($crate::logger::log($crate::logger::LogLevel::Error, &format!($($arg)*)));
355}
356
357
358/// Logs an info message with the specified format string and arguments.
359///
360/// # Arguments
361///
362/// * `format` - A format string for the info message.
363/// * `args` - Arguments to be formatted into the info message.
364///
365/// # Example
366///
367/// ```
368/// cgl_rs::logger::init(true);
369/// cgl_rs::log_info!("This is an info message with an argument: {}", 42);
370/// // ...
371/// cgl_rs::logger::shutdown();
372/// ```
373#[macro_export]
374macro_rules! log_info {
375    ($($arg:tt)*) => ($crate::logger::log($crate::logger::LogLevel::Info, &format!($($arg)*)));
376}