diff --git a/Cargo.lock b/Cargo.lock index 894aafdb1ab35ed6fd3c905568ec9749d947f39f..9366642865089914ba331c8647ed52b2155c9f0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,6 +366,7 @@ dependencies = [ "log", "paste", "serde", + "thiserror", ] [[package]] diff --git a/grimoire_engine_types/Cargo.toml b/grimoire_engine_types/Cargo.toml index 637d58e0800bb08cda725282b4b41883f6b5f715..a7c6bce469c0ed65c650ee008191659a8b30ca13 100644 --- a/grimoire_engine_types/Cargo.toml +++ b/grimoire_engine_types/Cargo.toml @@ -15,3 +15,4 @@ paste.workspace = true serde.workspace = true hashbrown.workspace = true log.workspace = true +thiserror.workspace = true diff --git a/grimoire_engine_types/src/error.rs b/grimoire_engine_types/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..482b1706099d59407254425bcf211b15de40f615 --- /dev/null +++ b/grimoire_engine_types/src/error.rs @@ -0,0 +1,2 @@ +#[derive(Debug, thiserror::Error)] +pub enum SpellError {} diff --git a/grimoire_engine_types/src/lib.rs b/grimoire_engine_types/src/lib.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..46bc08dfe30f0d9858f04de2a36dc136db55a584 100644 --- a/grimoire_engine_types/src/lib.rs +++ b/grimoire_engine_types/src/lib.rs @@ -0,0 +1,3 @@ +pub mod spell; +pub mod state; +pub mod error; diff --git a/grimoire_engine_types/src/spell.rs b/grimoire_engine_types/src/spell.rs new file mode 100644 index 0000000000000000000000000000000000000000..8db3e85ab9ed0d14d4120cdc82ab5007662e2f25 --- /dev/null +++ b/grimoire_engine_types/src/spell.rs @@ -0,0 +1,54 @@ +use crate::{error::SpellError, state::State}; + +pub trait Spell { + fn cast(&self, state: State) -> Result<State, SpellError>; + + fn uncast(&self, state: State) -> Result<State, SpellError>; +} + +pub struct SpellArguments {} + +pub trait BuildableSpell: Spell + TryFrom<SpellArguments, Error = SpellError> { + fn name() -> &'static str; + + fn aliases() -> &'static [&'static str] { + &[] + } + + fn name_list() -> impl Iterator<Item = &'static str> { + [Self::name()] + .into_iter() + .chain(Self::aliases().iter().copied()) + } + + fn create(arguments: SpellArguments) -> Result<Box<dyn Spell>, SpellError>; +} + +type SpellBuilderFunction = fn(SpellArguments) -> Result<Box<dyn Spell>, SpellError>; + +#[derive(Debug, Default)] +pub struct SpellFactory { + dispatch: hashbrown::HashMap<&'static str, SpellBuilderFunction>, +} + +impl SpellFactory { + pub fn register<Spell: BuildableSpell + 'static>(&mut self) -> Result<(), SpellError> { + Spell::name_list() + .find(|spell_name| self.dispatch.contains_key(spell_name)) + .map(|_name| -> Result<(), SpellError> { todo!("error") }) + .unwrap_or(Ok(()))?; + + Spell::name_list().for_each(|name| _ = self.dispatch.insert(name, Spell::create)); + + Ok(()) + } + + pub fn try_build_spell( + &self, + name: &str, + arguments: SpellArguments, + ) -> Result<Box<dyn Spell>, SpellError> { + let builder_function = self.dispatch.get(name).ok_or_else(|| todo!("error"))?; + builder_function(arguments) + } +} diff --git a/grimoire_engine_types/src/state.rs b/grimoire_engine_types/src/state.rs new file mode 100644 index 0000000000000000000000000000000000000000..815e4be480ea4e1d739caa5873ebe2b950287fee --- /dev/null +++ b/grimoire_engine_types/src/state.rs @@ -0,0 +1,2 @@ +pub struct State { +}