use std::marker::PhantomData;
use {ResourceId, Resources};
pub trait RunNow<'a> {
fn run_now(&mut self, res: &'a Resources);
fn setup(&mut self, res: &mut Resources);
}
impl<'a, T> RunNow<'a> for T
where
T: System<'a>,
{
fn run_now(&mut self, res: &'a Resources) {
let data = T::SystemData::fetch(res);
self.run(data);
}
fn setup(&mut self, res: &mut Resources) {
T::setup(self, res);
}
}
#[repr(u8)]
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug)]
pub enum RunningTime {
VeryShort = 1,
Short = 2,
Average = 3,
Long = 4,
VeryLong = 5,
}
pub trait System<'a> {
type SystemData: SystemData<'a>;
fn run(&mut self, data: Self::SystemData);
fn running_time(&self) -> RunningTime {
RunningTime::Average
}
fn setup(&mut self, res: &mut Resources) {
<Self::SystemData as SystemData>::setup(res)
}
}
pub trait SystemData<'a> {
fn setup(res: &mut Resources);
fn fetch(res: &'a Resources) -> Self;
fn reads() -> Vec<ResourceId>;
fn writes() -> Vec<ResourceId>;
}
impl<'a, T: ?Sized> SystemData<'a> for PhantomData<T> {
fn setup(_: &mut Resources) {}
fn fetch(_: &'a Resources) -> Self {
PhantomData
}
fn reads() -> Vec<ResourceId> {
Vec::new()
}
fn writes() -> Vec<ResourceId> {
Vec::new()
}
}
macro_rules! impl_data {
( $($ty:ident),* ) => {
impl<'a, $($ty),*> SystemData<'a> for ( $( $ty , )* )
where $( $ty : SystemData<'a> ),*
{
fn setup(res: &mut Resources) {
#![allow(unused_variables)]
$(
<$ty as SystemData>::setup(&mut *res);
)*
}
fn fetch(res: &'a Resources) -> Self {
#![allow(unused_variables)]
( $( <$ty as SystemData<'a>>::fetch(res), )* )
}
fn reads() -> Vec<ResourceId> {
#![allow(unused_mut)]
let mut r = Vec::new();
$( {
let mut reads = <$ty as SystemData>::reads();
r.append(&mut reads);
} )*
r
}
fn writes() -> Vec<ResourceId> {
#![allow(unused_mut)]
let mut r = Vec::new();
$( {
let mut writes = <$ty as SystemData>::writes();
r.append(&mut writes);
} )*
r
}
}
};
}
impl<'a> SystemData<'a> for () {
fn setup(_: &mut Resources) {}
fn fetch(_: &'a Resources) -> Self {
()
}
fn reads() -> Vec<ResourceId> {
Vec::new()
}
fn writes() -> Vec<ResourceId> {
Vec::new()
}
}
mod impl_data {
#![cfg_attr(rustfmt, rustfmt_skip)]
use super::*;
impl_data!(A);
impl_data!(A, B);
impl_data!(A, B, C);
impl_data!(A, B, C, D);
impl_data!(A, B, C, D, E);
impl_data!(A, B, C, D, E, F);
impl_data!(A, B, C, D, E, F, G);
impl_data!(A, B, C, D, E, F, G, H);
impl_data!(A, B, C, D, E, F, G, H, I);
impl_data!(A, B, C, D, E, F, G, H, I, J);
impl_data!(A, B, C, D, E, F, G, H, I, J, K);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
impl_data!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
}