use thiserror::Error;
use uom::si::{f64::Ratio, ratio};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct IsentropicEfficiency(Ratio);
#[derive(Debug, Error)]
#[error("isentropic efficiency must be in (0, 1], got {value}")]
pub struct InvalidIsentropicEfficiency {
pub value: f64,
}
impl IsentropicEfficiency {
pub fn new(eta: f64) -> Result<Self, InvalidIsentropicEfficiency> {
if !(eta > 0.0 && eta <= 1.0) {
return Err(InvalidIsentropicEfficiency { value: eta });
}
Ok(Self(Ratio::new::<ratio::ratio>(eta)))
}
pub fn from_ratio(eta: Ratio) -> Result<Self, InvalidIsentropicEfficiency> {
let value = eta.get::<ratio::ratio>();
if !(value > 0.0 && value <= 1.0) {
return Err(InvalidIsentropicEfficiency { value });
}
Ok(Self(eta))
}
#[must_use]
pub fn ratio(self) -> Ratio {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accepts_valid_range() {
assert!(IsentropicEfficiency::new(0.01).is_ok());
assert!(IsentropicEfficiency::new(0.9).is_ok());
assert!(IsentropicEfficiency::new(1.0).is_ok());
}
#[test]
fn rejects_zero() {
assert!(IsentropicEfficiency::new(0.0).is_err());
}
#[test]
fn rejects_negative() {
assert!(IsentropicEfficiency::new(-0.1).is_err());
}
#[test]
fn rejects_above_one() {
assert!(IsentropicEfficiency::new(1.01).is_err());
}
#[test]
fn rejects_nan() {
assert!(IsentropicEfficiency::new(f64::NAN).is_err());
}
#[test]
fn from_ratio_roundtrip() {
let r = Ratio::new::<ratio::ratio>(0.85);
let eta = IsentropicEfficiency::from_ratio(r).unwrap();
assert_eq!(eta.ratio(), r);
}
}