melodium_core/descriptor/
source.rs1use 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}