use crate::measurement::*;
use snafu::prelude::*;
use std::{path::PathBuf, str::FromStr};
use hdf5_metno::{Error, File, H5Type, Location, types::VarLenUnicode};
type Result<T> = std::result::Result<T, MeasurementError>;
pub fn read_h5_attr_scalar<T>(loc: &hdf5_metno::Location, attr_name: &str) -> Result<T>
where
T: H5Type,
{
let attr = loc.attr(attr_name).and_then(|attr| attr.read_scalar::<T>());
let attr = attr.map_err(H5Error::from);
attr.context(ReadingAttributeFailedSnafu { attr_name })
}
pub fn write_h5_attr_scalar<T>(loc: &hdf5_metno::Location, attr_name: &str, val: T) -> Result<()>
where
T: H5Type,
{
let attr = loc
.new_attr::<T>()
.create(attr_name)
.map_err(H5Error::from)
.context(H5FileProblemSnafu {
operation: format!("Creating scalar attribute for: {}", attr_name),
})?;
attr.write_scalar(&val)
.map_err(H5Error::from)
.with_context(|_| WritingAttributeFailedSnafu {
attr_name: attr_name.to_string(),
})?;
Ok(())
}
pub fn write_h5_attr_scalar_overwrite<T>(
loc: &hdf5_metno::Location,
attr_name: &str,
val: T,
) -> Result<()>
where
T: H5Type,
{
if let Err(e) = loc.delete_attr(attr_name) {
eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
}
write_h5_attr_scalar(loc, attr_name, val)
}
pub fn read_h5_attr_list<T>(loc: &Location, attr_name: &str) -> Result<Vec<T>>
where
T: H5Type + Clone,
{
let attr = loc
.attr(attr_name)
.and_then(|attr| attr.read_1d::<T>())
.map(|arr| arr.to_vec());
attr.map_err(H5Error::from)
.with_context(|_| ReadingAttributeFailedSnafu {
attr_name: attr_name.to_string(),
})
}
pub fn write_h5_attr_list<T>(loc: &Location, attr_name: &str, val: &[T]) -> Result<()>
where
T: H5Type,
{
let attr = loc
.new_attr::<T>()
.shape([val.len()])
.create(attr_name)
.map_err(H5Error::from)
.context(WritingAttributeFailedSnafu { attr_name })?;
attr.write(val)
.map_err(H5Error::from)
.context(WritingAttributeFailedSnafu { attr_name })?;
Ok(())
}
pub fn write_h5_attr_list_overwrite<T>(loc: &Location, attr_name: &str, val: &[T]) -> Result<()>
where
T: H5Type,
{
if let Err(e) = loc.delete_attr(attr_name) {
eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
}
write_h5_attr_list(loc, attr_name, val)
}
pub fn read_h5_attr_string(loc: &Location, attr_name: &str) -> Result<String> {
let attr = loc
.attr(attr_name)
.and_then(|attr| attr.read_scalar::<VarLenUnicode>())
.map(|s| s.to_string())
.map_err(H5Error::from);
attr.with_context(|_| ReadingAttributeFailedSnafu {
attr_name: attr_name.to_string(),
})
}
pub fn write_h5_attr_string(loc: &Location, attr_name: &str, val: &str) -> Result<()> {
let h5string: VarLenUnicode =
VarLenUnicode::from_str(val).expect("Failed to convert string to VarLenUnicode");
write_h5_attr_scalar(loc, attr_name, h5string)
}
pub fn write_h5_attr_string_overwrite(loc: &Location, attr_name: &str, val: &str) -> Result<()> {
if let Err(e) = loc.delete_attr(attr_name) {
eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
}
write_h5_attr_string(loc, attr_name, val)
}
pub fn read_h5_attr_stringlist(loc: &Location, attr_name: &str) -> Result<Vec<String>> {
let attr = loc
.attr(attr_name)
.and_then(|attr| attr.read_1d::<VarLenUnicode>())
.map(|arr| arr.into_iter().map(|s| s.to_string()).collect())
.map_err(H5Error::from);
attr.context(ReadingAttributeFailedSnafu { attr_name })
}
pub fn write_h5_attr_stringlist(loc: &Location, attr_name: &str, val: &[String]) -> Result<()> {
let attr_h5 = val
.iter()
.map(|v| VarLenUnicode::from_str(v).expect("Error converting string to hdf5 VarLenUnicode"))
.collect::<Vec<_>>();
write_h5_attr_list(loc, attr_name, &attr_h5)
}
pub fn write_h5_attr_stringlist_overwrite(
loc: &Location,
attr_name: &str,
val: &[String],
) -> Result<()> {
if let Err(e) = loc.delete_attr(attr_name) {
eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
}
write_h5_attr_stringlist(loc, attr_name, val)
}