use super::*;
use crate::common::{
log,
log::{callback::LogCallback, tee_file::TeeFileConfiguration},
};
use std::time::*;
#[no_mangle]
pub extern "C" fn dqcs_scfg_new() -> dqcs_handle_t {
insert(SimulatorConfiguration::default())
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_push_plugin(scfg: dqcs_handle_t, xcfg: dqcs_handle_t) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
take!(xcfg as BoxedPluginConfiguration);
scfg.plugins.push(xcfg);
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_seed_set(scfg: dqcs_handle_t, seed: u64) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
scfg.seed.value = seed;
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_seed_get(scfg: dqcs_handle_t) -> u64 {
api_return(0, || {
resolve!(scfg as &SimulatorConfiguration);
Ok(scfg.seed.value)
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_stderr_verbosity_set(
scfg: dqcs_handle_t,
level: dqcs_loglevel_t,
) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
scfg.stderr_level = level.into_loglevel_filter()?;
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_stderr_verbosity_get(scfg: dqcs_handle_t) -> dqcs_loglevel_t {
api_return(dqcs_loglevel_t::DQCS_LOG_INVALID, || {
resolve!(scfg as &SimulatorConfiguration);
Ok(scfg.stderr_level.into())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_tee(
scfg: dqcs_handle_t,
verbosity: dqcs_loglevel_t,
filename: *const c_char,
) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
scfg.tee_files.push(TeeFileConfiguration::new(
verbosity.into_loglevel_filter()?,
receive_str(filename)?,
));
Ok(())
})
}
#[no_mangle]
#[allow(unused_must_use)]
pub extern "C" fn dqcs_scfg_log_callback(
scfg: dqcs_handle_t,
verbosity: dqcs_loglevel_t,
callback: Option<
extern "C" fn(
user_data: *mut c_void,
message: *const c_char,
logger: *const c_char,
level: dqcs_loglevel_t,
module: *const c_char,
file: *const c_char,
line: u32,
time_s: u64,
time_ns: u32,
pid: u32,
tid: u64,
),
>,
user_free: Option<extern "C" fn(user_data: *mut c_void)>,
user_data: *mut c_void,
) -> dqcs_return_t {
api_return_none(|| {
let data = CallbackUserData::new(user_free, user_data);
resolve!(scfg as &mut SimulatorConfiguration);
if let Some(callback) = callback {
scfg.log_callback = Some(LogCallback {
callback: Box::new(move |record: &log::LogRecord| {
|| -> Result<()> {
let ts_sec;
let ts_nano;
if let Ok(ts) = record.timestamp().duration_since(SystemTime::UNIX_EPOCH) {
ts_sec = ts.as_secs();
ts_nano = ts.subsec_nanos();
} else {
ts_sec = 0;
ts_nano = 0;
}
let payload = CString::new(record.payload())?;
let logger = CString::new(record.logger())?;
let module_path = record
.module_path()
.map(CString::new)
.map_or(Ok(None), |v| v.map(Some))?;
let file = record
.file()
.map(CString::new)
.map_or(Ok(None), |v| v.map(Some))?;
callback(
data.data(),
payload.as_ptr(),
logger.as_ptr(),
record.level().into(),
module_path.as_ref().map(|x| x.as_ptr()).unwrap_or(null()),
file.as_ref().map(|x| x.as_ptr()).unwrap_or(null()),
record.line().unwrap_or(0),
ts_sec,
ts_nano,
record.process(),
record.thread(),
);
Ok(())
}();
}),
filter: verbosity.into_loglevel_filter()?,
});
} else {
scfg.log_callback = None;
}
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_dqcsim_verbosity_set(
scfg: dqcs_handle_t,
level: dqcs_loglevel_t,
) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
scfg.dqcsim_level = level.into_loglevel_filter()?;
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_dqcsim_verbosity_get(scfg: dqcs_handle_t) -> dqcs_loglevel_t {
api_return(dqcs_loglevel_t::DQCS_LOG_INVALID, || {
resolve!(scfg as &SimulatorConfiguration);
Ok(scfg.dqcsim_level.into())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_repro_path_style_set(
scfg: dqcs_handle_t,
path_style: dqcs_path_style_t,
) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
let path_style: Option<ReproductionPathStyle> = path_style.into();
scfg.reproduction_path_style =
Some(path_style.ok_or_else(oe_inv_arg("invalid path style"))?);
Ok(())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_repro_path_style_get(scfg: dqcs_handle_t) -> dqcs_path_style_t {
api_return(dqcs_path_style_t::DQCS_PATH_STYLE_INVALID, || {
resolve!(scfg as &SimulatorConfiguration);
Ok(scfg
.reproduction_path_style
.ok_or_else(oe_inv_arg(
"the reproduction system is disabled for this configuration",
))?
.into())
})
}
#[no_mangle]
pub extern "C" fn dqcs_scfg_repro_disable(scfg: dqcs_handle_t) -> dqcs_return_t {
api_return_none(|| {
resolve!(scfg as &mut SimulatorConfiguration);
scfg.reproduction_path_style = None;
Ok(())
})
}