use serde::Deserialize;
use crate::registry::{Dimension, DimensionVector, RegistryError, UnitRegistry};
#[derive(Debug, Deserialize)]
struct File {
#[serde(default)]
dimension: Vec<DimensionEntry>,
#[serde(default)]
unit: Vec<UnitEntry>,
}
#[derive(Debug, Deserialize)]
struct DimensionEntry {
name: String,
exponents: [i8; 7],
}
#[derive(Debug, Deserialize)]
struct UnitEntry {
name: String,
dimension: String,
scale: f64,
#[serde(default)]
offset: f64,
#[serde(default)]
gauge: bool,
}
impl UnitRegistry {
pub fn load_from_toml_str(&mut self, toml_text: &str) -> Result<(), RegistryError> {
let file: File = toml::from_str(toml_text)
.map_err(|e| RegistryError::ParseError(format!("TOML: {e}")))?;
for d in file.dimension {
self.define_dimension(&d.name, DimensionVector::new(d.exponents))?;
}
for u in file.unit {
if u.gauge {
if u.dimension != "pressure" {
return Err(RegistryError::ParseError(format!(
"gauge=true is only valid for pressure (unit `{}` has dimension `{}`)",
u.name, u.dimension
)));
}
self.define_gauge(&u.name, u.scale)?;
} else if let Some(d) = Dimension::from_name(&u.dimension) {
self.define(&u.name, d, u.scale, u.offset)?;
} else {
self.define_with_dimension(&u.name, &u.dimension, u.scale, u.offset)?;
}
}
Ok(())
}
pub fn load_from_toml(
&mut self,
path: impl AsRef<std::path::Path>,
) -> Result<(), RegistryError> {
let text = std::fs::read_to_string(path)
.map_err(|e| RegistryError::ParseError(format!("read: {e}")))?;
self.load_from_toml_str(&text)
}
}