From 53eff4fbe61cb9fa3bcb3e3753375f75d230ea0c Mon Sep 17 00:00:00 2001 From: Ivan Smirnov Date: Sun, 18 Nov 2018 17:46:01 +0000 Subject: [PATCH] Goodbye trait-based inheritance, hello Deref --- hdf5-rs/src/container.rs | 33 ++++++++++++++++---------- hdf5-rs/src/dataset.rs | 30 +++--------------------- hdf5-rs/src/datatype.rs | 39 +++++++++---------------------- hdf5-rs/src/file.rs | 40 +++++++------------------------- hdf5-rs/src/group.rs | 29 +++-------------------- hdf5-rs/src/handle.rs | 50 ++++++++++++++++++++++------------------ hdf5-rs/src/lib.rs | 2 +- hdf5-rs/src/location.rs | 29 +++++++++++++++-------- hdf5-rs/src/macros.rs | 47 +++++++++++++++++++++++++++++++++++++ hdf5-rs/src/object.rs | 37 +++++++++++------------------ hdf5-rs/src/plist.rs | 23 +----------------- hdf5-rs/src/space.rs | 33 +++++++------------------- 12 files changed, 165 insertions(+), 227 deletions(-) diff --git a/hdf5-rs/src/container.rs b/hdf5-rs/src/container.rs index ff55f228f..020442920 100644 --- a/hdf5-rs/src/container.rs +++ b/hdf5-rs/src/container.rs @@ -3,6 +3,7 @@ use std::default::Default; use libhdf5_sys::{ h5d::H5Dopen2, h5g::{H5G_info_t, H5Gcreate2, H5Gget_info, H5Gopen2}, + h5i::{H5I_FILE, H5I_GROUP}, h5l::{H5Lcreate_hard, H5Lcreate_soft, H5Ldelete, H5Lmove, H5L_SAME_LOC}, h5p::{H5Pcreate, H5Pset_create_intermediate_group}, }; @@ -22,20 +23,24 @@ fn make_lcpl() -> Result { }) } +define_object_type!(Container: Location, "container", |id_type| id_type == H5I_FILE + || id_type == H5I_GROUP); + /// A trait for HDF5 objects that can contain other objects (file, group). -pub trait Container: Location { +impl Container { /// Returns the number of objects in the container (or 0 if the container is invalid). - fn len(&self) -> u64 { + pub fn len(&self) -> u64 { group_info(self.id()).map(|info| info.nlinks).unwrap_or(0) } /// Returns true if the container has no linked objects (or if the container is invalid). - fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.len() == 0 } /// Create a new group in a file or group. - fn create_group(&self, name: &str) -> Result { + pub fn create_group(&self, name: &str) -> Result { + // TODO: &mut self? h5lock!({ let lcpl = make_lcpl()?; let name = to_cstring(name)?; @@ -50,13 +55,14 @@ pub trait Container: Location { } /// Opens an existing group in a file or group. - fn group(&self, name: &str) -> Result { + pub fn group(&self, name: &str) -> Result { let name = to_cstring(name)?; Group::from_id(h5try!(H5Gopen2(self.id(), name.as_ptr(), H5P_DEFAULT))) } /// Creates a soft link. Note: `src` and `dst` are relative to the current object. - fn link_soft(&self, src: &str, dst: &str) -> Result<()> { + pub fn link_soft(&self, src: &str, dst: &str) -> Result<()> { + // TODO: &mut self? h5lock!({ let lcpl = make_lcpl()?; let src = to_cstring(src)?; @@ -67,7 +73,8 @@ pub trait Container: Location { } /// Creates a hard link. Note: `src` and `dst` are relative to the current object. - fn link_hard(&self, src: &str, dst: &str) -> Result<()> { + pub fn link_hard(&self, src: &str, dst: &str) -> Result<()> { + // TODO: &mut self? let src = to_cstring(src)?; let dst = to_cstring(dst)?; h5call!(H5Lcreate_hard( @@ -82,7 +89,8 @@ pub trait Container: Location { } /// Relinks an object. Note: `name` and `path` are relative to the current object. - fn relink(&self, name: &str, path: &str) -> Result<()> { + pub fn relink(&self, name: &str, path: &str) -> Result<()> { + // TODO: &mut self? let name = to_cstring(name)?; let path = to_cstring(path)?; h5call!(H5Lmove( @@ -97,18 +105,19 @@ pub trait Container: Location { } /// Removes a link to an object from this file or group. - fn unlink(&self, name: &str) -> Result<()> { + pub fn unlink(&self, name: &str) -> Result<()> { + // TODO: &mut self? let name = to_cstring(name)?; h5call!(H5Ldelete(self.id(), name.as_ptr(), H5P_DEFAULT)).and(Ok(())) } /// Instantiates a new dataset builder. - fn new_dataset(&self) -> DatasetBuilder { - DatasetBuilder::::new::(self) + pub fn new_dataset(&self) -> DatasetBuilder { + DatasetBuilder::::new(self) } /// Opens an existing dataset in the file or group. - fn dataset(&self, name: &str) -> Result { + pub fn dataset(&self, name: &str) -> Result { let name = to_cstring(name)?; Dataset::from_id(h5try!(H5Dopen2(self.id(), name.as_ptr(), H5P_DEFAULT))) } diff --git a/hdf5-rs/src/dataset.rs b/hdf5-rs/src/dataset.rs index dd34e789e..5a2733fc4 100644 --- a/hdf5-rs/src/dataset.rs +++ b/hdf5-rs/src/dataset.rs @@ -8,6 +8,7 @@ use libhdf5_sys::{ H5D_fill_value_t, H5D_layout_t, H5Dcreate2, H5Dcreate_anon, H5Dget_create_plist, H5Dget_offset, H5Dget_space, H5Dget_storage_size, H5Dget_type, H5D_FILL_TIME_ALLOC, }, + h5i::H5I_DATASET, h5p::{ H5Pcreate, H5Pfill_value_defined, H5Pget_chunk, H5Pget_fill_value, H5Pget_layout, H5Pget_obj_track_times, H5Pset_chunk, H5Pset_create_intermediate_group, H5Pset_fill_time, @@ -27,32 +28,7 @@ pub enum Chunk { } /// Represents the HDF5 dataset object. -pub struct Dataset { - handle: Handle, -} - -#[doc(hidden)] -impl ID for Dataset { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for Dataset { - fn from_id(id: hid_t) -> Result { - h5lock!({ - match get_id_type(id) { - H5I_DATASET => Ok(Dataset { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid dataset id: {}", id))), - } - }) - } -} - -impl Object for Dataset {} - -impl Location for Dataset {} +define_object_type!(Dataset: Location, "dataset", |id_type| id_type == H5I_DATASET); impl Dataset { /// Returns the shape of the dataset. @@ -201,7 +177,7 @@ pub struct DatasetBuilder { impl DatasetBuilder { /// Create a new dataset builder and bind it to the parent container. - pub fn new(parent: &C) -> DatasetBuilder { + pub fn new(parent: &Container) -> DatasetBuilder { h5lock!({ // Store the reference to the parent handle and try to increase its reference count. let handle = Handle::new(parent.id()); diff --git a/hdf5-rs/src/datatype.rs b/hdf5-rs/src/datatype.rs index 9845b2aae..84fd49674 100644 --- a/hdf5-rs/src/datatype.rs +++ b/hdf5-rs/src/datatype.rs @@ -3,12 +3,15 @@ use std::fmt; use hdf5_types::{ CompoundField, CompoundType, EnumMember, EnumType, FloatSize, H5Type, IntSize, TypeDescriptor, }; -use libhdf5_sys::h5t::{ - H5T_class_t, H5T_cset_t, H5T_str_t, H5Tarray_create2, H5Tcopy, H5Tcreate, H5Tenum_create, - H5Tenum_insert, H5Tequal, H5Tget_array_dims2, H5Tget_array_ndims, H5Tget_class, H5Tget_cset, - H5Tget_member_name, H5Tget_member_offset, H5Tget_member_type, H5Tget_member_value, - H5Tget_nmembers, H5Tget_sign, H5Tget_size, H5Tget_super, H5Tinsert, H5Tis_variable_str, - H5Tset_cset, H5Tset_size, H5Tset_strpad, H5Tvlen_create, H5T_VARIABLE, +use libhdf5_sys::{ + h5i::H5I_DATATYPE, + h5t::{ + H5T_class_t, H5T_cset_t, H5T_str_t, H5Tarray_create2, H5Tcopy, H5Tcreate, H5Tenum_create, + H5Tenum_insert, H5Tequal, H5Tget_array_dims2, H5Tget_array_ndims, H5Tget_class, + H5Tget_cset, H5Tget_member_name, H5Tget_member_offset, H5Tget_member_type, + H5Tget_member_value, H5Tget_nmembers, H5Tget_sign, H5Tget_size, H5Tget_super, H5Tinsert, + H5Tis_variable_str, H5Tset_cset, H5Tset_size, H5Tset_strpad, H5Tvlen_create, H5T_VARIABLE, + }, }; use crate::globals::{H5T_C_S1, H5T_NATIVE_INT8}; @@ -40,28 +43,8 @@ macro_rules! be_le { }; } -pub struct Datatype { - handle: Handle, -} - -#[doc(hidden)] -impl ID for Datatype { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for Datatype { - fn from_id(id: hid_t) -> Result { - h5lock!(match get_id_type(id) { - H5I_DATATYPE => Ok(Datatype { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid datatype id: {}", id))), - }) - } -} - -impl Object for Datatype {} +/// Represents the HDF5 datatype object. +define_object_type!(Datatype: Object, "datatype", |id_type| id_type == H5I_DATATYPE); impl fmt::Debug for Datatype { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/hdf5-rs/src/file.rs b/hdf5-rs/src/file.rs index 1170b9b71..bf8fae586 100644 --- a/hdf5-rs/src/file.rs +++ b/hdf5-rs/src/file.rs @@ -9,6 +9,7 @@ use libhdf5_sys::{ H5F_ACC_RDWR, H5F_ACC_TRUNC, H5F_OBJ_ALL, H5F_OBJ_FILE, H5F_SCOPE_LOCAL, }, h5fd::{H5Pset_fapl_core, H5Pset_fapl_sec2, H5Pset_fapl_stdio}, + h5i::H5I_FILE, h5p::{H5Pcreate, H5Pget_userblock, H5Pset_userblock}, }; @@ -16,34 +17,7 @@ use crate::globals::{H5P_FILE_ACCESS, H5P_FILE_CREATE}; use crate::internal_prelude::*; /// Represents the HDF5 file object. -pub struct File { - handle: Handle, -} - -#[doc(hidden)] -impl ID for File { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for File { - fn from_id(id: hid_t) -> Result { - h5lock!({ - match get_id_type(id) { - H5I_FILE => Ok(File { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid file id: {}", id))), - } - }) - } -} - -impl Object for File {} - -impl Location for File {} - -impl Container for File {} +define_object_type!(File: Container, "file", |id_type| id_type == H5I_FILE); impl File { /// Create a new file object. @@ -110,6 +84,7 @@ impl File { /// Flushes the file to the storage medium. pub fn flush(&self) -> Result<()> { + // TODO: &mut self? h5call!(H5Fflush(self.id(), H5F_SCOPE_LOCAL)).and(Ok(())) } @@ -133,21 +108,22 @@ impl File { /// Closes the file and invalidates all open handles for contained objects. pub fn close(&self) { + // TODO: self instead of &self? h5lock!({ let file_ids = self.get_obj_ids(H5F_OBJ_FILE); let object_ids = self.get_obj_ids(H5F_OBJ_ALL & !H5F_OBJ_FILE); for file_id in &file_ids { - let handle = Handle::from_id(*file_id); + let handle = Handle::new(*file_id); if let Ok(handle) = handle { - while handle.is_valid() { + while handle.is_valid_user_id() { handle.decref(); } } } for object_id in &object_ids { - let handle = Handle::from_id(*object_id); + let handle = Handle::new(*object_id); if let Ok(handle) = handle { - while handle.is_valid() { + while handle.is_valid_user_id() { handle.decref(); } } diff --git a/hdf5-rs/src/group.rs b/hdf5-rs/src/group.rs index 975709cf8..a4e847201 100644 --- a/hdf5-rs/src/group.rs +++ b/hdf5-rs/src/group.rs @@ -1,11 +1,11 @@ use std::fmt; +use libhdf5_sys::h5i::H5I_type_t; + use crate::internal_prelude::*; /// Represents the HDF5 group object. -pub struct Group { - handle: Handle, -} +define_object_type!(Group: Container, "group", |id_type| id_type == H5I_type_t::H5I_GROUP); impl fmt::Debug for Group { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -28,29 +28,6 @@ impl fmt::Display for Group { } } -#[doc(hidden)] -impl ID for Group { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for Group { - fn from_id(id: hid_t) -> Result { - match get_id_type(id) { - H5I_GROUP => Ok(Group { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid group id: {}", id))), - } - } -} - -impl Object for Group {} - -impl Location for Group {} - -impl Container for Group {} - #[cfg(test)] pub mod tests { use crate::internal_prelude::*; diff --git a/hdf5-rs/src/handle.rs b/hdf5-rs/src/handle.rs index 9a494688d..4b656280a 100644 --- a/hdf5-rs/src/handle.rs +++ b/hdf5-rs/src/handle.rs @@ -30,12 +30,22 @@ pub fn is_valid_user_id(id: hid_t) -> bool { h5lock!({ H5Iis_valid(id) == 1 }) } -pub trait ID: Sized { - fn id(&self) -> hid_t; -} - pub trait FromID: Sized { - fn from_id(id: hid_t) -> Result; + fn object_type_name() -> &'static str; + + fn is_valid_id_type(id_type: H5I_type_t) -> bool; + + fn from_handle(handle: Handle) -> Self; + + fn from_id(id: hid_t) -> Result { + h5lock!({ + if Self::is_valid_id_type(get_id_type(id)) { + Ok(Self::from_handle(Handle::new(id)?)) + } else { + Err(From::from(format!("Invalid {} id: {}", Self::object_type_name(), id))) + } + }) + } } struct Registry { @@ -102,22 +112,32 @@ impl Handle { pub fn decref(&self) { h5lock!({ - if is_valid_user_id(self.id()) { + if self.is_valid_id() { H5Idec_ref(self.id()); } // must invalidate all linked IDs because the library reuses them internally - if !is_valid_user_id(self.id()) && !is_valid_id(self.id()) { + if !self.is_valid_user_id() && !self.is_valid_id() { self.invalidate(); } }) } + + /// Returns `true` if the object has a valid unlocked identifier (`false` for pre-defined + /// locked identifiers like property list classes). + pub fn is_valid_user_id(&self) -> bool { + is_valid_user_id(self.id()) + } + + pub fn is_valid_id(&self) -> bool { + is_valid_id(self.id()) + } } impl Clone for Handle { fn clone(&self) -> Handle { h5lock!({ self.incref(); - Handle::from_id(self.id()).unwrap_or_else(|_| Handle::invalid()) + Handle::new(self.id()).unwrap_or_else(|_| Handle::invalid()) }) } } @@ -127,17 +147,3 @@ impl Drop for Handle { h5lock!(self.decref()); } } - -impl ID for Handle { - fn id(&self) -> hid_t { - self.id() - } -} - -impl FromID for Handle { - fn from_id(id: hid_t) -> Result { - Handle::new(id) - } -} - -impl Object for Handle {} diff --git a/hdf5-rs/src/lib.rs b/hdf5-rs/src/lib.rs index 47b49debd..cb9fba170 100644 --- a/hdf5-rs/src/lib.rs +++ b/hdf5-rs/src/lib.rs @@ -72,7 +72,7 @@ mod internal_prelude { error::silence_errors, export::*, file::FileBuilder, - handle::{get_id_type, FromID, Handle, ID}, + handle::{get_id_type, FromID, Handle}, plist::PropertyList, types::H5Type, util::{get_h5_str, string_from_cstr, to_cstring}, diff --git a/hdf5-rs/src/location.rs b/hdf5-rs/src/location.rs index f9a0eff49..f491a9260 100644 --- a/hdf5-rs/src/location.rs +++ b/hdf5-rs/src/location.rs @@ -2,47 +2,58 @@ use std::ptr; use libhdf5_sys::{ h5f::H5Fget_name, - h5i::{H5Iget_file_id, H5Iget_name}, + h5i::{H5I_type_t, H5Iget_file_id, H5Iget_name}, h5o::{H5Oget_comment, H5Oset_comment}, }; use crate::internal_prelude::*; -/// A trait for HDF5 objects that can have a named location (file, group, dataset). -pub trait Location: Object { +/// Named location (file, group, dataset, named datatype). +define_object_type!(Location: Object, "location", |id_type| [ + H5I_type_t::H5I_FILE, + H5I_type_t::H5I_GROUP, + H5I_type_t::H5I_DATATYPE, + H5I_type_t::H5I_DATASET, + H5I_type_t::H5I_ATTR, +] +.contains(&id_type)); + +impl Location { /// Returns the name of the object within the file, or empty string if the object doesn't /// have a name (e.g., an anonymous dataset). - fn name(&self) -> String { + pub fn name(&self) -> String { // TODO: should this return Result or an empty string if it fails? h5lock!(get_h5_str(|m, s| H5Iget_name(self.id(), m, s)).unwrap_or_else(|_| "".to_string())) } /// Returns the name of the file containing the named object (or the file itself). - fn filename(&self) -> String { + pub fn filename(&self) -> String { // TODO: should this return Result or an empty string if it fails? h5lock!(get_h5_str(|m, s| H5Fget_name(self.id(), m, s)).unwrap_or_else(|_| "".to_string())) } /// Returns a handle to the file containing the named object (or the file itself). - fn file(&self) -> Result { + pub fn file(&self) -> Result { File::from_id(h5try!(H5Iget_file_id(self.id()))) } /// Returns the commment attached to the named object, if any. - fn comment(&self) -> Option { + pub fn comment(&self) -> Option { // TODO: should this return Result> or fail silently? let comment = h5lock!(get_h5_str(|m, s| H5Oget_comment(self.id(), m, s)).ok()); comment.and_then(|c| if c.is_empty() { None } else { Some(c) }) } /// Set or the commment attached to the named object. - fn set_comment(&self, comment: &str) -> Result<()> { + pub fn set_comment(&self, comment: &str) -> Result<()> { + // TODO: &mut self? let comment = to_cstring(comment)?; h5call!(H5Oset_comment(self.id(), comment.as_ptr())).and(Ok(())) } /// Clear the commment attached to the named object. - fn clear_comment(&self) -> Result<()> { + pub fn clear_comment(&self) -> Result<()> { + // TODO: &mut self? h5call!(H5Oset_comment(self.id(), ptr::null_mut())).and(Ok(())) } } diff --git a/hdf5-rs/src/macros.rs b/hdf5-rs/src/macros.rs index d049fdfd5..9d3fa120b 100644 --- a/hdf5-rs/src/macros.rs +++ b/hdf5-rs/src/macros.rs @@ -110,3 +110,50 @@ macro_rules! h5try { } }; } + +macro_rules! define_object_type { + ($ty:ident, $name:expr, $check_id_type:expr) => { + #[allow(dead_code)] + pub struct $ty { + handle: crate::handle::Handle, + } + + impl crate::handle::FromID for $ty { + #[inline] + fn object_type_name() -> &'static str { + $name + } + + #[inline] + #[cfg_attr(feature = "cargo-clippy", allow(clippy::redundant_closure_call))] + fn is_valid_id_type(id: ::libhdf5_sys::h5i::H5I_type_t) -> bool { + ($check_id_type)(id) + } + + #[inline] + fn from_handle(handle: crate::handle::Handle) -> Self { + Self { handle } + } + } + }; + + ($ty:ident: $parent:ty, $name:expr, $check_id_type:expr) => { + define_object_type!($ty, $name, $check_id_type); + + impl ::std::ops::Deref for $ty { + type Target = $parent; + + #[inline] + fn deref(&self) -> &$parent { + unsafe { &*(self as *const $ty as *const $parent) } + } + } + + impl ::std::ops::DerefMut for $ty { + #[inline] + fn deref_mut(&mut self) -> &mut $parent { + unsafe { &mut *(self as *mut $ty as *mut $parent) } + } + } + }; +} diff --git a/hdf5-rs/src/object.rs b/hdf5-rs/src/object.rs index 28b60a6d9..6631f84f4 100644 --- a/hdf5-rs/src/object.rs +++ b/hdf5-rs/src/object.rs @@ -3,10 +3,16 @@ use libhdf5_sys::h5i::{H5I_type_t, H5Iget_ref}; use crate::handle::is_valid_user_id; use crate::internal_prelude::*; -/// A trait for all HDF5 objects that can be referenced through an identifier. -pub trait Object: ID { +/// Any HDF5 object that can be referenced through an identifier. +define_object_type!(Object, "object", |_| true); + +impl Object { + pub(crate) fn id(&self) -> hid_t { + self.handle.id() + } + /// Returns reference count if the handle is valid and 0 otherwise. - fn refcount(&self) -> u32 { + pub fn refcount(&self) -> u32 { if self.is_valid() { h5call!(H5Iget_ref(self.id())).unwrap_or(0) as _ } else { @@ -16,27 +22,25 @@ pub trait Object: ID { /// Returns `true` if the object has a valid unlocked identifier (`false` for pre-defined /// locked identifiers like property list classes). - fn is_valid(&self) -> bool { + pub fn is_valid(&self) -> bool { is_valid_user_id(self.id()) } /// Returns type of the object. - fn id_type(&self) -> H5I_type_t { + pub fn id_type(&self) -> H5I_type_t { get_id_type(self.id()) } } #[cfg(test)] pub mod tests { - use libhdf5_sys::h5p::H5Pcreate; + use libhdf5_sys::{h5i::H5I_type_t, h5p::H5Pcreate}; use crate::globals::H5P_FILE_ACCESS; use crate::handle::{is_valid_id, is_valid_user_id}; use crate::internal_prelude::*; - struct TestObject { - handle: Handle, - } + define_object_type!(TestObject: Object, "test object", |_| true); impl TestObject { fn incref(&self) { @@ -48,20 +52,6 @@ pub mod tests { } } - impl ID for TestObject { - fn id(&self) -> hid_t { - self.handle.id() - } - } - - impl FromID for TestObject { - fn from_id(id: hid_t) -> Result { - Ok(TestObject { handle: Handle::new(id)? }) - } - } - - impl Object for TestObject {} - #[test] pub fn test_not_a_valid_user_id() { assert_err!(TestObject::from_id(H5I_INVALID_HID), "Invalid handle id"); @@ -75,6 +65,7 @@ pub mod tests { assert!(obj.is_valid()); assert!(is_valid_id(obj.id())); assert!(is_valid_user_id(obj.id())); + assert_eq!(obj.id_type(), H5I_type_t::H5I_GENPROP_LST); assert_eq!(obj.refcount(), 1); obj.incref(); diff --git a/hdf5-rs/src/plist.rs b/hdf5-rs/src/plist.rs index b4e67d7ca..b95a8cdc1 100644 --- a/hdf5-rs/src/plist.rs +++ b/hdf5-rs/src/plist.rs @@ -7,9 +7,7 @@ use libhdf5_sys::{ use crate::internal_prelude::*; -pub struct PropertyList { - handle: Handle, -} +define_object_type!(PropertyList: Object, "property list", |id_type| id_type == H5I_GENPROP_LST); impl fmt::Debug for PropertyList { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -27,25 +25,6 @@ impl fmt::Display for PropertyList { } } -#[doc(hidden)] -impl ID for PropertyList { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for PropertyList { - fn from_id(id: hid_t) -> Result { - match get_id_type(id) { - H5I_GENPROP_LST => Ok(PropertyList { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid property list id: {}", id))), - } - } -} - -impl Object for PropertyList {} - impl Clone for PropertyList { fn clone(&self) -> PropertyList { let id = h5call!(H5Pcopy(self.id())).unwrap_or(H5I_INVALID_HID); diff --git a/hdf5-rs/src/space.rs b/hdf5-rs/src/space.rs index ae1492830..5f5bb7175 100644 --- a/hdf5-rs/src/space.rs +++ b/hdf5-rs/src/space.rs @@ -2,8 +2,12 @@ use std::fmt; use std::ptr; use std::slice; -use libhdf5_sys::h5s::{ - H5Scopy, H5Screate_simple, H5Sget_simple_extent_dims, H5Sget_simple_extent_ndims, H5S_UNLIMITED, +use libhdf5_sys::{ + h5i::H5I_DATASPACE, + h5s::{ + H5Scopy, H5Screate_simple, H5Sget_simple_extent_dims, H5Sget_simple_extent_ndims, + H5S_UNLIMITED, + }, }; use crate::internal_prelude::*; @@ -87,10 +91,8 @@ impl Dimension for Ix { } } -/// Represents the HDF5 dataspace object. -pub struct Dataspace { - handle: Handle, -} +/// Represents the HDF5 datatype object. +define_object_type!(Dataspace: Object, "dataspace", |id_type| id_type == H5I_DATASPACE); impl Dataspace { pub fn new(d: D, resizable: bool) -> Result { @@ -147,25 +149,6 @@ impl Dimension for Dataspace { } } -#[doc(hidden)] -impl ID for Dataspace { - fn id(&self) -> hid_t { - self.handle.id() - } -} - -#[doc(hidden)] -impl FromID for Dataspace { - fn from_id(id: hid_t) -> Result { - match get_id_type(id) { - H5I_DATASPACE => Ok(Dataspace { handle: Handle::new(id)? }), - _ => Err(From::from(format!("Invalid dataspace id: {}", id))), - } - } -} - -impl Object for Dataspace {} - impl Clone for Dataspace { fn clone(&self) -> Dataspace { let id = h5call!(H5Scopy(self.id())).unwrap_or(H5I_INVALID_HID);