use std::fmt::{self, Debug};
use std::ops::Deref;
use hdf5_sys::h5t::H5Tcommitted;
use crate::internal_prelude::*;
#[repr(transparent)]
pub struct CommittedDatatype(Handle);
impl ObjectClass for CommittedDatatype {
const NAME: &'static str = "committed datatype";
const VALID_TYPES: &'static [H5I_type_t] = &[H5I_DATATYPE];
fn from_handle(handle: Handle) -> Self {
Self(handle)
}
fn handle(&self) -> &Handle {
&self.0
}
fn validate(&self) -> Result<()> {
ensure!(
h5call!(H5Tcommitted(self.id())).unwrap_or(0) > 0,
"expected committed datatype, got a transient datatype"
);
Ok(())
}
fn short_repr(&self) -> Option<String> {
self.as_datatype().short_repr()
}
}
impl Debug for CommittedDatatype {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.debug_fmt(f)
}
}
impl Clone for CommittedDatatype {
fn clone(&self) -> Self {
unsafe { self.deref().clone().cast_unchecked() }
}
}
impl Deref for CommittedDatatype {
type Target = Location;
fn deref(&self) -> &Location {
unsafe { self.transmute() }
}
}
impl TryFrom<Datatype> for CommittedDatatype {
type Error = Error;
fn try_from(datatype: Datatype) -> Result<Self> {
let committed: Self = unsafe { datatype.cast_unchecked() };
committed.validate().map(|()| committed)
}
}
impl CommittedDatatype {
pub fn as_datatype(&self) -> &Datatype {
unsafe { self.transmute() }
}
}
#[cfg(test)]
pub mod tests {
use crate::internal_prelude::*;
#[test]
pub fn test_committed_datatype_conversion() {
with_tmp_file(|file| {
let transient = Datatype::from_type::<i32>().unwrap();
assert_err!(CommittedDatatype::try_from(transient), "expected committed datatype");
let dtype = Datatype::from_type::<i32>().unwrap();
file.commit_datatype("mytype", &dtype).unwrap();
let committed = CommittedDatatype::try_from(dtype).unwrap();
assert_eq!(format!("{committed:?}"), "<HDF5 committed datatype: int32>");
assert_eq!(committed.name(), "/mytype");
assert!(committed.as_datatype().is_committed());
})
}
}