use std::collections::BTreeMap;
use std::sync::Arc;
use crate::{
ChromaticSerialRealizer, MarkedChromaticInflectionRealizer, ModalDegreeCycleRealizer,
NearestScaleToneRealizer, NonPitchSpineRealizer, RealizationContext, RealizerId, SerialPlan,
SerialRealization, SerialRealizer, StrictRealizationError,
};
#[derive(Clone, Default)]
pub struct SerialRealizerRegistry {
entries: BTreeMap<RealizerId, Arc<dyn SerialRealizer>>,
}
impl SerialRealizerRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, realizer: Arc<dyn SerialRealizer>) -> Result<(), RealizerId> {
if self.entries.contains_key(realizer.id()) {
return Err(realizer.id().clone());
}
self.entries.insert(realizer.id().clone(), realizer);
Ok(())
}
pub fn replace(
&mut self,
realizer: Arc<dyn SerialRealizer>,
) -> Option<Arc<dyn SerialRealizer>> {
self.entries.insert(realizer.id().clone(), realizer)
}
pub fn get(&self, id: &RealizerId) -> Option<&Arc<dyn SerialRealizer>> {
self.entries.get(id)
}
pub fn ids(&self) -> Vec<RealizerId> {
self.entries.keys().cloned().collect()
}
pub fn realize(
&self,
id: &RealizerId,
plan: &SerialPlan,
context: &RealizationContext,
) -> Result<SerialRealization, StrictRealizationError> {
let Some(realizer) = self.get(id) else {
return Err(StrictRealizationError::UnknownRealizer(id.clone()));
};
realizer.realize(plan, context)
}
pub fn realize_named(
&self,
id: &str,
plan: &SerialPlan,
context: &RealizationContext,
) -> Result<SerialRealization, StrictRealizationError> {
let id = RealizerId::new(id)
.map_err(|error| StrictRealizationError::PitchMap(error.to_string()))?;
self.realize(&id, plan, context)
}
}
pub fn default_realizer_registry() -> SerialRealizerRegistry {
let mut registry = SerialRealizerRegistry::new();
registry.replace(Arc::new(ChromaticSerialRealizer::default()));
registry.replace(Arc::new(ModalDegreeCycleRealizer::default()));
registry.replace(Arc::new(NearestScaleToneRealizer::default()));
registry.replace(Arc::new(MarkedChromaticInflectionRealizer::default()));
registry.replace(Arc::new(NonPitchSpineRealizer::default()));
registry
}