melodium_core/descriptor/
model.rs1use core::fmt::{Display, Formatter, Result};
2use melodium_common::descriptor::{
3 Attribuable, Attributes, Buildable, Context, Documented, Generic, Generics, Identified,
4 Identifier, Model as ModelDescriptor, ModelBuildMode, Parameter, Parameterized,
5};
6use melodium_common::executive::{Model as ExecutiveModel, World};
7use once_cell::sync::OnceCell;
8use std::collections::HashMap;
9use std::iter::FromIterator;
10use std::sync::{Arc, Weak};
11
12#[derive(Debug)]
13pub struct Model {
14 identifier: Identifier,
15 #[cfg(feature = "doc")]
16 documentation: String,
17 attributes: Attributes,
18 parameters: HashMap<String, Parameter>,
19 sources: HashMap<String, Vec<Arc<dyn Context>>>,
20 build_fn: fn(Arc<dyn World>) -> Arc<dyn ExecutiveModel>,
21 auto_reference: Weak<Self>,
22}
23
24impl Model {
25 pub fn new(
26 identifier: Identifier,
27 documentation: String,
28 attributes: Attributes,
29 parameters: Vec<Parameter>,
30 sources: Vec<(String, Vec<Arc<dyn Context>>)>,
31 build_fn: fn(Arc<dyn World>) -> Arc<dyn ExecutiveModel>,
32 ) -> Arc<Self> {
33 #[cfg(not(feature = "doc"))]
34 let _ = documentation;
35 Arc::new_cyclic(|me| Self {
36 identifier,
37 #[cfg(feature = "doc")]
38 documentation,
39 attributes,
40 parameters: HashMap::from_iter(
41 parameters.into_iter().map(|p| (p.name().to_string(), p)),
42 ),
43 sources: HashMap::from_iter(sources.into_iter()),
44 build_fn,
45 auto_reference: me.clone(),
46 })
47 }
48}
49
50impl Attribuable for Model {
51 fn attributes(&self) -> &Attributes {
52 &self.attributes
53 }
54}
55
56impl Identified for Model {
57 fn identifier(&self) -> &Identifier {
58 &self.identifier
59 }
60
61 fn make_use(&self, identifier: &Identifier) -> bool {
62 self.parameters.values().any(|parameter| {
63 parameter
64 .described_type()
65 .final_type()
66 .data()
67 .map(|data| data.identifier() == identifier || data.make_use(identifier))
68 .unwrap_or(false)
69 }) || self.sources.iter().any(|(_, contextes)| {
70 contextes
71 .iter()
72 .any(|context| context.identifier() == identifier)
73 })
74 }
75
76 fn uses(&self) -> Vec<Identifier> {
77 let mut uses = Vec::new();
78 self.parameters.values().for_each(|parameter| {
79 if let Some(data) = parameter.described_type().final_type().data() {
80 uses.push(data.identifier().clone());
81 uses.extend(data.uses());
82 }
83 });
84 self.sources.values().for_each(|contexts| {
85 for context in contexts {
86 uses.push(context.identifier().clone());
87 uses.extend(context.uses());
88 }
89 });
90 uses
91 }
92}
93
94impl Documented for Model {
95 fn documentation(&self) -> &str {
96 #[cfg(feature = "doc")]
97 {
98 &self.documentation
99 }
100 #[cfg(not(feature = "doc"))]
101 {
102 &""
103 }
104 }
105}
106
107impl Parameterized for Model {
108 fn parameters(&self) -> &HashMap<String, Parameter> {
109 &self.parameters
110 }
111
112 fn as_identified(&self) -> Arc<dyn Identified> {
113 self.auto_reference.upgrade().unwrap()
114 }
115}
116
117impl Generics for Model {
118 fn generics(&self) -> &Vec<Generic> {
119 static VEC: OnceCell<Vec<Generic>> = OnceCell::new();
120 VEC.get_or_init(|| Vec::new())
121 }
122}
123
124impl Buildable<ModelBuildMode> for Model {
125 fn build_mode(&self) -> ModelBuildMode {
126 ModelBuildMode::Compiled(self.build_fn)
127 }
128}
129
130impl Display for Model {
131 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
132 write!(
133 f,
134 "model {}({})",
135 self.identifier.to_string(),
136 self.parameters
137 .iter()
138 .map(|(_, p)| p.to_string())
139 .collect::<Vec<_>>()
140 .join(", "),
141 )?;
142
143 Ok(())
144 }
145}
146
147impl ModelDescriptor for Model {
148 fn is_core_model(&self) -> bool {
149 true
150 }
151
152 fn base_model(&self) -> Option<Arc<dyn ModelDescriptor>> {
153 None
154 }
155
156 fn sources(&self) -> &HashMap<String, Vec<Arc<dyn Context>>> {
157 &self.sources
158 }
159
160 fn as_identified(&self) -> Arc<dyn Identified> {
161 self.auto_reference.upgrade().unwrap()
162 }
163
164 fn as_buildable(&self) -> Arc<dyn Buildable<ModelBuildMode>> {
165 self.auto_reference.upgrade().unwrap()
166 }
167
168 fn as_parameterized(&self) -> Arc<dyn Parameterized> {
169 self.auto_reference.upgrade().unwrap()
170 }
171}