use crate::{Attributes, DescribedType, Identifier, SharingError, SharingResult, Value};
use melodium_common::descriptor::{Collection, Identified, Identifier as CommonIdentifier};
use melodium_engine::{
descriptor::Treatment as DesignedTreatment,
design::{Parameter as DesignedParameter, TreatmentInstanciation},
LogicError,
};
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "webassembly", derive(tsify::Tsify))]
#[cfg_attr(feature = "webassembly", tsify(into_wasm_abi, from_wasm_abi))]
pub struct TreatmentInstanciationDesign {
pub identifier: Identifier,
pub generics: BTreeMap<String, DescribedType>,
pub models: BTreeMap<String, String>,
pub parameters: BTreeMap<String, Value>,
pub attributes: Attributes,
}
impl TreatmentInstanciationDesign {
pub(crate) fn make_design(
&self,
collection: &Collection,
scope: &Arc<DesignedTreatment>,
name: &str,
) -> SharingResult<TreatmentInstanciation> {
let mut result = SharingResult::new_success(());
let identifier: CommonIdentifier = if let Ok(identifier) = (&self.identifier).try_into() {
identifier
} else {
return SharingResult::new_failure(SharingError::invalid_identifier(
17,
self.identifier.clone(),
));
};
let treatment = if let Some(melodium_common::descriptor::Entry::Treatment(treatment)) =
collection.get(&(&identifier).into())
{
treatment
} else {
return SharingResult::new_failure(
LogicError::unexisting_treatment(
241,
scope.identifier().clone(),
identifier.into(),
None,
)
.into(),
);
};
let mut generics = HashMap::with_capacity(self.generics.len());
for (name, described_type) in &self.generics {
if let Some(described_type) = result.merge_degrade_failure(
described_type.to_described_type(collection, scope.identifier()),
) {
generics.insert(name.clone(), described_type);
}
}
let mut parameters = HashMap::with_capacity(self.parameters.len());
for (name, value) in &self.parameters {
if let Some(value) =
result.merge_degrade_failure(value.to_value(collection, scope.identifier()))
{
parameters.insert(
name.clone(),
DesignedParameter {
name: name.clone(),
value,
},
);
}
}
result.and_then(|_| {
SharingResult::new_success(TreatmentInstanciation {
descriptor: Arc::downgrade(treatment),
name: name.to_string(),
attributes: (&self.attributes).into(),
models: self
.models
.iter()
.map(|(param_name, local_name)| (param_name.clone(), local_name.clone()))
.collect(),
generics,
parameters,
})
})
}
}
impl From<&TreatmentInstanciation> for TreatmentInstanciationDesign {
fn from(value: &TreatmentInstanciation) -> Self {
Self {
identifier: value.descriptor.upgrade().unwrap().identifier().into(),
generics: value
.generics
.iter()
.map(|(name, dt)| (name.clone(), dt.into()))
.collect(),
models: value
.models
.iter()
.map(|(param_name, local_name)| (param_name.clone(), local_name.clone()))
.collect(),
parameters: value
.parameters
.iter()
.map(|(name, param)| (name.clone(), (¶m.value).into()))
.collect(),
attributes: (&value.attributes).into(),
}
}
}