use rustecal_sys as sys;
use std::{
ffi::{CStr, CString},
ops::{Deref, DerefMut},
path::Path,
};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("Received null pointer from eCAL_Configuration_New")]
NullPointer,
#[error("Invalid file path: {0}")]
InvalidPath(String),
}
pub struct Configuration {
inner: *mut sys::eCAL_Configuration,
}
unsafe impl Send for Configuration {}
unsafe impl Sync for Configuration {}
impl Configuration {
pub fn new() -> Result<Self, ConfigError> {
let cfg = unsafe { sys::eCAL_Configuration_New() };
if cfg.is_null() {
return Err(ConfigError::NullPointer);
}
unsafe { sys::eCAL_Configuration_InitFromConfig(cfg) };
Ok(Configuration { inner: cfg })
}
pub fn from_file(path: &str) -> Result<Self, ConfigError> {
if !Path::new(path).exists() {
return Err(ConfigError::InvalidPath(path.to_string()));
}
let c_path = CString::new(path).map_err(|_| ConfigError::InvalidPath(path.to_string()))?;
let cfg = unsafe { sys::eCAL_Configuration_New() };
if cfg.is_null() {
return Err(ConfigError::NullPointer);
}
unsafe { sys::eCAL_Configuration_InitFromFile(cfg, c_path.as_ptr()) };
Ok(Configuration { inner: cfg })
}
pub fn file_path(&self) -> Option<String> {
unsafe {
let p = sys::eCAL_Configuration_GetConfigurationFilePath(self.inner);
if p.is_null() {
None
} else {
Some(CStr::from_ptr(p).to_string_lossy().into_owned())
}
}
}
pub(crate) fn as_ptr(&self) -> *const sys::eCAL_Configuration {
self.inner as *const _
}
}
impl Deref for Configuration {
type Target = sys::eCAL_Configuration;
fn deref(&self) -> &Self::Target {
unsafe { &*self.inner }
}
}
impl DerefMut for Configuration {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.inner }
}
}
impl Drop for Configuration {
fn drop(&mut self) {
unsafe { sys::eCAL_Configuration_Delete(self.inner) };
}
}