Skip to main content

hdf5_pure/
file_create_properties.rs

1//! File-creation properties as one reusable value — the `fcpl` analogue.
2
3use crate::file_space_info::FileSpaceStrategy;
4use crate::libver::LibVer;
5
6/// File-creation properties applied when writing a new HDF5 file.
7///
8/// This is the `hdf5-pure` analogue of an HDF5 **file creation property list**
9/// (`fcpl`): one value carrying every creation-time setting, so application code
10/// can define a file layout once and reuse it everywhere it writes, instead of
11/// repeating a builder call chain and keeping the copies in sync.
12///
13/// The `Properties` suffix means the type stands in for one whole HDF5 property
14/// list, so every setting on it has a C counterpart to look up. It is a stand-in
15/// and not a port: a plain `Copy` value, with no handle to create or close, no
16/// runtime property registry, and no setter that can fail. `fcpl` and each
17/// `H5Pset_*` it models are doc aliases, so a search for either lands here.
18///
19/// One setting crosses the class line. `H5Pset_libver_bounds` is officially a
20/// *file access* property, but this crate checks the bound as the file is
21/// written, so [`with_libver_bounds`](Self::with_libver_bounds) lives here with
22/// the other write-time settings rather than on
23/// [`FileAccessProperties`](crate::FileAccessProperties).
24///
25/// Pass it to [`FileBuilder::with_create_properties`](crate::FileBuilder::with_create_properties)
26/// or [`File::create_with_options`](crate::File::create_with_options). The
27/// equivalent [`FileBuilder`](crate::FileBuilder) methods set the same fields one
28/// at a time and interoperate freely with this.
29///
30/// Values are recorded as given and checked when the file is written, not when
31/// the properties are built — the value is inert data, so an illegal page size
32/// is reported by `finish`/`write` rather than here. Note that a non-paged
33/// userblock size is currently **not** validated against HDF5's power-of-two
34/// rule; see the property-support reference for the exact coverage.
35///
36/// See the [property-support reference] for the full property-by-property map.
37///
38/// [property-support reference]: https://github.com/CramBL/hdf5-pure/blob/main/docs/reference/property-support.md
39///
40/// # Examples
41///
42/// ```no_run
43/// use hdf5_pure::{FileCreateProperties, FileSpaceStrategy};
44///
45/// // Define the layout once...
46/// fn paged_layout() -> FileCreateProperties {
47///     FileCreateProperties::new()
48///         .with_file_space_strategy(FileSpaceStrategy::Page, true, 1)
49///         .with_file_space_page_size(8192)
50/// }
51///
52/// // ...and reuse it across every write path.
53/// let mut builder = hdf5_pure::FileBuilder::new();
54/// builder.with_create_properties(paged_layout());
55/// builder.create_dataset("data").with_f64_data(&[1.0, 2.0]);
56/// builder.write("out.h5").unwrap();
57/// ```
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59#[doc(alias = "fcpl")]
60pub struct FileCreateProperties {
61    userblock: u64,
62    libver_bounds: Option<(LibVer, LibVer)>,
63    file_space_strategy: Option<(FileSpaceStrategy, bool, u64)>,
64    file_space_page_size: Option<u64>,
65}
66
67impl FileCreateProperties {
68    /// A value carrying the crate's default creation behavior: no userblock,
69    /// no library-version bounds, and the writer's default file-space handling.
70    pub const fn new() -> Self {
71        Self {
72            userblock: 0,
73            libver_bounds: None,
74            file_space_strategy: None,
75            file_space_page_size: None,
76        }
77    }
78
79    /// Reserve a zero-filled userblock of `size` bytes before the superblock.
80    ///
81    /// HDF5 requires a power of two `>= 512`, or 0 for no userblock; the check
82    /// runs when the file is written. See
83    /// [`FileBuilder::with_userblock`](crate::FileBuilder::with_userblock) for how
84    /// to fill the region afterward.
85    #[doc(alias = "H5Pset_userblock")]
86    pub const fn with_userblock(mut self, size: u64) -> Self {
87        self.userblock = size;
88        self
89    }
90
91    /// Constrain the on-disk format version to `[low, high]`.
92    ///
93    /// `high` **selects** the format: `Earliest..=V18` writes the HDF5 1.8 one
94    /// and anything reaching 1.10 writes the 1.10 one, so this changes the bytes
95    /// of every file the properties are applied to. Content the chosen format
96    /// cannot express is refused with
97    /// [`FormatError::LibverTooOldForContent`](crate::FormatError::LibverTooOldForContent)
98    /// rather than silently upgraded — see
99    /// [`FileBuilder::with_libver_bounds`](crate::FileBuilder::with_libver_bounds)
100    /// for which content that is.
101    ///
102    /// `low` only rules formats out, licensing newer encodings without requiring
103    /// them, so a lower bound of `V112`, `V114` or `LATEST` writes the 1.10
104    /// format rather than being refused — provided `high` reaches it. An
105    /// inverted range such as `V114..=V110` is refused with
106    /// [`FormatError::LibverBoundsUnsatisfiable`](crate::FormatError::LibverBoundsUnsatisfiable).
107    ///
108    /// HDF5 classes `H5Pset_libver_bounds` as a *file access* property; it sits
109    /// here because this crate resolves the bound at write time.
110    #[doc(alias = "H5Pset_libver_bounds")]
111    pub const fn with_libver_bounds(mut self, low: LibVer, high: LibVer) -> Self {
112        self.libver_bounds = Some((low, high));
113        self
114    }
115
116    /// Set the file-space management strategy, whether free space persists across
117    /// close, and the smallest free-space section tracked.
118    #[doc(alias = "H5Pset_file_space_strategy")]
119    pub const fn with_file_space_strategy(
120        mut self,
121        strategy: FileSpaceStrategy,
122        persist: bool,
123        threshold: u64,
124    ) -> Self {
125        self.file_space_strategy = Some((strategy, persist, threshold));
126        self
127    }
128
129    /// Set the file-space page size, the allocation quantum under
130    /// [`FileSpaceStrategy::Page`].
131    #[doc(alias = "H5Pset_file_space_page_size")]
132    pub const fn with_file_space_page_size(mut self, page_size: u64) -> Self {
133        self.file_space_page_size = Some(page_size);
134        self
135    }
136
137    /// Return the configured userblock size in bytes (0 for none).
138    pub const fn userblock(&self) -> u64 {
139        self.userblock
140    }
141
142    /// Return the configured library-version bounds, if any.
143    pub const fn libver_bounds(&self) -> Option<(LibVer, LibVer)> {
144        self.libver_bounds
145    }
146
147    /// Return the configured file-space strategy, persist flag, and threshold, if
148    /// any.
149    pub const fn file_space_strategy(&self) -> Option<(FileSpaceStrategy, bool, u64)> {
150        self.file_space_strategy
151    }
152
153    /// Return the configured file-space page size, if any.
154    pub const fn file_space_page_size(&self) -> Option<u64> {
155        self.file_space_page_size
156    }
157}
158
159impl Default for FileCreateProperties {
160    fn default() -> Self {
161        Self::new()
162    }
163}