Skip to main content

sim_lib_music_serial/
parameter.rs

1//! Generic typed parameter alphabets and series for integral serialism.
2
3use std::fmt::Debug;
4
5use sim_lib_serial_core::{
6    AggregateLedger, AggregateRule, AlphabetError, AlphabetId, FiniteAlphabet, SerialAlphabet,
7    Series, SeriesError, SeriesTransform, SeriesTransformError,
8};
9use thiserror::Error;
10
11/// Value bound accepted by generic serial parameter tracks.
12pub trait ParameterValue: Clone + Eq + Ord + Debug + 'static {}
13
14impl<T> ParameterValue for T where T: Clone + Eq + Ord + Debug + 'static {}
15
16/// Generic finite alphabet declared by one parameter owner.
17#[derive(Clone, Debug, PartialEq, Eq)]
18pub struct ParameterAlphabet<T: ParameterValue> {
19    inner: FiniteAlphabet<T>,
20}
21
22impl<T: ParameterValue> ParameterAlphabet<T> {
23    /// Constructs a finite parameter alphabet with a stable caller-owned id.
24    pub fn try_new(id: impl Into<String>, symbols: Vec<T>) -> Result<Self, ParameterError> {
25        Ok(Self {
26            inner: FiniteAlphabet::try_new(AlphabetId::try_new(id.into())?, symbols)?,
27        })
28    }
29
30    /// Returns the stable identity of this alphabet.
31    pub fn id(&self) -> &AlphabetId {
32        self.inner.id()
33    }
34
35    /// Returns the canonical symbol ladder retained by this alphabet.
36    pub fn symbols(&self) -> &[T] {
37        self.inner.symbols()
38    }
39}
40
41impl<T: ParameterValue> SerialAlphabet for ParameterAlphabet<T> {
42    type Symbol = T;
43
44    fn id(&self) -> &AlphabetId {
45        self.inner.id()
46    }
47
48    fn symbols(&self) -> &[Self::Symbol] {
49        self.inner.symbols()
50    }
51}
52
53/// Thin typed wrapper over an unchanged serial-core [`Series`].
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct ParameterSeries<T: ParameterValue> {
56    inner: Series<ParameterAlphabet<T>>,
57}
58
59impl<T: ParameterValue> ParameterSeries<T> {
60    /// Constructs one exhaustive exactly-once parameter series.
61    pub fn try_new(id: impl Into<String>, order: Vec<T>) -> Result<Self, ParameterError> {
62        let id = id.into();
63        Self::try_new_with_rule(id.clone(), AggregateRule::exhaustive_exactly_once(), order)
64    }
65
66    /// Constructs one parameter series under an explicit aggregate rule.
67    pub fn try_new_with_rule(
68        id: impl Into<String>,
69        rule: AggregateRule,
70        order: Vec<T>,
71    ) -> Result<Self, ParameterError> {
72        let alphabet = ParameterAlphabet::try_new(id, order.clone())?;
73        Ok(Self {
74            inner: Series::try_new(alphabet, rule, order)?,
75        })
76    }
77
78    /// Returns the retained generic parameter alphabet.
79    pub fn alphabet(&self) -> &ParameterAlphabet<T> {
80        self.inner.alphabet()
81    }
82
83    /// Returns the unchanged aggregate rule carried by the series.
84    pub fn rule(&self) -> &AggregateRule {
85        self.inner.rule()
86    }
87
88    /// Returns the ordered parameter values.
89    pub fn order(&self) -> &[T] {
90        self.inner.order()
91    }
92
93    /// Returns the source aggregate ledger retained by serial-core.
94    pub fn ledger(&self) -> &AggregateLedger<T> {
95        self.inner.ledger()
96    }
97
98    /// Applies one serial-core transform and returns a new typed parameter series.
99    pub fn apply(
100        &self,
101        transform: &SeriesTransform<ParameterAlphabet<T>>,
102    ) -> Result<Self, ParameterError> {
103        Ok(Self {
104            inner: self.inner.apply(transform)?.series,
105        })
106    }
107}
108
109/// Failure while constructing or transforming a typed parameter series.
110#[derive(Clone, Debug, PartialEq, Eq, Error)]
111pub enum ParameterError {
112    /// The parameter alphabet id or symbol ladder was invalid.
113    #[error(transparent)]
114    Alphabet(#[from] AlphabetError),
115    /// The supplied order violated the declared aggregate rule.
116    #[error(transparent)]
117    Series(#[from] SeriesError),
118    /// The requested transform was invalid for this parameter series.
119    #[error(transparent)]
120    Transform(#[from] SeriesTransformError),
121}