1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use lazy_static::lazy_static;
use std::ffi::CStr;
use std::sync::{Arc, Mutex};

/// Log level enumeration.
///
/// This enumeration represents the different log levels supported.
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(u32)]
pub enum LogLevel {
    /// No messages
    Disabled,
    /// Fatal level messages
    Fatal,
    /// Error level messages
    Error,
    /// Warn level messages
    Warn,
    /// Info level messages
    Info,
    /// Debug level messages
    Debug,
    /// Message level messages
    Message,
    /// Trace level messages
    Trace,
    /// All messages
    All,
    #[doc(hidden)]
    __Unknown(u32),
}

impl From<ffi::otc_log_level> for LogLevel {
    fn from(value: ffi::otc_log_level) -> Self {
        match value {
            ffi::otc_log_level_OTC_LOG_LEVEL_DISABLED => Self::Disabled,
            ffi::otc_log_level_OTC_LOG_LEVEL_FATAL => Self::Fatal,
            ffi::otc_log_level_OTC_LOG_LEVEL_ERROR => Self::Error,
            ffi::otc_log_level_OTC_LOG_LEVEL_WARN => Self::Warn,
            ffi::otc_log_level_OTC_LOG_LEVEL_INFO => Self::Info,
            ffi::otc_log_level_OTC_LOG_LEVEL_DEBUG => Self::Debug,
            ffi::otc_log_level_OTC_LOG_LEVEL_MSG => Self::Message,
            ffi::otc_log_level_OTC_LOG_LEVEL_TRACE => Self::Trace,
            ffi::otc_log_level_OTC_LOG_LEVEL_ALL => Self::All,
            _ => Self::__Unknown(value),
        }
    }
}

impl From<LogLevel> for ffi::otc_log_level {
    fn from(value: LogLevel) -> Self {
        match value {
            LogLevel::Disabled => ffi::otc_log_level_OTC_LOG_LEVEL_DISABLED,
            LogLevel::Fatal => ffi::otc_log_level_OTC_LOG_LEVEL_FATAL,
            LogLevel::Error => ffi::otc_log_level_OTC_LOG_LEVEL_ERROR,
            LogLevel::Warn => ffi::otc_log_level_OTC_LOG_LEVEL_WARN,
            LogLevel::Info => ffi::otc_log_level_OTC_LOG_LEVEL_INFO,
            LogLevel::Debug => ffi::otc_log_level_OTC_LOG_LEVEL_DEBUG,
            LogLevel::Message => ffi::otc_log_level_OTC_LOG_LEVEL_MSG,
            LogLevel::Trace => ffi::otc_log_level_OTC_LOG_LEVEL_TRACE,
            LogLevel::All => ffi::otc_log_level_OTC_LOG_LEVEL_ALL,
            LogLevel::__Unknown(_) => ffi::otc_log_level_OTC_LOG_LEVEL_DISABLED,
        }
    }
}

pub fn enable_log(level: LogLevel) {
    unsafe { ffi::otc_log_enable(level.into()) };
}

pub type LoggerCallback = Box<dyn Fn(&str) + Send + Sync + 'static>;

lazy_static! {
    pub static ref LOGGER_CALLBACKS: Arc<Mutex<Vec<LoggerCallback>>> = Default::default();
}

unsafe extern "C" fn ffi_logger_callback(message: *const ::std::os::raw::c_char) {
    let message: &CStr = CStr::from_ptr(message);
    if let Ok(message) = message.to_str() {
        if let Ok(callbacks) = LOGGER_CALLBACKS.try_lock() {
            for ref callback in callbacks.iter() {
                callback(message);
            }
        }
    }
}

pub fn logger_callback(callback: LoggerCallback) {
    LOGGER_CALLBACKS.lock().unwrap().push(callback);
    unsafe { ffi::otc_log_set_logger_callback(Some(ffi_logger_callback)) }
}