1use std::ffi::{c_char, c_void, CStr};
2
3pub type LoggingCallback = Option<unsafe extern "C" fn(*mut c_void, *const c_char)>;
4pub type LoggingClosure = Box<dyn Fn(&str) + Send>;
5
6pub(crate) const RESULTS_STREAM_IDX: usize = 0;
7pub(crate) const WARNING_STREAM_IDX: usize = 1;
8pub(crate) const ERROR_STREAM_IDX: usize = 2;
9pub(crate) const LOG_STREAM_IDX: usize = 3;
10
11pub(crate) const DEFAULT_LOGGING_CLOSURE: Option<(LoggingClosure, LoggingCallback)> = None;
12
13#[derive(Clone, Copy, Debug)]
14pub enum StreamType {
15 Results,
16 Warning,
17 Error,
18 Log,
19}
20
21impl StreamType {
22 pub(crate) fn as_index(&self) -> usize {
23 match self {
24 Self::Results => RESULTS_STREAM_IDX,
25 Self::Warning => WARNING_STREAM_IDX,
26 Self::Error => ERROR_STREAM_IDX,
27 Self::Log => LOG_STREAM_IDX,
28 }
29 }
30}
31
32pub(crate) fn get_trampoline<F: Fn(&str)>() -> LoggingCallback {
33 Some(trampoline::<F>)
34}
35
36unsafe extern "C" fn trampoline<F>(user_data: *mut c_void, msg: *const c_char)
37where
38 F: Fn(&str),
39{
40 let logging_closure = &mut *(user_data as *mut F);
41 let msg = CStr::from_ptr(msg);
42 for line in msg.to_string_lossy().lines() {
43 logging_closure(line);
44 }
45}