graphannis_capi/
logging.rs

1use super::cerror::{Error, ErrorList};
2use super::cstr;
3use simplelog::{Config, LevelFilter, WriteLogger};
4use std::fs::File;
5
6/// Different levels of logging. Higher levels activate logging of events of lower levels as well.
7#[repr(C)]
8pub enum LogLevel {
9    Off,
10    Error,
11    Warn,
12    Info,
13    Debug,
14    Trace,
15}
16
17impl From<LogLevel> for simplelog::LevelFilter {
18    fn from(level: LogLevel) -> simplelog::LevelFilter {
19        match level {
20            LogLevel::Off => simplelog::LevelFilter::Off,
21            LogLevel::Error => simplelog::LevelFilter::Error,
22            LogLevel::Warn => simplelog::LevelFilter::Warn,
23            LogLevel::Info => simplelog::LevelFilter::Info,
24            LogLevel::Debug => simplelog::LevelFilter::Debug,
25            LogLevel::Trace => simplelog::LevelFilter::Trace,
26        }
27    }
28}
29
30/// Initialize the logging of this library.
31///
32/// - `logfile` - The file that is used to output the log messages.
33/// - `level` - Minimum level to output.
34/// - `err` - Pointer to a list of errors. If any error occured, this list will be non-empty.
35///
36/// # Safety
37///
38/// This functions dereferences the `err` pointer and is therefore unsafe.
39#[unsafe(no_mangle)]
40pub unsafe extern "C" fn annis_init_logging(
41    logfile: *const libc::c_char,
42    level: LogLevel,
43    err: *mut *mut ErrorList,
44) {
45    if !logfile.is_null() {
46        let logfile: &str = &cstr(logfile);
47
48        unsafe {
49            match File::create(logfile) {
50                Ok(f) => {
51                    if let Err(e) =
52                        WriteLogger::init(LevelFilter::from(level), Config::default(), f)
53                    {
54                        // File was created, but logger was not.
55                        if !err.is_null() {
56                            *err = Box::into_raw(Box::new(vec![Error::from(e)]));
57                        }
58                    }
59                }
60                Err(e) => {
61                    if !err.is_null() {
62                        *err = Box::into_raw(Box::new(vec![Error::from(e)]));
63                    }
64                }
65            };
66        }
67    }
68}