rav2d 0.3.0

AV2 video decoder in Rust
Documentation
use std::fmt;

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

pub struct Logger {
    callback: Option<LogCallback>,
}

impl Logger {
    pub fn new() -> Self {
        Self { callback: None }
    }

    pub fn with_default() -> Self {
        Self {
            callback: Some(Box::new(|msg| {
                eprint!("{}", msg);
            })),
        }
    }

    pub fn with_callback(callback: LogCallback) -> Self {
        Self {
            callback: Some(callback),
        }
    }

    pub fn log(&self, args: fmt::Arguments<'_>) {
        if let Some(ref cb) = self.callback {
            cb(&fmt::format(args));
        }
    }
}

impl Default for Logger {
    fn default() -> Self {
        Self::with_default()
    }
}

impl fmt::Debug for Logger {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Logger")
            .field("has_callback", &self.callback.is_some())
            .finish()
    }
}

#[allow(unused_macros)]
macro_rules! rav2d_log {
    ($logger:expr, $($arg:tt)*) => {
        $logger.log(format_args!($($arg)*))
    };
}

#[allow(unused_imports)]
pub(crate) use rav2d_log;

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::{Arc, Mutex};

    #[test]
    fn test_default_logger_has_callback() {
        let logger = Logger::with_default();
        assert!(logger.callback.is_some());
    }

    #[test]
    fn test_new_logger_no_callback() {
        let logger = Logger::new();
        assert!(logger.callback.is_none());
    }

    #[test]
    fn test_log_no_callback_noop() {
        let logger = Logger::new();
        rav2d_log!(logger, "should not panic {}", 42);
    }

    #[test]
    fn test_log_with_callback() {
        let captured = Arc::new(Mutex::new(String::new()));
        let captured_clone = captured.clone();
        let logger = Logger::with_callback(Box::new(move |msg| {
            captured_clone.lock().unwrap().push_str(msg);
        }));
        rav2d_log!(logger, "hello {}", 42);
        assert_eq!(*captured.lock().unwrap(), "hello 42");
    }
}