From 28d5069b02dfcc03e7a9b803418557c15b219520 Mon Sep 17 00:00:00 2001 From: brnrs Date: Fri, 17 Apr 2020 19:53:20 +0200 Subject: [PATCH] component factories + formatting --- src/battle/mod.rs | 15 ++--- src/contexts/component.rs | 12 ++-- src/contexts/component_factory.rs | 97 ++++++++++++++++++++++++++++++- src/contexts/component_map.rs | 8 ++- src/contexts/mod.rs | 4 +- src/contexts/model_i.rs | 6 +- src/main.rs | 1 - 7 files changed, 119 insertions(+), 24 deletions(-) diff --git a/src/battle/mod.rs b/src/battle/mod.rs index 7635343..46407b8 100644 --- a/src/battle/mod.rs +++ b/src/battle/mod.rs @@ -161,16 +161,17 @@ fn check_result(context: &Context) -> Option { let team_db = context.get::().unwrap(); let actor_state_db = context.get::().unwrap(); + let is_alive = |actor_id: &u32| { + if let ActorState::Dead = actor_state_db.get(*actor_id).unwrap() { + false + } else { + true + } + }; let alive: Vec = team_db .iter() .filter_map(|(team_id, team)| { - if team.actors.iter().any(|actor_id| { - if let ActorState::Dead = actor_state_db.get(*actor_id).unwrap() { - false - } else { - true - } - }) { + if team.actors.iter().any(is_alive) { Some(*team_id) } else { None diff --git a/src/contexts/component.rs b/src/contexts/component.rs index 0b90dc6..a481f2e 100644 --- a/src/contexts/component.rs +++ b/src/contexts/component.rs @@ -1,13 +1,13 @@ -use std::any::{Any, TypeId, type_name}; -use std::convert::TryFrom; +use std::any::{type_name, Any, TypeId}; use std::cell::RefCell; +use std::convert::TryFrom; use std::ops::Deref; use std::rc::Rc; #[derive(Clone)] pub struct Component(Rc>); -impl Deref for Component { +impl Deref for Component { type Target = RefCell; fn deref(&self) -> &Self::Target { @@ -16,7 +16,7 @@ impl Deref for Component { } #[allow(dead_code)] -impl Component { +impl Component { pub fn from(t: T) -> Component { Component(Rc::new(RefCell::new(t))) } @@ -30,9 +30,9 @@ impl Component { } } -impl TryFrom> for Component { +impl TryFrom> for Component { type Error = Rc; fn try_from(rc: Rc) -> Result, Self::Error> { Ok(Component(rc.downcast::>()?)) } -} \ No newline at end of file +} diff --git a/src/contexts/component_factory.rs b/src/contexts/component_factory.rs index bf1a3b9..a3c51e7 100644 --- a/src/contexts/component_factory.rs +++ b/src/contexts/component_factory.rs @@ -1,7 +1,7 @@ use super::component::Component; use super::model_i::{Context, FromContext}; -use std::any::{Any, type_name}; +use std::any::{type_name, Any}; trait ComponentFactory { type Input; @@ -14,11 +14,102 @@ trait ContextComponentFactory: ComponentFactory { fn build_from_context(&self, context: &Context) -> Result; } -impl , Output=O>> ContextComponentFactory for CF { +impl, Output = O>> + ContextComponentFactory for CF +{ fn build_from_context(&self, context: &Context) -> Result { - let input = FromContext::from(context).ok_or_else(|| format!("Could not find retrieve component of type {} from context", type_name::()))?; + let input = FromContext::from(context).ok_or_else(|| { + format!( + "Could not find retrieve component of type {} from context", + type_name::() + ) + })?; self.build(input) } } +#[macro_export] +macro_rules! derive_ccf { + ($CF:ty; $( $T:ty ),* ) => { + impl ContextComponentFactory for $CF { + fn build_from_context(&self, context: &Context) -> Result { + let input = from_context!(context; $($T),*); + self.build(input) + } + } + } +} + +#[macro_export] +macro_rules! from_context { + ($context:expr; $( $T:ty ),* ) => { + ( + $( + FromContext::from($context).ok_or_else(|| { + format!( + "Could not find retrieve component of type {} from context", + type_name::<$T>() + ) + })?, + )* + ) + + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, Eq, PartialEq)] + struct A(&'static str); + #[derive(Debug, Eq, PartialEq)] + struct B(u32); + + #[test] + fn test_from_context_macro() { + // Given + fn get_input(context: &Context) -> Result<(Component, Component), String> { + Ok(from_context!(context; A, B)) + } + + let mut context = Context::new(); + context.set(A("Test")); + context.set(B(67)); + + // When + let (comp_a, comp_b) = get_input(&context).unwrap(); + // Then + assert_eq!(*comp_a.borrow(), A("Test")); + assert_eq!(*comp_b.borrow(), B(67)); + } + + #[derive(Debug, Eq, PartialEq)] + struct C(&'static str, u32); + + struct CFactory; + impl ComponentFactory for CFactory { + type Input = (Component, Component); + type Output = C; + + fn build(&self, (comp_a, comp_b): Self::Input) -> Result { + Ok(C(comp_a.borrow().0, comp_b.borrow().0)) + } + } + + #[test] + fn test_derive_ccf_macro() { + // Given + derive_ccf!(CFactory; A, B); + let c_factory = CFactory; + let mut context = Context::new(); + context.set(A("test")); + context.set(B(67)); + + // When + let c = c_factory.build_from_context(&context).unwrap(); + + assert_eq!(c, C("test", 67)); + } +} diff --git a/src/contexts/component_map.rs b/src/contexts/component_map.rs index a935d63..08b9335 100644 --- a/src/contexts/component_map.rs +++ b/src/contexts/component_map.rs @@ -19,10 +19,14 @@ impl ComponentMap { } pub fn get(&self) -> Option> { - self.0.get(&TypeId::of::()).cloned().map(|c| c.try_into().unwrap()) + self.0 + .get(&TypeId::of::()) + .cloned() + .map(|c| c.try_into().unwrap()) } pub fn set(&mut self, component: T) { - self.0.insert(TypeId::of::(), Rc::new(RefCell::new(component))); + self.0 + .insert(TypeId::of::(), Rc::new(RefCell::new(component))); } } diff --git a/src/contexts/mod.rs b/src/contexts/mod.rs index 812c77a..4ef008c 100644 --- a/src/contexts/mod.rs +++ b/src/contexts/mod.rs @@ -1,4 +1,4 @@ -mod model_i; mod component; -mod component_map; mod component_factory; +mod component_map; +mod model_i; diff --git a/src/contexts/model_i.rs b/src/contexts/model_i.rs index b1806d0..82135c5 100644 --- a/src/contexts/model_i.rs +++ b/src/contexts/model_i.rs @@ -43,7 +43,7 @@ pub trait FromContext: Sized { fn from(context: &Context) -> Option; } -impl FromContext for Component { +impl FromContext for Component { fn from(context: &Context) -> Option { context.get() } @@ -96,8 +96,8 @@ mod tests { #[derive(Debug, Eq, PartialEq)] struct TestStruct(&'static str); let context = Context::new(); - let subcontext = { - let mut tmp = context.subcontext(); + let subcontext = { + let mut tmp = context.subcontext(); tmp.set(TestStruct("hello")); tmp }; diff --git a/src/main.rs b/src/main.rs index e708f17..4d31b2f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,6 @@ use battle::skill::*; use battle::uic::Uic; use context::Context; - fn main() { println!("Hello, world!");