pub fn convert_unit(v: f64, from: &str, to: &str) -> Option<f64> {
if from == to {
return Some(v);
}
const RAD_TO_DEG: f64 = 180.0 / std::f64::consts::PI;
Some(match (from, to) {
("rad", "deg") => v * RAD_TO_DEG,
("deg", "rad") => v / RAD_TO_DEG,
("rad/s", "deg/s") => v * RAD_TO_DEG,
("deg/s", "rad/s") => v / RAD_TO_DEG,
("K", "C") => v - 273.15,
("C", "K") => v + 273.15,
("Pa", "bar") => v / 100_000.0,
("bar", "Pa") => v * 100_000.0,
("C", "Ah") => v / 3600.0,
("Ah", "C") => v * 3600.0,
("J", "kWh") => v / 3.6e6,
("kWh", "J") => v * 3.6e6,
_ => return None,
})
}
#[cfg(test)]
mod tests {
use super::convert_unit;
#[test]
fn identity_and_known_pairs() {
assert_eq!(convert_unit(1.5, "deg", "deg"), Some(1.5));
assert!((convert_unit(1.6384, "rad", "deg").unwrap() - 93.8734).abs() < 1e-3);
assert!((convert_unit(93.8734, "deg", "rad").unwrap() - 1.6384).abs() < 1e-4);
assert!((convert_unit(300.0, "K", "C").unwrap() - 26.85).abs() < 1e-9);
assert!((convert_unit(100_000.0, "Pa", "bar").unwrap() - 1.0).abs() < 1e-9);
assert!((convert_unit(3600.0, "C", "Ah").unwrap() - 1.0).abs() < 1e-9);
assert!((convert_unit(3.6e6, "J", "kWh").unwrap() - 1.0).abs() < 1e-9);
assert!((convert_unit(1.0, "kWh", "J").unwrap() - 3.6e6).abs() < 1e-3);
}
#[test]
fn unknown_pair_is_none() {
assert_eq!(convert_unit(1.0, "m/s", "kn"), None);
assert_eq!(convert_unit(1.0, "deg", "K"), None);
}
}