From 15601e54a3333399cf0f9d0fce561712dbdc7c56 Mon Sep 17 00:00:00 2001
From: Kubat <maelle.martin@proton.me>
Date: Fri, 18 Apr 2025 20:36:17 +0200
Subject: [PATCH] Just trying an API for the Spell/SpellFactory

---
 Cargo.lock                         |  1 +
 grimoire_engine_types/Cargo.toml   |  1 +
 grimoire_engine_types/src/error.rs |  2 ++
 grimoire_engine_types/src/lib.rs   |  3 ++
 grimoire_engine_types/src/spell.rs | 54 ++++++++++++++++++++++++++++++
 grimoire_engine_types/src/state.rs |  2 ++
 6 files changed, 63 insertions(+)
 create mode 100644 grimoire_engine_types/src/error.rs
 create mode 100644 grimoire_engine_types/src/spell.rs
 create mode 100644 grimoire_engine_types/src/state.rs

diff --git a/Cargo.lock b/Cargo.lock
index 894aafd..9366642 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 637d58e..a7c6bce 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 0000000..482b170
--- /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 e69de29..46bc08d 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 0000000..8db3e85
--- /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 0000000..815e4be
--- /dev/null
+++ b/grimoire_engine_types/src/state.rs
@@ -0,0 +1,2 @@
+pub struct State {
+}
-- 
GitLab