use crate::error::{ParameterRegisterError, StorageError};
use crate::hal_parameter::ParameterPermissions;
use linuxcnc_hal_sys::hal_malloc;
use std::{convert::TryInto, mem};
fn is_aligned_to<T: ?Sized>(ptr: *const T, align: usize) -> bool {
assert!(align.is_power_of_two());
let ptr = ptr as *const u8 as usize;
let mask = align.wrapping_sub(1);
(ptr & mask) == 0
}
pub trait HalParameter: Sized {
type Storage: std::fmt::Debug;
fn allocate_storage() -> Result<*mut Self::Storage, StorageError> {
let storage_ptr = unsafe {
let size = mem::size_of::<Self::Storage>();
let ptr_size = mem::size_of::<Self::Storage>().try_into().unwrap();
debug!("Allocating {} bytes (ptr size {})", size, ptr_size);
let ptr = hal_malloc(ptr_size) as *mut Self::Storage;
if ptr.is_null() {
return Err(StorageError::Null);
}
if !is_aligned_to(ptr, size) {
return Err(StorageError::Alignment);
}
debug!("Allocated value {:?} at {:?}", *ptr, ptr);
ptr
};
Ok(storage_ptr)
}
fn name(&self) -> &str;
fn storage_mut(&self) -> Result<&mut Self::Storage, StorageError>;
fn storage(&self) -> Result<&Self::Storage, StorageError>;
fn register(
full_pin_name: &str,
component_id: i32,
direction: ParameterPermissions,
) -> Result<Self, ParameterRegisterError>;
}