Skip to main content

sim_lib_music_serial/
registry.rs

1//! Open serial realizer registry.
2
3use std::collections::BTreeMap;
4use std::sync::Arc;
5
6use crate::{
7    ChromaticSerialRealizer, MarkedChromaticInflectionRealizer, ModalDegreeCycleRealizer,
8    NearestScaleToneRealizer, NonPitchSpineRealizer, RealizationContext, RealizerId, SerialPlan,
9    SerialRealization, SerialRealizer, StrictRealizationError,
10};
11
12/// Id-addressed registry of serial realizers with stable sorted listing.
13#[derive(Clone, Default)]
14pub struct SerialRealizerRegistry {
15    entries: BTreeMap<RealizerId, Arc<dyn SerialRealizer>>,
16}
17
18impl SerialRealizerRegistry {
19    /// Creates an empty registry.
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    /// Inserts one realizer, rejecting duplicate ids unless the caller uses `replace`.
25    pub fn register(&mut self, realizer: Arc<dyn SerialRealizer>) -> Result<(), RealizerId> {
26        if self.entries.contains_key(realizer.id()) {
27            return Err(realizer.id().clone());
28        }
29        self.entries.insert(realizer.id().clone(), realizer);
30        Ok(())
31    }
32
33    /// Inserts one realizer and returns the replaced registration, if any.
34    pub fn replace(
35        &mut self,
36        realizer: Arc<dyn SerialRealizer>,
37    ) -> Option<Arc<dyn SerialRealizer>> {
38        self.entries.insert(realizer.id().clone(), realizer)
39    }
40
41    /// Returns one registered realizer by id.
42    pub fn get(&self, id: &RealizerId) -> Option<&Arc<dyn SerialRealizer>> {
43        self.entries.get(id)
44    }
45
46    /// Returns all registered ids in stable sorted order.
47    pub fn ids(&self) -> Vec<RealizerId> {
48        self.entries.keys().cloned().collect()
49    }
50
51    /// Realizes one plan through the registered realizer named by `id`.
52    pub fn realize(
53        &self,
54        id: &RealizerId,
55        plan: &SerialPlan,
56        context: &RealizationContext,
57    ) -> Result<SerialRealization, StrictRealizationError> {
58        let Some(realizer) = self.get(id) else {
59            return Err(StrictRealizationError::UnknownRealizer(id.clone()));
60        };
61        realizer.realize(plan, context)
62    }
63
64    /// Realizes one plan through the registered realizer named by a stable string id.
65    pub fn realize_named(
66        &self,
67        id: &str,
68        plan: &SerialPlan,
69        context: &RealizationContext,
70    ) -> Result<SerialRealization, StrictRealizationError> {
71        let id = RealizerId::new(id)
72            .map_err(|error| StrictRealizationError::PitchMap(error.to_string()))?;
73        self.realize(&id, plan, context)
74    }
75}
76
77/// Returns the built-in registry with the strict chromatic realizer installed.
78pub fn default_realizer_registry() -> SerialRealizerRegistry {
79    let mut registry = SerialRealizerRegistry::new();
80    registry.replace(Arc::new(ChromaticSerialRealizer::default()));
81    registry.replace(Arc::new(ModalDegreeCycleRealizer::default()));
82    registry.replace(Arc::new(NearestScaleToneRealizer::default()));
83    registry.replace(Arc::new(MarkedChromaticInflectionRealizer::default()));
84    registry.replace(Arc::new(NonPitchSpineRealizer::default()));
85    registry
86}