From 28564b11bde31a7ba3b0468bfb0ecf813fb44ae5 Mon Sep 17 00:00:00 2001 From: brnrs Date: Fri, 17 Apr 2020 15:30:38 +0200 Subject: [PATCH] WIP: contexts --- src/contexts/component.rs | 38 ++++++++++++ src/contexts/component_map.rs | 28 +++++++++ src/contexts/mod.rs | 3 + src/contexts/model_i.rs | 111 ++++++++++++++++++++++++++++++++++ src/main.rs | 2 + 5 files changed, 182 insertions(+) create mode 100644 src/contexts/component.rs create mode 100644 src/contexts/component_map.rs create mode 100644 src/contexts/mod.rs create mode 100644 src/contexts/model_i.rs diff --git a/src/contexts/component.rs b/src/contexts/component.rs new file mode 100644 index 0000000..0b90dc6 --- /dev/null +++ b/src/contexts/component.rs @@ -0,0 +1,38 @@ +use std::any::{Any, TypeId, type_name}; +use std::convert::TryFrom; +use std::cell::RefCell; +use std::ops::Deref; +use std::rc::Rc; + +#[derive(Clone)] +pub struct Component(Rc>); + +impl Deref for Component { + type Target = RefCell; + + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} + +#[allow(dead_code)] +impl Component { + pub fn from(t: T) -> Component { + Component(Rc::new(RefCell::new(t))) + } + + pub fn type_id() -> TypeId { + TypeId::of::() + } + + pub fn type_name() -> &'static str { + type_name::() + } +} + +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_map.rs b/src/contexts/component_map.rs new file mode 100644 index 0000000..a935d63 --- /dev/null +++ b/src/contexts/component_map.rs @@ -0,0 +1,28 @@ +use std::any::{Any, TypeId}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::convert::TryInto; +use std::rc::Rc; + +use super::component::Component; + +pub struct ComponentMap(HashMap>); + +#[allow(dead_code)] +impl ComponentMap { + pub fn new() -> ComponentMap { + ComponentMap(HashMap::new()) + } + + pub fn contains(&self) -> bool { + self.0.contains_key(&TypeId::of::()) + } + + pub fn get(&self) -> Option> { + 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))); + } +} diff --git a/src/contexts/mod.rs b/src/contexts/mod.rs new file mode 100644 index 0000000..b6acac3 --- /dev/null +++ b/src/contexts/mod.rs @@ -0,0 +1,3 @@ +mod model_i; +mod component; +mod component_map; diff --git a/src/contexts/model_i.rs b/src/contexts/model_i.rs new file mode 100644 index 0000000..7788a97 --- /dev/null +++ b/src/contexts/model_i.rs @@ -0,0 +1,111 @@ +use std::any::Any; + +use super::component::*; +use super::component_map::*; + +#[allow(dead_code)] +struct Context<'t> { + map: ComponentMap, + base_context: Option<&'t Context<'t>>, +} + +#[allow(dead_code)] +impl<'t> Context<'t> { + fn new() -> Context<'t> { + Context { + map: ComponentMap::new(), + base_context: None, + } + } + + fn get(&self) -> Option> { + match self.map.get() { + component @ Some(_) => component, + _ => match self.base_context { + Some(context) => context.get(), + None => None, + }, + } + } + + fn set(&mut self, component: T) { + self.map.set(component) + } + + fn subcontext(&self) -> Context { + let mut context = Context::new(); + context.base_context = Some(self); + context + } +} + +trait FromContext: Sized { + fn from(context: &Context) -> Option; +} + +impl FromContext for Component { + fn from(context: &Context) -> Option { + context.get() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn get_from_context() { + // Given + #[derive(Debug, Eq, PartialEq)] + struct TestStruct(&'static str); + let context = { + let mut tmp = Context::new(); + tmp.set(TestStruct("hello")); + tmp + }; + + // When + let test_struct = context.get::().unwrap(); + + // Then + assert_eq!(*test_struct.borrow(), TestStruct("hello")); + } + + #[test] + fn get_from_base_context() { + // Given + #[derive(Debug, Eq, PartialEq)] + struct TestStruct(&'static str); + let context = { + let mut tmp = Context::new(); + tmp.set(TestStruct("hello")); + tmp + }; + let subcontext = context.subcontext(); + + // When + let test_struct = subcontext.get::().unwrap(); + + // Then + assert_eq!(*test_struct.borrow(), TestStruct("hello")); + } + + #[test] + fn get_from_subcontext() { + // Given + #[derive(Debug, Eq, PartialEq)] + struct TestStruct(&'static str); + let context = Context::new(); + let subcontext = { + let mut tmp = context.subcontext(); + tmp.set(TestStruct("hello")); + tmp + }; + + // When + let test_struct = subcontext.get::().unwrap(); + + // Then + assert_eq!(*test_struct.borrow(), TestStruct("hello")); + } +} diff --git a/src/main.rs b/src/main.rs index e29f1ce..e708f17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![feature(trait_alias, option_unwrap_none)] mod battle; mod context; +mod contexts; use battle::actor::*; use battle::base::*; @@ -8,6 +9,7 @@ use battle::skill::*; use battle::uic::Uic; use context::Context; + fn main() { println!("Hello, world!");