extern crate shred;
use std::collections::HashMap;
use shred::{Accessor, AccessorCow, CastFrom, DispatcherBuilder, DynamicSystemData, MetaTable, Read, Resource,
ResourceId, Resources,
System, SystemData};
use shred::cell::{Ref, RefMut};
struct Dependencies {
reads: Vec<ResourceId>,
writes: Vec<ResourceId>,
}
impl Accessor for Dependencies {
fn try_new() -> Option<Self> {
None
}
fn reads(&self) -> Vec<ResourceId> {
let mut reads = self.reads.clone();
reads.push(ResourceId::new::<ReflectionTable>());
reads
}
fn writes(&self) -> Vec<ResourceId> {
self.writes.clone()
}
}
struct DynamicSystem {
dependencies: Dependencies,
script: fn(ScriptInput),
}
impl<'a> System<'a> for DynamicSystem {
type SystemData = ScriptSystemData<'a>;
fn run(&mut self, mut data: Self::SystemData) {
let meta = data.meta_table;
let reads: Vec<&Reflection> = data.reads.iter().map(|resource| {
let res = Box::as_ref(resource);
meta.get(res).expect("Not registered in meta table")
}).collect();
let writes: Vec<&mut Reflection> = data.writes.iter_mut().map(|resource| {
let res = Box::as_mut(resource);
let res: &mut Reflection = meta.get_mut(res).expect("Not registered in meta table");
res
}).collect();
let input = ScriptInput {
reads,
writes,
};
(self.script)(input);
}
fn accessor<'b>(&'b self) -> AccessorCow<'a, 'b, Self> {
AccessorCow::Ref(&self.dependencies)
}
fn setup(&mut self, _res: &mut Resources) {
}
}
trait Reflection {
fn call_method(&self, s: &str);
}
impl<T> CastFrom<T> for Reflection
where
T: Reflection + 'static,
{
fn cast(t: &T) -> &Self {
t
}
fn cast_mut(t: &mut T) -> &mut Self {
t
}
}
type ReflectionTable = MetaTable<Reflection>;
struct ResourceTable {
map: HashMap<String, ResourceId>,
}
impl ResourceTable {
fn new() -> Self {
ResourceTable {
map: HashMap::default(),
}
}
fn register<T: Resource>(&mut self, name: &str) {
self.map.insert(name.to_owned(), ResourceId::new::<T>());
}
fn get(&self, name: &str) -> ResourceId {
*self.map.get(name).unwrap()
}
}
struct ScriptInput<'a> {
reads: Vec<&'a Reflection>,
writes: Vec<&'a mut Reflection>,
}
struct ScriptSystemData<'a> {
meta_table: Read<'a, ReflectionTable>,
reads: Vec<Ref<'a, Box<Resource + 'static>>>,
writes: Vec<RefMut<'a, Box<Resource + 'static>>>,
}
impl<'a> DynamicSystemData<'a> for ScriptSystemData<'a> {
type Accessor = Dependencies;
fn setup(_accessor: &Dependencies, _res: &mut Resources) {}
fn fetch(access: &Dependencies, res: &'a Resources) -> Self {
let reads = access
.reads
.iter()
.map(|id| id.0)
.map(|id| res
.try_fetch_internal(id)
.expect("bug: the requested resource does not exist")
.borrow()
)
.collect();
let writes = access
.writes
.iter()
.map(|id| id.0)
.map(|id| res
.try_fetch_internal(id)
.expect("bug: the requested resource does not exist")
.borrow_mut()
)
.collect();
ScriptSystemData {
meta_table: SystemData::fetch(res),
reads,
writes,
}
}
}
fn create_script_sys(res: &Resources) -> DynamicSystem {
fn script(input: ScriptInput) {
input.reads[0].call_method("bar");
input.writes[0].call_method("foo");
}
let reads = vec!["Bar"];
let writes = vec!["Foo"];
let table = res.fetch::<ResourceTable>();
let sys = DynamicSystem {
dependencies: Dependencies {
reads: reads.iter().map(|r| table.get(r)).collect(),
writes: writes.iter().map(|r| table.get(r)).collect(),
},
script,
};
sys
}
fn main() {
#[derive(Debug, Default)]
struct Foo;
impl Reflection for Foo {
fn call_method(&self, s: &str) {
match s {
"foo" => println!("Hello from Foo"),
"bar" => println!("You gotta ask somebody else"),
_ => panic!("The error handling of this example is non-ideal"),
}
}
}
#[derive(Debug, Default)]
struct Bar;
impl Reflection for Bar {
fn call_method(&self, s: &str) {
match s {
"bar" => println!("Hello from Bar"),
"foo" => println!("You gotta ask somebody else"),
_ => panic!("The error handling of this example is non-ideal"),
}
}
}
struct NormalSys;
impl<'a> System<'a> for NormalSys {
type SystemData = (Read<'a, Foo>, Read<'a, Bar>);
fn run(&mut self, (foo, bar): Self::SystemData) {
println!("Fetched foo: {:?}", &foo as &Foo);
println!("Fetched bar: {:?}", &bar as &Bar);
}
}
let mut res = Resources::new();
{
let mut table = res.entry().or_insert_with(|| ReflectionTable::new());
table.register(&Foo);
table.register(&Bar);
}
{
let mut table = res.entry().or_insert_with(|| ResourceTable::new());
table.register::<Foo>("Foo");
table.register::<Bar>("Bar");
}
let mut dispatcher = DispatcherBuilder::new().with(NormalSys, "normal", &[]).build();
dispatcher.setup(&mut res);
let script0 = create_script_sys(&res);
let mut scripts = DispatcherBuilder::new().with(script0, "script0", &[]).build();
scripts.setup(&mut res);
loop {
dispatcher.dispatch(&res);
scripts.dispatch(&res);
break;
}
}