Skip to content

Commit be72139

Browse files
authored
Merge pull request #36 from WiresmithTech/feature/refs2
Object Reference Types
2 parents dd8e048 + c461ec1 commit be72139

File tree

15 files changed

+563
-2
lines changed

15 files changed

+563
-2
lines changed

hdf5-src/ext/hdf5

Submodule hdf5 updated 4731 files

hdf5-types/build.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,15 @@ fn main() {
44
if std::env::var_os("DEP_HDF5_MSVC_DLL_INDIRECTION").is_some() {
55
println!("cargo::rustc-cfg=windows_dll");
66
}
7+
8+
// Declare the known HDF5 versions we might feature flag on
9+
// in this crate.
10+
println!("cargo::rustc-check-cfg=cfg(feature, values(\"1.12.0\"))");
11+
12+
for (key, _) in std::env::vars() {
13+
if key.starts_with("DEP_HDF5_VERSION_") {
14+
let version = key.trim_start_matches("DEP_HDF5_VERSION_").replace("_", ".");
15+
println!("cargo::rustc-cfg=feature=\"{version}\"");
16+
}
17+
}
718
}

hdf5-types/src/dyn_value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ impl<'a> DynValue<'a> {
703703
FixedUnicode(_) => DynFixedString::new(buf, true).into(),
704704
VarLenAscii => DynVarLenString::new(buf, false).into(),
705705
VarLenUnicode => DynVarLenString::new(buf, true).into(),
706+
Reference(_x) => todo!(),
706707
}
707708
}
708709
}

hdf5-types/src/h5type.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::os::raw::c_void;
44
use std::ptr;
55

66
use crate::array::VarLenArray;
7+
use crate::references::Reference;
78
use crate::string::{FixedAscii, FixedUnicode, VarLenAscii, VarLenUnicode};
89

910
#[allow(non_camel_case_types)]
@@ -160,6 +161,7 @@ pub enum TypeDescriptor {
160161
VarLenArray(Box<Self>),
161162
VarLenAscii,
162163
VarLenUnicode,
164+
Reference(Reference),
163165
}
164166

165167
impl Display for TypeDescriptor {
@@ -186,6 +188,10 @@ impl Display for TypeDescriptor {
186188
TypeDescriptor::VarLenArray(ref tp) => write!(f, "[{}] (var len)", tp),
187189
TypeDescriptor::VarLenAscii => write!(f, "string (var len)"),
188190
TypeDescriptor::VarLenUnicode => write!(f, "unicode (var len)"),
191+
TypeDescriptor::Reference(Reference::Object) => write!(f, "reference (object)"),
192+
TypeDescriptor::Reference(Reference::Region) => write!(f, "reference (region)"),
193+
#[cfg(feature = "1.12.0")]
194+
TypeDescriptor::Reference(Reference::Std) => write!(f, "reference"),
189195
}
190196
}
191197
}
@@ -202,6 +208,7 @@ impl TypeDescriptor {
202208
Self::FixedAscii(len) | Self::FixedUnicode(len) => len,
203209
Self::VarLenArray(_) => mem::size_of::<hvl_t>(),
204210
Self::VarLenAscii | Self::VarLenUnicode => mem::size_of::<*const u8>(),
211+
Self::Reference(reftyp) => reftyp.size(),
205212
}
206213
}
207214

@@ -340,7 +347,7 @@ unsafe impl<T: H5Type, const N: usize> H5Type for [T; N] {
340347
}
341348
}
342349

343-
unsafe impl<T: Copy + H5Type> H5Type for VarLenArray<T> {
350+
unsafe impl<T: H5Type + Copy> H5Type for VarLenArray<T> {
344351
#[inline]
345352
fn type_descriptor() -> TypeDescriptor {
346353
TypeDescriptor::VarLenArray(Box::new(<T as H5Type>::type_descriptor()))

hdf5-types/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern crate quickcheck;
2020
mod array;
2121
pub mod dyn_value;
2222
mod h5type;
23+
pub mod references;
2324
mod string;
2425

2526
#[cfg(feature = "complex")]
@@ -30,6 +31,7 @@ pub use self::dyn_value::{DynValue, OwnedDynValue};
3031
pub use self::h5type::{
3132
CompoundField, CompoundType, EnumMember, EnumType, FloatSize, H5Type, IntSize, TypeDescriptor,
3233
};
34+
pub use self::references::Reference;
3335
pub use self::string::{FixedAscii, FixedUnicode, StringError, VarLenAscii, VarLenUnicode};
3436

3537
pub(crate) unsafe fn malloc(n: usize) -> *mut core::ffi::c_void {

hdf5-types/src/references.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! Types for references.
2+
3+
use std::mem;
4+
5+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6+
pub enum Reference {
7+
Object,
8+
Region,
9+
#[cfg(feature = "1.12.0")]
10+
Std,
11+
}
12+
13+
impl Reference {
14+
pub fn size(self) -> usize {
15+
match self {
16+
Self::Object => mem::size_of::<hdf5_sys::h5r::hobj_ref_t>(),
17+
Self::Region => mem::size_of::<hdf5_sys::h5r::hdset_reg_ref_t>(),
18+
#[cfg(feature = "1.12.0")]
19+
Self::Std => mem::size_of::<hdf5_sys::h5r::H5R_ref_t>(),
20+
}
21+
}
22+
}

hdf5/src/globals.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ link_hid!(H5T_STD_B64BE, h5t::H5T_STD_B64BE);
7777
link_hid!(H5T_STD_B64LE, h5t::H5T_STD_B64LE);
7878
link_hid!(H5T_STD_REF_OBJ, h5t::H5T_STD_REF_OBJ);
7979
link_hid!(H5T_STD_REF_DSETREG, h5t::H5T_STD_REF_DSETREG);
80+
#[cfg(feature = "1.12.0")]
81+
link_hid!(H5T_STD_REF, h5t::H5T_STD_REF);
8082
link_hid!(H5T_UNIX_D32BE, h5t::H5T_UNIX_D32BE);
8183
link_hid!(H5T_UNIX_D32LE, h5t::H5T_UNIX_D32LE);
8284
link_hid!(H5T_UNIX_D64BE, h5t::H5T_UNIX_D64BE);

hdf5/src/hl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod group;
1111
pub mod location;
1212
pub mod object;
1313
pub mod plist;
14+
pub mod references;
1415
pub mod selection;
1516

1617
pub use self::{

hdf5/src/hl/datatype.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,16 @@ impl Datatype {
410410
}
411411
TD::VarLenAscii => string_type(None, H5T_cset_t::H5T_CSET_ASCII),
412412
TD::VarLenUnicode => string_type(None, H5T_cset_t::H5T_CSET_UTF8),
413+
#[cfg(feature = "1.12.0")]
414+
TD::Reference(hdf5_types::Reference::Std) => {
415+
Ok(h5try!(H5Tcopy(*crate::globals::H5T_STD_REF)))
416+
}
417+
TD::Reference(hdf5_types::Reference::Object) => {
418+
Ok(h5try!(H5Tcopy(*crate::globals::H5T_STD_REF_OBJ)))
419+
}
420+
TD::Reference(hdf5_types::Reference::Region) => {
421+
Ok(h5try!(H5Tcopy(*crate::globals::H5T_STD_REF_DSETREG)))
422+
}
413423
}
414424
});
415425

hdf5/src/hl/location.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@ impl Location {
146146
pub fn open_by_token(&self, token: LocationToken) -> Result<Self> {
147147
H5O_open_by_token(self.id(), token)
148148
}
149+
150+
/// Generate a [object reference](ObjectReference) to the object for a reference storage.
151+
///
152+
/// This can be a group, dataset or datatype. Other objects are not supported.
153+
pub fn reference<R: ObjectReference>(&self, name: &str) -> Result<R> {
154+
R::create(self, name)
155+
}
156+
157+
/// Get a reference back to the referenced object from a standard reference.
158+
///
159+
/// This can be called against any object in the same file as the referenced object.
160+
pub fn dereference<R: ObjectReference>(&self, reference: &R) -> Result<ReferencedObject> {
161+
reference.dereference(self)
162+
}
149163
}
150164

151165
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

hdf5/src/hl/references.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use crate::internal_prelude::*;
2+
use crate::Location;
3+
4+
mod legacy;
5+
6+
#[cfg(feature = "1.12.1")]
7+
mod standard;
8+
9+
use hdf5_sys::h5o::H5O_type_t;
10+
use hdf5_sys::h5r::H5R_type_t;
11+
12+
pub use legacy::ObjectReference1;
13+
#[cfg(feature = "1.12.1")]
14+
pub use standard::ObjectReference2;
15+
16+
mod private {
17+
pub trait ObjectReferencePrivate {}
18+
}
19+
20+
/// The trait for all object references. This provides a common interface
21+
/// over the legacy and standard reference types.
22+
///
23+
/// This trait is sealed and cannot be implemented for types outside `hdf5::hl`.
24+
pub trait ObjectReference: Sized + H5Type + private::ObjectReferencePrivate {
25+
const REF_TYPE: H5R_type_t;
26+
fn ptr(&self) -> *const c_void;
27+
28+
/// Get the type of the object that the reference points in the same space as the provided location.
29+
fn get_object_type(&self, location: &Location) -> Result<H5O_type_t>;
30+
31+
/// Create a new reference in the same structure as the location provided.
32+
fn create(location: &Location, name: &str) -> Result<Self>;
33+
34+
/// Dereference the object reference in the space provided.
35+
fn dereference(&self, location: &Location) -> Result<ReferencedObject>;
36+
}
37+
/// The result of dereferencing an [object reference](ObjectReference).
38+
///
39+
/// Each variant represents a different type of object that can be referenced by a [ObjectReference].
40+
#[derive(Clone, Debug)]
41+
pub enum ReferencedObject {
42+
Group(Group),
43+
Dataset(Dataset),
44+
Datatype(Datatype),
45+
}
46+
47+
impl ReferencedObject {
48+
pub fn from_type_and_id(object_type: H5O_type_t, object_id: hid_t) -> Result<Self> {
49+
use hdf5_sys::h5o::H5O_type_t::*;
50+
let referenced_object = match object_type {
51+
H5O_TYPE_GROUP => ReferencedObject::Group(Group::from_id(object_id)?),
52+
H5O_TYPE_DATASET => ReferencedObject::Dataset(Dataset::from_id(object_id)?),
53+
H5O_TYPE_NAMED_DATATYPE => ReferencedObject::Datatype(Datatype::from_id(object_id)?),
54+
#[cfg(feature = "1.12.0")]
55+
H5O_TYPE_MAP => fail!("Can not create object from a map"),
56+
H5O_TYPE_UNKNOWN => fail!("Unknown datatype"),
57+
H5O_TYPE_NTYPES => fail!("hdf5 should not produce this type"),
58+
};
59+
Ok(referenced_object)
60+
}
61+
}

hdf5/src/hl/references/legacy.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//! The pre v1.12.0 reference types.
2+
3+
use crate::internal_prelude::*;
4+
5+
use hdf5_sys::{
6+
h5o::H5O_type_t,
7+
h5p::H5P_DEFAULT,
8+
h5r::{hobj_ref_t, H5Rcreate, H5Rdereference, H5Rget_obj_type2},
9+
};
10+
use hdf5_types::H5Type;
11+
12+
#[cfg(not(feature = "1.12.0"))]
13+
use hdf5_sys::h5r::H5R_OBJECT as H5R_OBJECT1;
14+
#[cfg(feature = "1.12.0")]
15+
use hdf5_sys::h5r::H5R_OBJECT1;
16+
17+
use super::{private::ObjectReferencePrivate, ObjectReference};
18+
use crate::Location;
19+
20+
#[repr(transparent)]
21+
#[derive(Debug, Copy, Clone)]
22+
pub struct ObjectReference1 {
23+
inner: hobj_ref_t,
24+
}
25+
26+
unsafe impl H5Type for ObjectReference1 {
27+
fn type_descriptor() -> hdf5_types::TypeDescriptor {
28+
hdf5_types::TypeDescriptor::Reference(hdf5_types::Reference::Object)
29+
}
30+
}
31+
32+
impl ObjectReferencePrivate for ObjectReference1 {}
33+
34+
impl ObjectReference for ObjectReference1 {
35+
const REF_TYPE: hdf5_sys::h5r::H5R_type_t = H5R_OBJECT1;
36+
37+
fn ptr(&self) -> *const c_void {
38+
let pointer = std::ptr::addr_of!(self.inner);
39+
pointer.cast()
40+
}
41+
42+
fn create(location: &Location, name: &str) -> Result<Self> {
43+
let mut ref_out: std::mem::MaybeUninit<hobj_ref_t> = std::mem::MaybeUninit::uninit();
44+
let name = to_cstring(name)?;
45+
h5call!(H5Rcreate(
46+
ref_out.as_mut_ptr().cast(),
47+
location.id(),
48+
name.as_ptr(),
49+
Self::REF_TYPE,
50+
-1
51+
))?;
52+
let reference = unsafe { ref_out.assume_init() };
53+
Ok(Self { inner: reference })
54+
}
55+
56+
fn get_object_type(&self, location: &Location) -> Result<hdf5_sys::h5o::H5O_type_t> {
57+
let mut objtype = std::mem::MaybeUninit::<H5O_type_t>::uninit();
58+
h5call!(H5Rget_obj_type2(location.id(), H5R_OBJECT1, self.ptr(), objtype.as_mut_ptr()))?;
59+
let objtype = unsafe { objtype.assume_init() };
60+
Ok(objtype)
61+
}
62+
63+
fn dereference(&self, location: &Location) -> Result<ReferencedObject> {
64+
let object_type = self.get_object_type(location)?;
65+
#[cfg(feature = "1.10.0")]
66+
let object_id =
67+
h5call!(H5Rdereference(location.id(), H5P_DEFAULT, H5R_OBJECT1, self.ptr()))?;
68+
#[cfg(not(feature = "1.10.0"))]
69+
let object_id = h5call!(H5Rdereference(location.id(), H5R_OBJECT1, self.ptr()))?;
70+
ReferencedObject::from_type_and_id(object_type, object_id)
71+
}
72+
}

0 commit comments

Comments
 (0)