Skip to content

Commit 40654f1

Browse files
authored
Merge pull request #93 from balintbalazs/external-links
Support for external links
2 parents 3d6fec7 + ec6aead commit 40654f1

File tree

2 files changed

+74
-14
lines changed

2 files changed

+74
-14
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
only supports the same operations as `hdf5` (e.g. one can not perform partial IO,
4949
but must read the entire attribute at once).
5050
- Added support in `hdf5-sys` for the new functions in `hdf5` `1.10.6` and `1.10.7`.
51+
- Added support for creating external links on a `Group` with `link_external`.
5152

5253
### Changed
5354

src/hl/group.rs

+73-14
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use hdf5_sys::{
77
h5d::H5Dopen2,
88
h5g::{H5G_info_t, H5Gcreate2, H5Gget_info, H5Gopen2},
99
h5l::{
10-
H5L_info_t, H5L_iterate_t, H5Lcreate_hard, H5Lcreate_soft, H5Ldelete, H5Lexists,
11-
H5Literate, H5Lmove, H5L_SAME_LOC,
10+
H5L_info_t, H5L_iterate_t, H5Lcreate_external, H5Lcreate_hard, H5Lcreate_soft, H5Ldelete,
11+
H5Lexists, H5Literate, H5Lmove, H5L_SAME_LOC,
1212
},
1313
h5p::{H5Pcreate, H5Pset_create_intermediate_group},
1414
};
@@ -102,34 +102,69 @@ impl Group {
102102
Self::from_id(h5try!(H5Gopen2(self.id(), name.as_ptr(), H5P_DEFAULT)))
103103
}
104104

105-
/// Creates a soft link. Note: `src` and `dst` are relative to the current object.
106-
pub fn link_soft(&self, src: &str, dst: &str) -> Result<()> {
105+
/// Creates a soft link.
106+
///
107+
/// A soft link does not require the linked object to exist.
108+
/// Note: `target` and `link_name` are relative to the current object.
109+
pub fn link_soft(&self, target: &str, link_name: &str) -> Result<()> {
107110
// TODO: &mut self?
108111
h5lock!({
109112
let lcpl = make_lcpl()?;
110-
let src = to_cstring(src)?;
111-
let dst = to_cstring(dst)?;
112-
h5call!(H5Lcreate_soft(src.as_ptr(), self.id(), dst.as_ptr(), lcpl.id(), H5P_DEFAULT))
113-
.and(Ok(()))
113+
let target = to_cstring(target)?;
114+
let link_name = to_cstring(link_name)?;
115+
h5call!(H5Lcreate_soft(
116+
target.as_ptr(),
117+
self.id(),
118+
link_name.as_ptr(),
119+
lcpl.id(),
120+
H5P_DEFAULT
121+
))
122+
.and(Ok(()))
114123
})
115124
}
116125

117-
/// Creates a hard link. Note: `src` and `dst` are relative to the current object.
118-
pub fn link_hard(&self, src: &str, dst: &str) -> Result<()> {
126+
/// Creates a hard link. Note: `target` and `link_name` are relative to the current object.
127+
pub fn link_hard(&self, target: &str, link_name: &str) -> Result<()> {
119128
// TODO: &mut self?
120-
let src = to_cstring(src)?;
121-
let dst = to_cstring(dst)?;
129+
let target = to_cstring(target)?;
130+
let link_name = to_cstring(link_name)?;
122131
h5call!(H5Lcreate_hard(
123132
self.id(),
124-
src.as_ptr(),
133+
target.as_ptr(),
125134
H5L_SAME_LOC,
126-
dst.as_ptr(),
135+
link_name.as_ptr(),
127136
H5P_DEFAULT,
128137
H5P_DEFAULT
129138
))
130139
.and(Ok(()))
131140
}
132141

142+
/// Creates an external link.
143+
///
144+
/// Note: `link_name` is relative to the current object,
145+
/// `target` is relative to the root of the source file,
146+
/// `target_file_name` is the path to the external file.
147+
///
148+
/// For a detailed explanation on how `target_file_name` is resolved, see
149+
/// [https://portal.hdfgroup.org/display/HDF5/H5L_CREATE_EXTERNAL](https://portal.hdfgroup.org/display/HDF5/H5L_CREATE_EXTERNAL)
150+
pub fn link_external(
151+
&self, target_file_name: &str, target: &str, link_name: &str,
152+
) -> Result<()> {
153+
// TODO: &mut self?
154+
let target = to_cstring(target)?;
155+
let target_file_name = to_cstring(target_file_name)?;
156+
let link_name = to_cstring(link_name)?;
157+
h5call!(H5Lcreate_external(
158+
target_file_name.as_ptr(),
159+
target.as_ptr(),
160+
self.id(),
161+
link_name.as_ptr(),
162+
H5P_DEFAULT,
163+
H5P_DEFAULT,
164+
))
165+
.and(Ok(()))
166+
}
167+
133168
/// Relinks an object. Note: `name` and `path` are relative to the current object.
134169
pub fn relink(&self, name: &str, path: &str) -> Result<()> {
135170
// TODO: &mut self?
@@ -412,4 +447,28 @@ pub mod tests {
412447
assert_eq!(file.member_names().unwrap(), vec!["a", "b"]);
413448
})
414449
}
450+
451+
#[test]
452+
pub fn test_external_link() {
453+
with_tmp_dir(|dir| {
454+
let file1 = dir.join("foo.h5");
455+
let file1 = File::create(file1).unwrap();
456+
let dset1 = file1.new_dataset::<i32>().create("foo").unwrap();
457+
dset1.write_scalar(&13).unwrap();
458+
459+
let file2 = dir.join("bar.h5");
460+
let file2 = File::create(file2).unwrap();
461+
file2.link_external("foo.h5", "foo", "bar").unwrap();
462+
let dset2 = file2.dataset("bar").unwrap();
463+
assert_eq!(dset2.read_scalar::<i32>().unwrap(), 13);
464+
465+
file1.unlink("foo").unwrap();
466+
assert!(file1.dataset("foo").is_err());
467+
assert!(file2.dataset("bar").is_err());
468+
469+
// foo is only weakly closed
470+
assert_eq!(dset1.read_scalar::<i32>().unwrap(), 13);
471+
assert_eq!(dset2.read_scalar::<i32>().unwrap(), 13);
472+
})
473+
}
415474
}

0 commit comments

Comments
 (0)