melodium_core/descriptor/
source.rs

1use core::fmt::{Display, Formatter, Result};
2use melodium_common::descriptor::{
3    Attribuable, Attributes, Buildable, Context, Documented, Generic, Generics, Identified,
4    Identifier, Input, Model, Output, Parameter, Parameterized, Treatment as TreatmentDescriptor,
5    TreatmentBuildMode,
6};
7use once_cell::sync::OnceCell;
8use std::collections::HashMap;
9use std::iter::FromIterator;
10use std::sync::{Arc, Weak};
11
12#[derive(Debug)]
13pub struct Source {
14    identifier: Identifier,
15    #[cfg(feature = "doc")]
16    documentation: String,
17    attributes: Attributes,
18    models: HashMap<String, Arc<dyn Model>>,
19    parameters: HashMap<String, Parameter>,
20    outputs: HashMap<String, Output>,
21    source_from: HashMap<String, Vec<String>>,
22    auto_reference: Weak<Self>,
23}
24
25impl Source {
26    pub fn new(
27        identifier: Identifier,
28        documentation: String,
29        attributes: Attributes,
30        models: Vec<(String, Arc<dyn Model>)>,
31        parameters: Vec<Parameter>,
32        source_from: Vec<(String, Vec<String>)>,
33        outputs: Vec<Output>,
34    ) -> Arc<Self> {
35        #[cfg(not(feature = "doc"))]
36        let _ = documentation;
37        Arc::new_cyclic(|me| Self {
38            identifier,
39            #[cfg(feature = "doc")]
40            documentation,
41            attributes,
42            models: HashMap::from_iter(models.into_iter().map(|(n, m)| (n.to_string(), m))),
43            parameters: HashMap::from_iter(
44                parameters.into_iter().map(|p| (p.name().to_string(), p)),
45            ),
46            outputs: HashMap::from_iter(outputs.into_iter().map(|o| (o.name().to_string(), o))),
47            source_from: HashMap::from_iter(source_from.into_iter()),
48            auto_reference: me.clone(),
49        })
50    }
51}
52
53impl Attribuable for Source {
54    fn attributes(&self) -> &Attributes {
55        &self.attributes
56    }
57}
58
59impl Identified for Source {
60    fn identifier(&self) -> &Identifier {
61        &self.identifier
62    }
63
64    fn make_use(&self, identifier: &Identifier) -> bool {
65        self.models
66            .iter()
67            .any(|(_, model)| model.identifier() == identifier || model.make_use(identifier))
68            || self.outputs.values().any(|output| {
69                output
70                    .described_type()
71                    .final_type()
72                    .data()
73                    .map(|data| data.identifier() == identifier || data.make_use(identifier))
74                    .unwrap_or(false)
75            })
76            || self.parameters.values().any(|parameter| {
77                parameter
78                    .described_type()
79                    .final_type()
80                    .data()
81                    .map(|data| data.identifier() == identifier || data.make_use(identifier))
82                    .unwrap_or(false)
83            })
84    }
85
86    fn uses(&self) -> Vec<Identifier> {
87        let mut uses = Vec::new();
88        self.models.values().for_each(|model| {
89            uses.push(model.identifier().clone());
90            uses.extend(model.uses());
91        });
92        self.outputs.values().for_each(|output| {
93            if let Some(data) = output.described_type().final_type().data() {
94                uses.push(data.identifier().clone());
95                uses.extend(data.uses());
96            }
97        });
98        self.parameters.values().for_each(|parameter| {
99            if let Some(data) = parameter.described_type().final_type().data() {
100                uses.push(data.identifier().clone());
101                uses.extend(data.uses());
102            }
103        });
104        uses
105    }
106}
107
108impl Documented for Source {
109    fn documentation(&self) -> &str {
110        #[cfg(feature = "doc")]
111        {
112            &self.documentation
113        }
114        #[cfg(not(feature = "doc"))]
115        {
116            &""
117        }
118    }
119}
120
121impl Parameterized for Source {
122    fn parameters(&self) -> &HashMap<String, Parameter> {
123        &self.parameters
124    }
125
126    fn as_identified(&self) -> Arc<dyn Identified> {
127        self.auto_reference.upgrade().unwrap()
128    }
129}
130
131impl Buildable<TreatmentBuildMode> for Source {
132    fn build_mode(&self) -> TreatmentBuildMode {
133        TreatmentBuildMode::Source(self.auto_reference.clone())
134    }
135}
136
137impl Display for Source {
138    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
139        write!(f, "treatment {}", self.identifier.to_string())?;
140
141        if !self.models.is_empty() {
142            write!(
143                f,
144                "[{}]",
145                self.models
146                    .iter()
147                    .map(|(n, m)| format!("{}: {}", n, m.identifier().to_string()))
148                    .collect::<Vec<_>>()
149                    .join(", "),
150            )?;
151        }
152
153        write!(
154            f,
155            "({})",
156            self.parameters()
157                .iter()
158                .map(|(_, p)| p.to_string())
159                .collect::<Vec<_>>()
160                .join(", ")
161        )?;
162
163        Ok(())
164    }
165}
166
167impl TreatmentDescriptor for Source {
168    fn inputs(&self) -> &HashMap<String, Input> {
169        static HASHMAP: OnceCell<HashMap<String, Input>> = OnceCell::new();
170        HASHMAP.get_or_init(|| HashMap::new())
171    }
172
173    fn outputs(&self) -> &HashMap<String, Output> {
174        &self.outputs
175    }
176
177    fn models(&self) -> &HashMap<String, Arc<dyn Model>> {
178        &self.models
179    }
180
181    fn contexts(&self) -> &HashMap<String, Arc<dyn Context>> {
182        static HASHMAP: OnceCell<HashMap<String, Arc<dyn Context>>> = OnceCell::new();
183        HASHMAP.get_or_init(|| HashMap::new())
184    }
185
186    fn source_from(&self) -> &HashMap<String, Vec<String>> {
187        &self.source_from
188    }
189
190    fn as_identified(&self) -> Arc<dyn Identified> {
191        self.auto_reference.upgrade().unwrap()
192    }
193
194    fn as_buildable(&self) -> Arc<dyn Buildable<TreatmentBuildMode>> {
195        self.auto_reference.upgrade().unwrap()
196    }
197
198    fn as_parameterized(&self) -> Arc<dyn Parameterized> {
199        self.auto_reference.upgrade().unwrap()
200    }
201}
202
203impl Generics for Source {
204    fn generics(&self) -> &Vec<Generic> {
205        static VEC: OnceCell<Vec<Generic>> = OnceCell::new();
206        VEC.get_or_init(|| Vec::new())
207    }
208}