use std::boxed::Box;
use std::convert::TryInto;
use std::ptr::null;
use libc::{c_char, c_int, c_uchar, size_t};
use crate::error_codes::*;
use crate::{
copy_string, PluginAPI, PluginData, PluginError, Val, ATTRIBUTE_PRE_INIT_FALSE,
ATTRIBUTE_PRE_INIT_TRUE, ERRORS,
};
pub type Phase = c_int;
pub extern "C" fn plugin_free(plugin_data: *mut PluginData) {
if plugin_data.is_null() {
return;
}
let plugin_data = plugin_data as *mut Box<PluginData>;
unsafe {
Box::from_raw(plugin_data);
}
}
pub unsafe extern "C" fn plugin_init<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *mut PluginData,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
};
let plugin_data = plugin_data as *mut T;
match (*plugin_data).init() {
Ok(_) => {
log::debug!("Successfully initialized plugin");
PLUGIN_OK
}
Err(e) => {
log::error!("Plugin failed to initialize: {}", e);
e.error_code()
}
}
}
pub extern "C" fn error_message_ns(error_code: c_int) -> *const c_uchar {
let error_code: size_t = match error_code.try_into() {
Ok(error_code) => error_code,
Err(_) => {
log::error!("Unrecognized error code provided");
return null();
}
};
ERRORS.get(error_code).map_or(null(), |e| e.as_ptr())
}
pub unsafe extern "C" fn attribute_count<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *const PluginData,
count: *mut size_t,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
};
let plugin_data = plugin_data as *const T;
*count = (*plugin_data).attribute_count();
PLUGIN_OK
}
pub unsafe extern "C" fn attribute_ids<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *const PluginData,
buffer: *mut size_t,
length: size_t,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
}
let plugin_data = plugin_data as *const T;
let ids = (*plugin_data).attribute_ids();
match copy_string(&ids, buffer, length) {
Ok(_) => PLUGIN_OK,
Err(_) => UNDEFINED_ERR,
}
}
pub unsafe extern "C" fn attribute_name<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *const PluginData,
id: size_t,
buffer: *mut c_uchar,
length: size_t,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
}
let plugin_data = plugin_data as *const T;
match (*plugin_data).attribute_name(id) {
Ok(name) => copy_string(name.to_bytes_with_nul(), buffer, length)
.map(|_| PLUGIN_OK)
.unwrap_or_else(|_| UNDEFINED_ERR),
Err(e) => e.error_code(),
}
}
pub unsafe extern "C" fn attribute_pre_init<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *const PluginData,
id: size_t,
pre_init: *mut c_char,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
}
if pre_init.is_null() {
log::error!("pre_init pointer is null");
return NULL_PTR_ERR;
}
let plugin_data = plugin_data as *const T;
match (*plugin_data).attribute_pre_init(id) {
Ok(pre_init_resp) => {
log::debug!(
"Response for pre-init status of attribute {}: {}",
id,
pre_init_resp
);
if pre_init_resp {
*pre_init = ATTRIBUTE_PRE_INIT_TRUE;
} else {
*pre_init = ATTRIBUTE_PRE_INIT_FALSE;
};
PLUGIN_OK
}
Err(e) => e.error_code(),
}
}
pub unsafe extern "C" fn attribute_value<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *const PluginData,
id: size_t,
value: *mut Val,
phase: Phase,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
}
let plugin_data = plugin_data as *const T;
match (*plugin_data).attribute_value(id, phase) {
Ok(new_value) => {
log::debug!(
"Response for the value of attribute {}: {:?}",
id,
new_value
);
*value = new_value
}
Err(e) => return e.error_code(),
};
PLUGIN_OK
}
pub unsafe extern "C" fn set_attribute_value<T: PluginAPI<E>, E: PluginError + 'static>(
plugin_data: *mut PluginData,
id: size_t,
value: *const Val,
phase: Phase,
) -> c_int {
if plugin_data.is_null() {
log::error!("plugin_data pointer is null");
return NULL_PTR_ERR;
}
if value.is_null() {
log::error!("value pointer is null");
return NULL_PTR_ERR;
}
let plugin_data = plugin_data as *mut T;
match (*plugin_data).attribute_set_value(id, &*value, phase) {
Ok(_) => {
log::debug!("Set attribute {} to {:?}", id, *value);
PLUGIN_OK
}
Err(e) => e.error_code(),
}
}