use std::collections::HashMap;
use super::types::{AttributeValue, DataArray};
#[derive(Debug, Clone, PartialEq)]
pub enum FileMode {
ReadOnly,
ReadWrite,
Create,
Truncate,
}
#[derive(Debug, Clone, PartialEq)]
pub enum StringEncoding {
UTF8,
ASCII,
}
#[derive(Debug, Clone, Default)]
pub struct FileStats {
pub num_groups: usize,
pub num_datasets: usize,
pub num_attributes: usize,
pub total_data_size: usize,
}
#[derive(Debug, Clone)]
pub struct Group {
pub name: String,
pub groups: HashMap<String, Group>,
pub datasets: HashMap<String, Dataset>,
pub attributes: HashMap<String, AttributeValue>,
}
impl Group {
pub fn new(name: String) -> Self {
Self {
name,
groups: HashMap::new(),
datasets: HashMap::new(),
attributes: HashMap::new(),
}
}
pub fn create_group(&mut self, name: &str) -> &mut Group {
self.groups
.entry(name.to_string())
.or_insert_with(|| Group::new(name.to_string()))
}
pub fn get_group(&self, name: &str) -> Option<&Group> {
self.groups.get(name)
}
pub fn get_group_mut(&mut self, name: &str) -> Option<&mut Group> {
self.groups.get_mut(name)
}
pub fn set_attribute(&mut self, name: &str, value: AttributeValue) {
self.attributes.insert(name.to_string(), value);
}
pub fn get_attribute(&self, name: &str) -> Option<&AttributeValue> {
self.attributes.get(name)
}
pub fn remove_attribute(&mut self, name: &str) -> Option<AttributeValue> {
self.attributes.remove(name)
}
pub fn attribute_names(&self) -> Vec<&str> {
self.attributes.keys().map(|s| s.as_str()).collect()
}
pub fn has_attribute(&self, name: &str) -> bool {
self.attributes.contains_key(name)
}
pub fn get_dataset(&self, name: &str) -> Option<&Dataset> {
self.datasets.get(name)
}
pub fn get_dataset_mut(&mut self, name: &str) -> Option<&mut Dataset> {
self.datasets.get_mut(name)
}
pub fn dataset_names(&self) -> Vec<&str> {
self.datasets.keys().map(|s| s.as_str()).collect()
}
pub fn group_names(&self) -> Vec<&str> {
self.groups.keys().map(|s| s.as_str()).collect()
}
pub fn has_dataset(&self, name: &str) -> bool {
self.datasets.contains_key(name)
}
pub fn has_group(&self, name: &str) -> bool {
self.groups.contains_key(name)
}
pub fn remove_dataset(&mut self, name: &str) -> Option<Dataset> {
self.datasets.remove(name)
}
pub fn remove_group(&mut self, name: &str) -> Option<Group> {
self.groups.remove(name)
}
}
#[derive(Debug, Clone)]
pub struct Dataset {
pub name: String,
pub dtype: HDF5DataType,
pub shape: Vec<usize>,
pub data: DataArray,
pub attributes: HashMap<String, AttributeValue>,
pub options: DatasetOptions,
}
impl Dataset {
pub fn new(
name: String,
dtype: HDF5DataType,
shape: Vec<usize>,
data: DataArray,
options: DatasetOptions,
) -> Self {
Self {
name,
dtype,
shape,
data,
attributes: HashMap::new(),
options,
}
}
pub fn set_attribute(&mut self, name: &str, value: AttributeValue) {
self.attributes.insert(name.to_string(), value);
}
pub fn get_attribute(&self, name: &str) -> Option<&AttributeValue> {
self.attributes.get(name)
}
pub fn remove_attribute(&mut self, name: &str) -> Option<AttributeValue> {
self.attributes.remove(name)
}
pub fn len(&self) -> usize {
self.shape.iter().product()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn ndim(&self) -> usize {
self.shape.len()
}
pub fn size_bytes(&self) -> usize {
let element_size = match &self.dtype {
HDF5DataType::Integer { size, .. } => *size,
HDF5DataType::Float { size } => *size,
HDF5DataType::String { .. } => 8,
HDF5DataType::Array { .. } => 8,
HDF5DataType::Compound { .. } => 8,
HDF5DataType::Enum { .. } => 8,
};
self.len() * element_size
}
pub fn as_float_vec(&self) -> Option<Vec<f64>> {
match &self.data {
DataArray::Float(data) => Some(data.clone()),
DataArray::Integer(data) => Some(data.iter().map(|&x| x as f64).collect()),
_ => None,
}
}
pub fn as_integer_vec(&self) -> Option<Vec<i64>> {
match &self.data {
DataArray::Integer(data) => Some(data.clone()),
DataArray::Float(data) => Some(data.iter().map(|&x| x as i64).collect()),
_ => None,
}
}
pub fn as_string_vec(&self) -> Option<Vec<String>> {
match &self.data {
DataArray::String(data) => Some(data.clone()),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum HDF5DataType {
Integer {
size: usize,
signed: bool,
},
Float {
size: usize,
},
String {
encoding: StringEncoding,
},
Array {
base_type: Box<HDF5DataType>,
shape: Vec<usize>,
},
Compound {
fields: Vec<(String, HDF5DataType)>,
},
Enum {
values: Vec<(String, i64)>,
},
}
#[derive(Debug, Clone, Default)]
pub struct CompressionOptions {
pub gzip: Option<u8>,
pub szip: Option<(u32, u32)>,
pub lzf: bool,
pub shuffle: bool,
}
#[derive(Debug, Clone, Default)]
pub struct DatasetOptions {
pub chunk_size: Option<Vec<usize>>,
pub compression: CompressionOptions,
pub fill_value: Option<f64>,
pub fletcher32: bool,
}