use crate::{
core::{
parking_lot::{Mutex, MutexGuard},
uuid::Uuid,
SafeLock, TypeUuidProvider,
},
script::{Script, ScriptTrait},
};
use std::collections::BTreeMap;
pub struct ScriptConstructor {
pub constructor: Box<dyn FnMut() -> Script + Send>,
pub name: String,
pub source_path: &'static str,
pub assembly_name: &'static str,
}
#[derive(Default)]
pub struct ScriptConstructorContainer {
map: Mutex<BTreeMap<Uuid, ScriptConstructor>>,
}
impl ScriptConstructorContainer {
pub fn new() -> Self {
ScriptConstructorContainer::default()
}
pub fn add<T>(&self, name: &str) -> &Self
where
T: TypeUuidProvider + ScriptTrait + Default,
{
let old = self.map.safe_lock().insert(
T::type_uuid(),
ScriptConstructor {
constructor: Box::new(|| Script::new(T::default())),
name: name.to_owned(),
source_path: T::source_path(),
assembly_name: T::type_assembly_name(),
},
);
assert!(old.is_none());
self
}
pub fn add_custom(
&self,
type_uuid: Uuid,
constructor: ScriptConstructor,
) -> Result<(), String> {
let mut map = self.map.safe_lock();
if let Some(old) = map.get(&type_uuid) {
return Err(format!(
"cannot add {} ({}) because its uuid is already used by {} ({})",
constructor.name, constructor.assembly_name, old.name, old.assembly_name
));
}
map.insert(type_uuid, constructor);
Ok(())
}
pub fn remove(&self, type_uuid: Uuid) {
self.map.safe_lock().remove(&type_uuid);
}
pub fn try_create(&self, type_uuid: &Uuid) -> Option<Script> {
self.map
.safe_lock()
.get_mut(type_uuid)
.map(|c| (c.constructor)())
}
pub fn map(&self) -> MutexGuard<BTreeMap<Uuid, ScriptConstructor>> {
self.map.safe_lock()
}
}