Skip to content

Commit 53eff4f

Browse files
committed
Goodbye trait-based inheritance, hello Deref
1 parent 02237ea commit 53eff4f

File tree

12 files changed

+165
-227
lines changed

12 files changed

+165
-227
lines changed

hdf5-rs/src/container.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::default::Default;
33
use libhdf5_sys::{
44
h5d::H5Dopen2,
55
h5g::{H5G_info_t, H5Gcreate2, H5Gget_info, H5Gopen2},
6+
h5i::{H5I_FILE, H5I_GROUP},
67
h5l::{H5Lcreate_hard, H5Lcreate_soft, H5Ldelete, H5Lmove, H5L_SAME_LOC},
78
h5p::{H5Pcreate, H5Pset_create_intermediate_group},
89
};
@@ -22,20 +23,24 @@ fn make_lcpl() -> Result<PropertyList> {
2223
})
2324
}
2425

26+
define_object_type!(Container: Location, "container", |id_type| id_type == H5I_FILE
27+
|| id_type == H5I_GROUP);
28+
2529
/// A trait for HDF5 objects that can contain other objects (file, group).
26-
pub trait Container: Location {
30+
impl Container {
2731
/// Returns the number of objects in the container (or 0 if the container is invalid).
28-
fn len(&self) -> u64 {
32+
pub fn len(&self) -> u64 {
2933
group_info(self.id()).map(|info| info.nlinks).unwrap_or(0)
3034
}
3135

3236
/// Returns true if the container has no linked objects (or if the container is invalid).
33-
fn is_empty(&self) -> bool {
37+
pub fn is_empty(&self) -> bool {
3438
self.len() == 0
3539
}
3640

3741
/// Create a new group in a file or group.
38-
fn create_group(&self, name: &str) -> Result<Group> {
42+
pub fn create_group(&self, name: &str) -> Result<Group> {
43+
// TODO: &mut self?
3944
h5lock!({
4045
let lcpl = make_lcpl()?;
4146
let name = to_cstring(name)?;
@@ -50,13 +55,14 @@ pub trait Container: Location {
5055
}
5156

5257
/// Opens an existing group in a file or group.
53-
fn group(&self, name: &str) -> Result<Group> {
58+
pub fn group(&self, name: &str) -> Result<Group> {
5459
let name = to_cstring(name)?;
5560
Group::from_id(h5try!(H5Gopen2(self.id(), name.as_ptr(), H5P_DEFAULT)))
5661
}
5762

5863
/// Creates a soft link. Note: `src` and `dst` are relative to the current object.
59-
fn link_soft(&self, src: &str, dst: &str) -> Result<()> {
64+
pub fn link_soft(&self, src: &str, dst: &str) -> Result<()> {
65+
// TODO: &mut self?
6066
h5lock!({
6167
let lcpl = make_lcpl()?;
6268
let src = to_cstring(src)?;
@@ -67,7 +73,8 @@ pub trait Container: Location {
6773
}
6874

6975
/// Creates a hard link. Note: `src` and `dst` are relative to the current object.
70-
fn link_hard(&self, src: &str, dst: &str) -> Result<()> {
76+
pub fn link_hard(&self, src: &str, dst: &str) -> Result<()> {
77+
// TODO: &mut self?
7178
let src = to_cstring(src)?;
7279
let dst = to_cstring(dst)?;
7380
h5call!(H5Lcreate_hard(
@@ -82,7 +89,8 @@ pub trait Container: Location {
8289
}
8390

8491
/// Relinks an object. Note: `name` and `path` are relative to the current object.
85-
fn relink(&self, name: &str, path: &str) -> Result<()> {
92+
pub fn relink(&self, name: &str, path: &str) -> Result<()> {
93+
// TODO: &mut self?
8694
let name = to_cstring(name)?;
8795
let path = to_cstring(path)?;
8896
h5call!(H5Lmove(
@@ -97,18 +105,19 @@ pub trait Container: Location {
97105
}
98106

99107
/// Removes a link to an object from this file or group.
100-
fn unlink(&self, name: &str) -> Result<()> {
108+
pub fn unlink(&self, name: &str) -> Result<()> {
109+
// TODO: &mut self?
101110
let name = to_cstring(name)?;
102111
h5call!(H5Ldelete(self.id(), name.as_ptr(), H5P_DEFAULT)).and(Ok(()))
103112
}
104113

105114
/// Instantiates a new dataset builder.
106-
fn new_dataset<T: H5Type>(&self) -> DatasetBuilder<T> {
107-
DatasetBuilder::<T>::new::<Self>(self)
115+
pub fn new_dataset<T: H5Type>(&self) -> DatasetBuilder<T> {
116+
DatasetBuilder::<T>::new(self)
108117
}
109118

110119
/// Opens an existing dataset in the file or group.
111-
fn dataset(&self, name: &str) -> Result<Dataset> {
120+
pub fn dataset(&self, name: &str) -> Result<Dataset> {
112121
let name = to_cstring(name)?;
113122
Dataset::from_id(h5try!(H5Dopen2(self.id(), name.as_ptr(), H5P_DEFAULT)))
114123
}

hdf5-rs/src/dataset.rs

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use libhdf5_sys::{
88
H5D_fill_value_t, H5D_layout_t, H5Dcreate2, H5Dcreate_anon, H5Dget_create_plist,
99
H5Dget_offset, H5Dget_space, H5Dget_storage_size, H5Dget_type, H5D_FILL_TIME_ALLOC,
1010
},
11+
h5i::H5I_DATASET,
1112
h5p::{
1213
H5Pcreate, H5Pfill_value_defined, H5Pget_chunk, H5Pget_fill_value, H5Pget_layout,
1314
H5Pget_obj_track_times, H5Pset_chunk, H5Pset_create_intermediate_group, H5Pset_fill_time,
@@ -27,32 +28,7 @@ pub enum Chunk {
2728
}
2829

2930
/// Represents the HDF5 dataset object.
30-
pub struct Dataset {
31-
handle: Handle,
32-
}
33-
34-
#[doc(hidden)]
35-
impl ID for Dataset {
36-
fn id(&self) -> hid_t {
37-
self.handle.id()
38-
}
39-
}
40-
41-
#[doc(hidden)]
42-
impl FromID for Dataset {
43-
fn from_id(id: hid_t) -> Result<Dataset> {
44-
h5lock!({
45-
match get_id_type(id) {
46-
H5I_DATASET => Ok(Dataset { handle: Handle::new(id)? }),
47-
_ => Err(From::from(format!("Invalid dataset id: {}", id))),
48-
}
49-
})
50-
}
51-
}
52-
53-
impl Object for Dataset {}
54-
55-
impl Location for Dataset {}
31+
define_object_type!(Dataset: Location, "dataset", |id_type| id_type == H5I_DATASET);
5632

5733
impl Dataset {
5834
/// Returns the shape of the dataset.
@@ -201,7 +177,7 @@ pub struct DatasetBuilder<T> {
201177

202178
impl<T: H5Type> DatasetBuilder<T> {
203179
/// Create a new dataset builder and bind it to the parent container.
204-
pub fn new<C: Container>(parent: &C) -> DatasetBuilder<T> {
180+
pub fn new(parent: &Container) -> DatasetBuilder<T> {
205181
h5lock!({
206182
// Store the reference to the parent handle and try to increase its reference count.
207183
let handle = Handle::new(parent.id());

hdf5-rs/src/datatype.rs

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ use std::fmt;
33
use hdf5_types::{
44
CompoundField, CompoundType, EnumMember, EnumType, FloatSize, H5Type, IntSize, TypeDescriptor,
55
};
6-
use libhdf5_sys::h5t::{
7-
H5T_class_t, H5T_cset_t, H5T_str_t, H5Tarray_create2, H5Tcopy, H5Tcreate, H5Tenum_create,
8-
H5Tenum_insert, H5Tequal, H5Tget_array_dims2, H5Tget_array_ndims, H5Tget_class, H5Tget_cset,
9-
H5Tget_member_name, H5Tget_member_offset, H5Tget_member_type, H5Tget_member_value,
10-
H5Tget_nmembers, H5Tget_sign, H5Tget_size, H5Tget_super, H5Tinsert, H5Tis_variable_str,
11-
H5Tset_cset, H5Tset_size, H5Tset_strpad, H5Tvlen_create, H5T_VARIABLE,
6+
use libhdf5_sys::{
7+
h5i::H5I_DATATYPE,
8+
h5t::{
9+
H5T_class_t, H5T_cset_t, H5T_str_t, H5Tarray_create2, H5Tcopy, H5Tcreate, H5Tenum_create,
10+
H5Tenum_insert, H5Tequal, H5Tget_array_dims2, H5Tget_array_ndims, H5Tget_class,
11+
H5Tget_cset, H5Tget_member_name, H5Tget_member_offset, H5Tget_member_type,
12+
H5Tget_member_value, H5Tget_nmembers, H5Tget_sign, H5Tget_size, H5Tget_super, H5Tinsert,
13+
H5Tis_variable_str, H5Tset_cset, H5Tset_size, H5Tset_strpad, H5Tvlen_create, H5T_VARIABLE,
14+
},
1215
};
1316

1417
use crate::globals::{H5T_C_S1, H5T_NATIVE_INT8};
@@ -40,28 +43,8 @@ macro_rules! be_le {
4043
};
4144
}
4245

43-
pub struct Datatype {
44-
handle: Handle,
45-
}
46-
47-
#[doc(hidden)]
48-
impl ID for Datatype {
49-
fn id(&self) -> hid_t {
50-
self.handle.id()
51-
}
52-
}
53-
54-
#[doc(hidden)]
55-
impl FromID for Datatype {
56-
fn from_id(id: hid_t) -> Result<Datatype> {
57-
h5lock!(match get_id_type(id) {
58-
H5I_DATATYPE => Ok(Datatype { handle: Handle::new(id)? }),
59-
_ => Err(From::from(format!("Invalid datatype id: {}", id))),
60-
})
61-
}
62-
}
63-
64-
impl Object for Datatype {}
46+
/// Represents the HDF5 datatype object.
47+
define_object_type!(Datatype: Object, "datatype", |id_type| id_type == H5I_DATATYPE);
6548

6649
impl fmt::Debug for Datatype {
6750
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

hdf5-rs/src/file.rs

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,15 @@ use libhdf5_sys::{
99
H5F_ACC_RDWR, H5F_ACC_TRUNC, H5F_OBJ_ALL, H5F_OBJ_FILE, H5F_SCOPE_LOCAL,
1010
},
1111
h5fd::{H5Pset_fapl_core, H5Pset_fapl_sec2, H5Pset_fapl_stdio},
12+
h5i::H5I_FILE,
1213
h5p::{H5Pcreate, H5Pget_userblock, H5Pset_userblock},
1314
};
1415

1516
use crate::globals::{H5P_FILE_ACCESS, H5P_FILE_CREATE};
1617
use crate::internal_prelude::*;
1718

1819
/// Represents the HDF5 file object.
19-
pub struct File {
20-
handle: Handle,
21-
}
22-
23-
#[doc(hidden)]
24-
impl ID for File {
25-
fn id(&self) -> hid_t {
26-
self.handle.id()
27-
}
28-
}
29-
30-
#[doc(hidden)]
31-
impl FromID for File {
32-
fn from_id(id: hid_t) -> Result<File> {
33-
h5lock!({
34-
match get_id_type(id) {
35-
H5I_FILE => Ok(File { handle: Handle::new(id)? }),
36-
_ => Err(From::from(format!("Invalid file id: {}", id))),
37-
}
38-
})
39-
}
40-
}
41-
42-
impl Object for File {}
43-
44-
impl Location for File {}
45-
46-
impl Container for File {}
20+
define_object_type!(File: Container, "file", |id_type| id_type == H5I_FILE);
4721

4822
impl File {
4923
/// Create a new file object.
@@ -110,6 +84,7 @@ impl File {
11084

11185
/// Flushes the file to the storage medium.
11286
pub fn flush(&self) -> Result<()> {
87+
// TODO: &mut self?
11388
h5call!(H5Fflush(self.id(), H5F_SCOPE_LOCAL)).and(Ok(()))
11489
}
11590

@@ -133,21 +108,22 @@ impl File {
133108

134109
/// Closes the file and invalidates all open handles for contained objects.
135110
pub fn close(&self) {
111+
// TODO: self instead of &self?
136112
h5lock!({
137113
let file_ids = self.get_obj_ids(H5F_OBJ_FILE);
138114
let object_ids = self.get_obj_ids(H5F_OBJ_ALL & !H5F_OBJ_FILE);
139115
for file_id in &file_ids {
140-
let handle = Handle::from_id(*file_id);
116+
let handle = Handle::new(*file_id);
141117
if let Ok(handle) = handle {
142-
while handle.is_valid() {
118+
while handle.is_valid_user_id() {
143119
handle.decref();
144120
}
145121
}
146122
}
147123
for object_id in &object_ids {
148-
let handle = Handle::from_id(*object_id);
124+
let handle = Handle::new(*object_id);
149125
if let Ok(handle) = handle {
150-
while handle.is_valid() {
126+
while handle.is_valid_user_id() {
151127
handle.decref();
152128
}
153129
}

hdf5-rs/src/group.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::fmt;
22

3+
use libhdf5_sys::h5i::H5I_type_t;
4+
35
use crate::internal_prelude::*;
46

57
/// Represents the HDF5 group object.
6-
pub struct Group {
7-
handle: Handle,
8-
}
8+
define_object_type!(Group: Container, "group", |id_type| id_type == H5I_type_t::H5I_GROUP);
99

1010
impl fmt::Debug for Group {
1111
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -28,29 +28,6 @@ impl fmt::Display for Group {
2828
}
2929
}
3030

31-
#[doc(hidden)]
32-
impl ID for Group {
33-
fn id(&self) -> hid_t {
34-
self.handle.id()
35-
}
36-
}
37-
38-
#[doc(hidden)]
39-
impl FromID for Group {
40-
fn from_id(id: hid_t) -> Result<Group> {
41-
match get_id_type(id) {
42-
H5I_GROUP => Ok(Group { handle: Handle::new(id)? }),
43-
_ => Err(From::from(format!("Invalid group id: {}", id))),
44-
}
45-
}
46-
}
47-
48-
impl Object for Group {}
49-
50-
impl Location for Group {}
51-
52-
impl Container for Group {}
53-
5431
#[cfg(test)]
5532
pub mod tests {
5633
use crate::internal_prelude::*;

0 commit comments

Comments
 (0)