Skip to content
Extraits de code Groupes Projets
Non vérifiée Valider 4af1f65d rédigé par Kubat's avatar Kubat
Parcourir les fichiers

Organise the Spell things

parent 15601e54
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
#[derive(Debug, thiserror::Error)]
pub enum SpellError {}
pub enum SpellError {
#[error("Already defined spell '{0}': {1}")]
Redefined(&'static str, &'static str),
#[error("Undefined spell '{0}'")]
Undefined(String),
}
pub struct SpellArguments {}
use crate::{
error::SpellError,
spell::{BuildableSpell, Spell, SpellArguments},
};
use std::collections::HashMap;
/// The builder function, call it with some arguments to try to build the spell
pub type SpellBuilderFunction = fn(SpellArguments) -> Result<Box<dyn Spell>, SpellError>;
/// The spell factory, you have to register the spell before trying to create them.
#[derive(Debug, Default)]
pub struct SpellFactory {
/// The dispatch map, to get a builder by an associated spell name.
dispatch: HashMap<&'static str, SpellBuilderFunction>,
}
impl SpellFactory {
/// Get the list of all registered spells.
pub fn get_registered_spells(&self) -> impl Iterator<Item = &'static str> {
self.dispatch.keys().copied()
}
/// Register a spell into the factory. In case of re-registering returns an [Err].
pub fn register<Sp: BuildableSpell + 'static>(&mut self) -> Result<(), SpellError> {
Sp::name_list().try_for_each(|name| match self.dispatch.entry(name) {
std::collections::hash_map::Entry::Occupied(_) => Err(SpellError::Redefined(
Sp::name(),
"name or alias was already registered",
)),
std::collections::hash_map::Entry::Vacant(entry) => {
_ = entry.insert(Sp::create);
Ok(())
}
})
}
/// Get the builder of a [Spell] by its name. In case of undefined [Spell], returns an [Err].
pub fn get_builder(&self, name: impl AsRef<str>) -> Result<SpellBuilderFunction, SpellError> {
self.dispatch
.get(name.as_ref())
.copied()
.ok_or(SpellError::Undefined(name.as_ref().to_string()))
}
}
mod factory;
mod arguments;
mod traits;
pub use factory::*;
pub use arguments::*;
pub use traits::*;
use crate::{error::SpellError, state::State};
use crate::{error::SpellError, spell::SpellArguments, state::State};
pub trait Spell {
fn cast(&self, state: State) -> Result<State, SpellError>;
......@@ -6,9 +6,10 @@ pub trait Spell {
fn uncast(&self, state: State) -> Result<State, SpellError>;
}
pub struct SpellArguments {}
pub trait BuildableSpell: Spell + TryFrom<SpellArguments, Error = SpellError> {
pub trait BuildableSpell
where
Self: Spell + TryFrom<SpellArguments, Error = SpellError> + 'static,
{
fn name() -> &'static str;
fn aliases() -> &'static [&'static str] {
......@@ -21,34 +22,9 @@ pub trait BuildableSpell: Spell + TryFrom<SpellArguments, Error = SpellError> {
.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)
fn create(arguments: SpellArguments) -> Result<Box<dyn Spell>, SpellError> {
Self::try_from(arguments)
.map(Box::new)
.map(|boxed| boxed as Box<dyn Spell>)
}
}
pub struct State {
}
pub struct State {}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter