#[derive(Debug, Clone)]
pub struct FieldDescriptor {
pub name: String,
pub offset: usize,
pub size: usize,
pub type_class: TypeClass,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TypeClass {
Integer { signed: bool },
Float,
Compound,
}
pub unsafe trait H5Type: Copy + 'static {
fn type_size() -> usize;
fn compound_fields() -> Option<Vec<FieldDescriptor>> {
None
}
fn enum_members() -> Option<Vec<(String, i64)>> {
None
}
}
macro_rules! impl_h5type {
($($t:ty),*) => {
$(
unsafe impl H5Type for $t {
fn type_size() -> usize { std::mem::size_of::<$t>() }
}
)*
};
}
impl_h5type!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
pub fn bytes_to_slice<T: H5Type>(bytes: &[u8]) -> crate::Result<&[T]> {
let elem_size = T::type_size();
if elem_size == 0 {
return Err(crate::Error::Other("zero-size type".into()));
}
if bytes.len() % elem_size != 0 {
return Err(crate::Error::InvalidFormat(format!(
"byte count {} is not a multiple of element size {}",
bytes.len(),
elem_size
)));
}
let align = std::mem::align_of::<T>();
if (bytes.as_ptr() as usize) % align != 0 {
return Err(crate::Error::Other(
"buffer alignment insufficient for type; use read() instead of read_scalar()".into(),
));
}
let count = bytes.len() / elem_size;
let ptr = bytes.as_ptr() as *const T;
Ok(unsafe { std::slice::from_raw_parts(ptr, count) })
}
pub fn bytes_to_vec<T: H5Type>(bytes: Vec<u8>) -> crate::Result<Vec<T>> {
let elem_size = T::type_size();
if elem_size == 0 {
return Err(crate::Error::Other("zero-size type".into()));
}
if bytes.len() % elem_size != 0 {
return Err(crate::Error::InvalidFormat(format!(
"byte count {} is not a multiple of element size {}",
bytes.len(),
elem_size
)));
}
let count = bytes.len() / elem_size;
let align = std::mem::align_of::<T>();
if (bytes.as_ptr() as usize) % align == 0 {
let mut bytes = std::mem::ManuallyDrop::new(bytes);
let ptr = bytes.as_mut_ptr() as *mut T;
let cap = bytes.capacity() / elem_size;
Ok(unsafe { Vec::from_raw_parts(ptr, count, cap) })
} else {
let mut result = Vec::<T>::with_capacity(count);
unsafe {
std::ptr::copy_nonoverlapping(
bytes.as_ptr(),
result.as_mut_ptr() as *mut u8,
bytes.len(),
);
result.set_len(count);
}
Ok(result)
}
}