#![doc(html_no_source)]
mod datapoint;
mod datapoint_value;
mod datapoint_value_quality;
pub mod device_config;
pub mod error;
mod log;
mod plugin_config;
mod plugin_info;
mod plugin_interface;
pub mod raw;
use std::ffi::c_char;
pub use log::GCLogLevel;
pub type GCDatapointID = gc_abi_sys::GCDatapointIdentifier;
pub use datapoint::GCDatapoint;
pub use datapoint_value::{GCDatapointValue, GCDatapointValueType};
pub use datapoint_value_quality::GCDatapointValueQuality;
pub use device_config::{DataBits, GCEthernetInterface, GCSerialInterface, Parity, StopBits};
pub use plugin_config::GCPluginConfig;
pub use plugin_info::GCPluginInfo;
pub use plugin_interface::GCCoreExportedFunctions;
pub use plugin_interface::GCPluginInterface;
use crate::error::GCPluginABIError;
pub unsafe trait GCAbiConversion: Sized {
type CType: Sized;
fn from_c(c_type: Self::CType) -> Self;
fn into_c(self) -> Self::CType;
fn ref_c(&self) -> &Self::CType {
unsafe { &*(self as *const Self as *const Self::CType) }
}
fn from_c_ref(c_type: &Self::CType) -> &Self {
unsafe { &*(c_type as *const Self::CType as *const Self) }
}
unsafe fn from_c_ptr(ptr: *const Self::CType) -> &'static Self {
unsafe {
let result = ptr as *const Self;
&*result
}
}
unsafe fn as_ptr(&self) -> *const Self::CType {
self as *const Self as *mut Self::CType
}
unsafe fn as_mut_ptr(&mut self) -> *mut Self::CType {
self as *mut Self as *mut Self::CType
}
}
fn copy_str_to_c<const N: usize>(str: &str) -> Result<[c_char; N], GCPluginABIError> {
let mut bytes = [0; N];
if str.len() >= N {
return Err(GCPluginABIError::StringTooLong(N, str.to_string()));
}
for (dst, src) in bytes.iter_mut().zip(str.bytes()) {
*dst = src as c_char;
}
Ok(bytes)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_copy_str_to_c_valid_string() {
let result = copy_str_to_c::<6>("hello");
assert!(result.is_ok(), "Short string should succeed");
let bytes = result.unwrap();
assert_eq!(bytes[0], b'h' as i8);
assert_eq!(bytes[1], b'e' as i8);
assert_eq!(bytes[2], b'l' as i8);
assert_eq!(bytes[3], b'l' as i8);
assert_eq!(bytes[4], b'o' as i8);
assert_eq!(bytes[5], 0); }
#[test]
fn test_copy_str_to_c_string_too_long() {
let result = copy_str_to_c::<5>("hello");
assert!(result.is_err(), "String of length N should fail");
match result {
Err(GCPluginABIError::StringTooLong(size, string)) => {
assert_eq!(size, 5);
assert_eq!(string, "hello");
}
_ => panic!("Expected StringTooLong error"),
}
}
#[test]
fn test_copy_str_to_c_string_much_longer() {
let result = copy_str_to_c::<5>("hello world");
assert!(result.is_err(), "String longer than N should fail");
match result {
Err(GCPluginABIError::StringTooLong(size, string)) => {
assert_eq!(size, 5);
assert_eq!(string, "hello world");
}
_ => panic!("Expected StringTooLong error"),
}
}
}