1use std::collections::HashMap;
6
7use super::types::{AttributeValue, DataArray};
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum FileMode {
12 ReadOnly,
14 ReadWrite,
16 Create,
18 Truncate,
20}
21#[derive(Debug, Clone, PartialEq)]
23pub enum StringEncoding {
24 UTF8,
26 ASCII,
28}
29#[derive(Debug, Clone, Default)]
31pub struct FileStats {
32 pub num_groups: usize,
34 pub num_datasets: usize,
36 pub num_attributes: usize,
38 pub total_data_size: usize,
40}
41#[derive(Debug, Clone)]
43pub struct Group {
44 pub name: String,
46 pub groups: HashMap<String, Group>,
48 pub datasets: HashMap<String, Dataset>,
50 pub attributes: HashMap<String, AttributeValue>,
52}
53impl Group {
54 pub fn new(name: String) -> Self {
56 Self {
57 name,
58 groups: HashMap::new(),
59 datasets: HashMap::new(),
60 attributes: HashMap::new(),
61 }
62 }
63 pub fn create_group(&mut self, name: &str) -> &mut Group {
65 self.groups
66 .entry(name.to_string())
67 .or_insert_with(|| Group::new(name.to_string()))
68 }
69 pub fn get_group(&self, name: &str) -> Option<&Group> {
71 self.groups.get(name)
72 }
73 pub fn get_group_mut(&mut self, name: &str) -> Option<&mut Group> {
75 self.groups.get_mut(name)
76 }
77 pub fn set_attribute(&mut self, name: &str, value: AttributeValue) {
79 self.attributes.insert(name.to_string(), value);
80 }
81 pub fn get_attribute(&self, name: &str) -> Option<&AttributeValue> {
83 self.attributes.get(name)
84 }
85 pub fn remove_attribute(&mut self, name: &str) -> Option<AttributeValue> {
87 self.attributes.remove(name)
88 }
89 pub fn attribute_names(&self) -> Vec<&str> {
91 self.attributes.keys().map(|s| s.as_str()).collect()
92 }
93 pub fn has_attribute(&self, name: &str) -> bool {
95 self.attributes.contains_key(name)
96 }
97 pub fn get_dataset(&self, name: &str) -> Option<&Dataset> {
99 self.datasets.get(name)
100 }
101 pub fn get_dataset_mut(&mut self, name: &str) -> Option<&mut Dataset> {
103 self.datasets.get_mut(name)
104 }
105 pub fn dataset_names(&self) -> Vec<&str> {
107 self.datasets.keys().map(|s| s.as_str()).collect()
108 }
109 pub fn group_names(&self) -> Vec<&str> {
111 self.groups.keys().map(|s| s.as_str()).collect()
112 }
113 pub fn has_dataset(&self, name: &str) -> bool {
115 self.datasets.contains_key(name)
116 }
117 pub fn has_group(&self, name: &str) -> bool {
119 self.groups.contains_key(name)
120 }
121 pub fn remove_dataset(&mut self, name: &str) -> Option<Dataset> {
123 self.datasets.remove(name)
124 }
125 pub fn remove_group(&mut self, name: &str) -> Option<Group> {
127 self.groups.remove(name)
128 }
129}
130#[derive(Debug, Clone)]
132pub struct Dataset {
133 pub name: String,
135 pub dtype: HDF5DataType,
137 pub shape: Vec<usize>,
139 pub data: DataArray,
141 pub attributes: HashMap<String, AttributeValue>,
143 pub options: DatasetOptions,
145}
146impl Dataset {
147 pub fn new(
149 name: String,
150 dtype: HDF5DataType,
151 shape: Vec<usize>,
152 data: DataArray,
153 options: DatasetOptions,
154 ) -> Self {
155 Self {
156 name,
157 dtype,
158 shape,
159 data,
160 attributes: HashMap::new(),
161 options,
162 }
163 }
164 pub fn set_attribute(&mut self, name: &str, value: AttributeValue) {
166 self.attributes.insert(name.to_string(), value);
167 }
168 pub fn get_attribute(&self, name: &str) -> Option<&AttributeValue> {
170 self.attributes.get(name)
171 }
172 pub fn remove_attribute(&mut self, name: &str) -> Option<AttributeValue> {
174 self.attributes.remove(name)
175 }
176 pub fn len(&self) -> usize {
178 self.shape.iter().product()
179 }
180 pub fn is_empty(&self) -> bool {
182 self.len() == 0
183 }
184 pub fn ndim(&self) -> usize {
186 self.shape.len()
187 }
188 pub fn size_bytes(&self) -> usize {
190 let element_size = match &self.dtype {
191 HDF5DataType::Integer { size, .. } => *size,
192 HDF5DataType::Float { size } => *size,
193 HDF5DataType::String { .. } => 8,
194 HDF5DataType::Array { .. } => 8,
195 HDF5DataType::Compound { .. } => 8,
196 HDF5DataType::Enum { .. } => 8,
197 };
198 self.len() * element_size
199 }
200 pub fn as_float_vec(&self) -> Option<Vec<f64>> {
202 match &self.data {
203 DataArray::Float(data) => Some(data.clone()),
204 DataArray::Integer(data) => Some(data.iter().map(|&x| x as f64).collect()),
205 _ => None,
206 }
207 }
208 pub fn as_integer_vec(&self) -> Option<Vec<i64>> {
210 match &self.data {
211 DataArray::Integer(data) => Some(data.clone()),
212 DataArray::Float(data) => Some(data.iter().map(|&x| x as i64).collect()),
213 _ => None,
214 }
215 }
216 pub fn as_string_vec(&self) -> Option<Vec<String>> {
218 match &self.data {
219 DataArray::String(data) => Some(data.clone()),
220 _ => None,
221 }
222 }
223}
224#[derive(Debug, Clone, PartialEq)]
226pub enum HDF5DataType {
227 Integer {
229 size: usize,
231 signed: bool,
233 },
234 Float {
236 size: usize,
238 },
239 String {
241 encoding: StringEncoding,
243 },
244 Array {
246 base_type: Box<HDF5DataType>,
248 shape: Vec<usize>,
250 },
251 Compound {
253 fields: Vec<(String, HDF5DataType)>,
255 },
256 Enum {
258 values: Vec<(String, i64)>,
260 },
261}
262#[derive(Debug, Clone, Default)]
264pub struct CompressionOptions {
265 pub gzip: Option<u8>,
267 pub szip: Option<(u32, u32)>,
269 pub lzf: bool,
271 pub shuffle: bool,
273}
274#[derive(Debug, Clone, Default)]
276pub struct DatasetOptions {
277 pub chunk_size: Option<Vec<usize>>,
279 pub compression: CompressionOptions,
281 pub fill_value: Option<f64>,
283 pub fletcher32: bool,
285}