pub mod jordan_model;
pub use jordan_model::*;
use var_quantity::uom::si::f64::SpecificPower;
use var_quantity::{DynQuantity, IsQuantityFunction, QuantityFunction};
#[derive(Clone, Debug, PartialEq)]
pub enum IronLosses {
Constant(SpecificPower),
JordanModel(JordanModel),
Function(QuantityFunction<SpecificPower>),
}
impl IronLosses {
pub fn get(&self, conditions: &[DynQuantity<f64>]) -> SpecificPower {
match self {
Self::Constant(val) => val.clone(),
Self::JordanModel(model) => model.call(conditions).try_into().expect("implementation of JordanModel makes sure the returned value is always a SpecificPower"),
Self::Function(fun) => fun.call(conditions),
}
}
pub fn function(&self) -> Option<&dyn IsQuantityFunction> {
match self {
Self::Function(quantity_function) => return Some(quantity_function.as_ref()),
_ => return None,
}
}
}
impl TryFrom<Box<dyn IsQuantityFunction>> for IronLosses {
type Error = var_quantity::UnitsNotEqual;
fn try_from(value: Box<dyn IsQuantityFunction>) -> Result<Self, Self::Error> {
let wrapper = QuantityFunction::new(value)?;
return Ok(Self::Function(wrapper));
}
}
impl From<SpecificPower> for IronLosses {
fn from(value: SpecificPower) -> Self {
return Self::Constant(value);
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for IronLosses {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::Serialize;
use var_quantity::serialize_quantity;
#[derive(Serialize)]
enum PredefinedModels<'a> {
JordanModel(&'a JordanModel),
}
#[derive(Serialize)]
#[serde(untagged)]
enum IronLossesSerde<'a> {
#[serde(serialize_with = "serialize_quantity")]
Constant(SpecificPower),
PredefinedModels(PredefinedModels<'a>),
Function(&'a QuantityFunction<SpecificPower>),
}
let il = match self {
IronLosses::Constant(v) => IronLossesSerde::Constant(*v),
IronLosses::JordanModel(model) => {
IronLossesSerde::PredefinedModels(PredefinedModels::JordanModel(model))
}
IronLosses::Function(quantity_function) => IronLossesSerde::Function(quantity_function),
};
il.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for IronLosses {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use std::str::FromStr;
use serde::Deserialize;
use var_quantity::DynQuantity;
#[derive(Deserialize)]
enum PredefinedModels {
JordanModel(JordanModel),
}
#[derive(deserialize_untagged_verbose_error::DeserializeUntaggedVerboseError)]
enum IronLossesSerde {
Constant(SpecificPower),
String(String),
PredefinedModels(PredefinedModels),
Function(QuantityFunction<SpecificPower>),
}
let losses_de = IronLossesSerde::deserialize(deserializer)?;
let losses = match losses_de {
IronLossesSerde::Constant(v) => IronLosses::Constant(v),
IronLossesSerde::String(string) => {
let dyn_quantity =
DynQuantity::<f64>::from_str(&string).map_err(serde::de::Error::custom)?;
let static_quantity =
SpecificPower::try_from(dyn_quantity).map_err(serde::de::Error::custom)?;
IronLosses::Constant(static_quantity)
}
IronLossesSerde::PredefinedModels(pd) => match pd {
PredefinedModels::JordanModel(jordan_model) => {
IronLosses::JordanModel(jordan_model)
}
},
IronLossesSerde::Function(quantity_function) => IronLosses::Function(quantity_function),
};
return Ok(losses);
}
}