cplex-rs 0.1.10

Binding of IBM Cplex library
Documentation
use std::ffi::{c_char, c_void, CStr};

pub type LoggingCallback = Option<unsafe extern "C" fn(*mut c_void, *const c_char)>;
pub type LoggingClosure = Box<dyn Fn(&str) + Send>;

pub(crate) const RESULTS_STREAM_IDX: usize = 0;
pub(crate) const WARNING_STREAM_IDX: usize = 1;
pub(crate) const ERROR_STREAM_IDX: usize = 2;
pub(crate) const LOG_STREAM_IDX: usize = 3;

pub(crate) const DEFAULT_LOGGING_CLOSURE: Option<(LoggingClosure, LoggingCallback)> = None;

#[derive(Clone, Copy, Debug)]
pub enum StreamType {
    Results,
    Warning,
    Error,
    Log,
}

impl StreamType {
    pub(crate) fn as_index(&self) -> usize {
        match self {
            Self::Results => RESULTS_STREAM_IDX,
            Self::Warning => WARNING_STREAM_IDX,
            Self::Error => ERROR_STREAM_IDX,
            Self::Log => LOG_STREAM_IDX,
        }
    }
}

pub(crate) fn get_trampoline<F: Fn(&str)>() -> LoggingCallback {
    Some(trampoline::<F>)
}

unsafe extern "C" fn trampoline<F>(user_data: *mut c_void, msg: *const c_char)
where
    F: Fn(&str),
{
    let logging_closure = &mut *(user_data as *mut F);
    let msg = CStr::from_ptr(msg);
    for line in msg.to_string_lossy().lines() {
        logging_closure(line);
    }
}