use std::fmt::Debug;
use sim_lib_serial_core::{
AggregateLedger, AggregateRule, AlphabetError, AlphabetId, FiniteAlphabet, SerialAlphabet,
Series, SeriesError, SeriesTransform, SeriesTransformError,
};
use thiserror::Error;
pub trait ParameterValue: Clone + Eq + Ord + Debug + 'static {}
impl<T> ParameterValue for T where T: Clone + Eq + Ord + Debug + 'static {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParameterAlphabet<T: ParameterValue> {
inner: FiniteAlphabet<T>,
}
impl<T: ParameterValue> ParameterAlphabet<T> {
pub fn try_new(id: impl Into<String>, symbols: Vec<T>) -> Result<Self, ParameterError> {
Ok(Self {
inner: FiniteAlphabet::try_new(AlphabetId::try_new(id.into())?, symbols)?,
})
}
pub fn id(&self) -> &AlphabetId {
self.inner.id()
}
pub fn symbols(&self) -> &[T] {
self.inner.symbols()
}
}
impl<T: ParameterValue> SerialAlphabet for ParameterAlphabet<T> {
type Symbol = T;
fn id(&self) -> &AlphabetId {
self.inner.id()
}
fn symbols(&self) -> &[Self::Symbol] {
self.inner.symbols()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParameterSeries<T: ParameterValue> {
inner: Series<ParameterAlphabet<T>>,
}
impl<T: ParameterValue> ParameterSeries<T> {
pub fn try_new(id: impl Into<String>, order: Vec<T>) -> Result<Self, ParameterError> {
let id = id.into();
Self::try_new_with_rule(id.clone(), AggregateRule::exhaustive_exactly_once(), order)
}
pub fn try_new_with_rule(
id: impl Into<String>,
rule: AggregateRule,
order: Vec<T>,
) -> Result<Self, ParameterError> {
let alphabet = ParameterAlphabet::try_new(id, order.clone())?;
Ok(Self {
inner: Series::try_new(alphabet, rule, order)?,
})
}
pub fn alphabet(&self) -> &ParameterAlphabet<T> {
self.inner.alphabet()
}
pub fn rule(&self) -> &AggregateRule {
self.inner.rule()
}
pub fn order(&self) -> &[T] {
self.inner.order()
}
pub fn ledger(&self) -> &AggregateLedger<T> {
self.inner.ledger()
}
pub fn apply(
&self,
transform: &SeriesTransform<ParameterAlphabet<T>>,
) -> Result<Self, ParameterError> {
Ok(Self {
inner: self.inner.apply(transform)?.series,
})
}
}
#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum ParameterError {
#[error(transparent)]
Alphabet(#[from] AlphabetError),
#[error(transparent)]
Series(#[from] SeriesError),
#[error(transparent)]
Transform(#[from] SeriesTransformError),
}