Skip to main content

oxigdal_hdf5/
lib.rs

1//! OxiGDAL HDF5 Driver - Pure Rust HDF5 with Optional C-Binding Support
2//!
3//! This crate provides HDF5 file format support for OxiGDAL, following the
4//! COOLJAPAN Pure Rust policy.
5//!
6//! # Pure Rust Policy Compliance
7//!
8//! **IMPORTANT**: This driver provides Pure Rust minimal HDF5 support by default,
9//! with feature-gated C bindings for full HDF5 functionality.
10//!
11//! ## Default: Pure Rust Minimal HDF5
12//!
13//! The default implementation provides basic HDF5 reading and writing capabilities
14//! in Pure Rust, inspired by the [hdf5file](https://github.com/sile/hdf5file)
15//! and [oxifive](https://github.com/dragly/oxifive) projects.
16//!
17//! **Supported Features (Pure Rust):**
18//! - Reading and writing HDF5 1.0 format (Superblock Version 0)
19//! - Basic datatypes: i8, u8, i16, u16, i32, u32, i64, u64, f32, f64
20//! - Fixed-length strings
21//! - Multi-dimensional datasets
22//! - Hierarchical groups
23//! - Attributes (metadata)
24//! - GZIP compression (via Pure Rust flate2)
25//! - Contiguous and chunked layouts
26//!
27//! **Limitations (Pure Rust):**
28//! - No HDF5 2.0/3.0 features (requires hdf5_sys)
29//! - No compound types (requires hdf5_sys)
30//! - No variable-length types (requires hdf5_sys)
31//! - No SZIP compression (requires hdf5_sys)
32//! - No advanced filters (requires hdf5_sys)
33//! - Limited to simple use cases
34//!
35//! ## Full HDF5 Support (C Bindings)
36//!
37//! For full HDF5 functionality, enable the `hdf5_sys` feature, which uses the
38//! [hdf5-rust](https://github.com/aldanor/hdf5-rust) crate with C bindings.
39//!
40//! **Warning**: Enabling `hdf5_sys` requires system libhdf5 library and is
41//! **NOT Pure Rust**.
42//!
43//! ## Feature Flags
44//!
45//! - `std` (default): Standard library support
46//! - `pure_rust` (default): Pure Rust minimal HDF5 implementation
47//! - `hdf5_sys`: Full HDF5 support via C bindings (NOT Pure Rust)
48//! - `compression`: Compression support (GZIP in Pure Rust, all filters with hdf5_sys)
49//! - `async`: Async I/O support
50//!
51//! # HDF5 Format Overview
52//!
53//! HDF5 (Hierarchical Data Format version 5) is a file format designed for
54//! storing and organizing large amounts of data. It's widely used in scientific
55//! computing, particularly for:
56//!
57//! - Climate and weather data (NetCDF-4 is built on HDF5)
58//! - Satellite imagery (HDF-EOS)
59//! - Astronomy datasets
60//! - Medical imaging
61//! - Machine learning model storage
62//!
63//! ## Key Concepts
64//!
65//! - **File**: Container for all HDF5 data
66//! - **Group**: Directory-like container for organizing objects
67//! - **Dataset**: Multi-dimensional array of homogeneous data
68//! - **Attribute**: Small metadata attached to groups or datasets
69//! - **Datatype**: Description of data element type
70//! - **Dataspace**: Description of dataset dimensions
71//!
72//! # Example - Writing HDF5 File (Pure Rust)
73//!
74//! ```ignore
75//! use oxigdal_hdf5::{Hdf5Writer, Hdf5Version};
76//! use oxigdal_hdf5::datatype::Datatype;
77//! use oxigdal_hdf5::dataset::DatasetProperties;
78//! use oxigdal_hdf5::attribute::Attribute;
79//!
80//! // Create HDF5 file
81//! let mut writer = Hdf5Writer::create("output.h5", Hdf5Version::V10)?;
82//!
83//! // Create group
84//! writer.create_group("/measurements")?;
85//!
86//! // Add group attribute
87//! writer.add_group_attribute(
88//!     "/measurements",
89//!     Attribute::string("description", "Temperature measurements")
90//! )?;
91//!
92//! // Create dataset
93//! writer.create_dataset(
94//!     "/measurements/temperature",
95//!     Datatype::Float32,
96//!     vec![100, 200],  // 100x200 array
97//!     DatasetProperties::new()
98//! )?;
99//!
100//! // Write data
101//! let data: Vec<f32> = vec![20.5; 20000];  // 100 * 200 elements
102//! writer.write_f32("/measurements/temperature", &data)?;
103//!
104//! // Add dataset attribute
105//! writer.add_dataset_attribute(
106//!     "/measurements/temperature",
107//!     Attribute::string("units", "celsius")
108//! )?;
109//!
110//! // Finalize file
111//! writer.finalize()?;
112//! # Ok::<(), oxigdal_hdf5::error::Hdf5Error>(())
113//! ```
114//!
115//! # Example - Reading HDF5 File (Pure Rust)
116//!
117//! ```ignore
118//! use oxigdal_hdf5::Hdf5Reader;
119//!
120//! // Open HDF5 file
121//! let mut reader = Hdf5Reader::open("output.h5")?;
122//!
123//! // Get root group
124//! let root = reader.root()?;
125//! println!("Root group: {}", root.name());
126//!
127//! // List groups
128//! for group_path in reader.list_groups() {
129//!     println!("Group: {}", group_path);
130//! }
131//!
132//! // List datasets
133//! for dataset_path in reader.list_datasets() {
134//!     let dataset = reader.dataset(dataset_path)?;
135//!     println!("Dataset: {} (shape: {:?}, type: {})",
136//!         dataset.name(),
137//!         dataset.dims(),
138//!         dataset.datatype()
139//!     );
140//! }
141//!
142//! // Read dataset
143//! let temperature = reader.read_f32("/measurements/temperature")?;
144//! println!("Temperature data: {} elements", temperature.len());
145//! # Ok::<(), oxigdal_hdf5::error::Hdf5Error>(())
146//! ```
147//!
148//! # Example - Chunked Dataset with Compression
149//!
150//! ```ignore
151//! use oxigdal_hdf5::{Hdf5Writer, Hdf5Version};
152//! use oxigdal_hdf5::datatype::Datatype;
153//! use oxigdal_hdf5::dataset::{DatasetProperties, CompressionFilter};
154//!
155//! let mut writer = Hdf5Writer::create("compressed.h5", Hdf5Version::V10)?;
156//!
157//! // Create compressed dataset with chunking
158//! let properties = DatasetProperties::new()
159//!     .with_chunks(vec![10, 20])        // 10x20 chunks
160//!     .with_gzip(6);                     // GZIP compression level 6
161//!
162//! writer.create_dataset(
163//!     "/data",
164//!     Datatype::Float64,
165//!     vec![1000, 2000],
166//!     properties
167//! )?;
168//!
169//! // Write data
170//! let data: Vec<f64> = vec![0.0; 2_000_000];
171//! writer.write_f64("/data", &data)?;
172//!
173//! writer.finalize()?;
174//! # Ok::<(), oxigdal_hdf5::error::Hdf5Error>(())
175//! ```
176//!
177//! # Integration with OxiGDAL
178//!
179//! This driver integrates with the OxiGDAL core types and can be used to read
180//! and write geospatial data in HDF5 format, particularly for:
181//!
182//! - HDF-EOS (Earth Observing System) satellite data
183//! - NetCDF-4 files (which use HDF5 as backend)
184//! - Climate model outputs
185//! - Remote sensing imagery
186//!
187//! # References
188//!
189//! - [HDF5 Specification](https://portal.hdfgroup.org/display/HDF5/File+Format+Specification)
190//! - [HDF5 User Guide](https://portal.hdfgroup.org/display/HDF5/HDF5+User+Guide)
191//! - [hdf5file](https://github.com/sile/hdf5file) - Pure Rust HDF5 implementation
192//! - [oxifive](https://github.com/dragly/oxifive) - Pure Rust HDF5 reader
193//! - [hdf5-rust](https://github.com/aldanor/hdf5-rust) - HDF5 C bindings for Rust
194//!
195//! # See Also
196//!
197//! - [`oxigdal-netcdf`](../oxigdal_netcdf/index.html) - NetCDF driver (NetCDF-4 uses HDF5)
198//! - [`oxigdal-geotiff`](../oxigdal_geotiff/index.html) - GeoTIFF driver
199//! - [`oxigdal-zarr`](../oxigdal_zarr/index.html) - Zarr driver (alternative to HDF5)
200
201#![warn(missing_docs)]
202#![deny(unsafe_code)]
203
204// Module declarations
205pub mod attribute;
206pub mod dataset;
207pub mod datatype;
208pub mod error;
209pub mod filters;
210pub mod group;
211pub mod reader;
212pub mod writer;
213
214// Re-exports
215pub use attribute::{Attribute, AttributeValue, Attributes};
216pub use dataset::{CompressionFilter, Dataset, DatasetProperties, LayoutType};
217pub use datatype::{
218    CompoundMember, Datatype, DatatypeClass, EnumMember, Hdf5ByteOrder, StringPadding,
219    TypeConverter,
220};
221pub use error::{Hdf5Error, Result};
222pub use group::{Group, ObjectRef, ObjectType, PathUtils};
223pub use reader::{Hdf5Reader, Hdf5ReaderBuilder, Superblock, SuperblockVersion};
224pub use writer::{Hdf5Version, Hdf5Writer, Hdf5WriterBuilder};
225
226/// Library version
227pub const VERSION: &str = env!("CARGO_PKG_VERSION");
228
229/// Library name
230pub const NAME: &str = env!("CARGO_PKG_NAME");
231
232/// Get library information
233pub fn version_info() -> String {
234    format!("{} v{}", NAME, VERSION)
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    fn test_version_info() {
243        let info = version_info();
244        assert!(info.contains("oxigdal-hdf5"));
245        assert!(info.contains(VERSION));
246    }
247
248    #[test]
249    fn test_constants() {
250        assert_eq!(NAME, "oxigdal-hdf5");
251        assert_eq!(VERSION, env!("CARGO_PKG_VERSION"));
252    }
253}