melodium_core/descriptor/
model.rs

1use 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}