use crate::*;
pub trait Nest: private::Sealed {
type Nested;
fn flatten(v: Self::Nested) -> Self;
fn nest(self) -> Self::Nested;
}
pub trait Flatten: private::Sealed {
type Flattened;
fn flatten(self) -> Self::Flattened;
fn nest(v: Self::Flattened) -> Self;
}
macro_rules! unnest {
(($layer:expr); ($($v:expr),*); ($u:ident, $($us:ident,)*)) => {
unnest!(($layer . 1); ($($v,)* $layer . 0); ($($us,)*))
};
(($layer:expr); ($($v:expr),*); ()) => { ($($v,)*) };
}
impl Nest for () {
type Nested = ();
#[inline]
fn flatten(_v: ()) -> () {
()
}
#[inline]
fn nest(self) -> () {
()
}
}
macro_rules! nest {
($v:ident,) => { () };
($v:ident, $n:tt, $($ns:tt,)*) => {
($v.$n, nest!($v, $($ns,)*))
}
}
macro_rules! impl_nested {
(@impl_internal {($t:ident, $n:tt), $(($ts:ident, $ns:tt),)*}) => {
impl<$t, $($ts),*> Nest for ($t, $($ts,)*) where ($($ts,)*): Nest {
type Nested = impl_nested!(@nest_type $t, $($ts,)*);
#[inline]
fn flatten(v: Self::Nested) -> Self {
unnest!((v); (); ($t, $($ts,)*))
}
#[inline]
fn nest(self) -> Self::Nested {
nest!(self, $n, $($ns,)*)
}
}
impl<$t, $($ts),*> Flatten for impl_nested!(@nest_type $t, $($ts,)*) {
type Flattened = ($t, $($ts,)*);
#[inline]
fn flatten(self) -> Self::Flattened {
unnest!((self); (); ($t, $($ts,)*))
}
#[inline]
fn nest(v: Self::Flattened) -> Self {
nest!(v, $n, $($ns,)*)
}
}
};
(@nest_type) => {
()
};
(@nest_type $t:ident, $($ts:ident,)*) => {
($t, impl_nested!(@nest_type $($ts,)*))
};
(@internal {$(($t:ident,$n:tt),)+}; {}; {}) => {
impl_nested!(@impl_internal {$(($t, $n),)*});
};
(@internal {$(($t1:ident,$n1:tt),)+};
{$t2:ident, $($t3:ident,)*};
{$n2:tt, $($n3:tt,)*}) => {
impl_nested!(@impl_internal {$(($t1, $n1),)*});
impl_nested!(@internal {$(($t1, $n1),)* ($t2, $n2),};
{$($t3,)*};
{$($n3,)*});
};
(($t:ident, $($ts:ident,)+); ($n:tt, $($ns:tt,)+)) => {
impl_nested!(@internal {($t, $n),}; {$($ts,)*}; {$($ns,)*});
};
}
impl_nested!(
(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, AA, BB, CC, DD,
EE, FF,);
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,)
);
pub trait ComponentProviderRec<'a, T> {
fn fetch(&'a self) -> T;
}
pub trait ComponentProvider<'a, T: Nest> {
fn fetch(&'a self) -> T;
}
impl<'a, T, W> ComponentProvider<'a, T> for W
where
T: Nest,
W: WorldInterface<'a> + ComponentProviderRec<'a, T::Nested>,
{
#[inline]
fn fetch(&'a self) -> T {
<T as Nest>::flatten(<Self as ComponentProviderRec<'a, T::Nested>>::fetch(self))
}
}
impl<'a, H, T, WD> ComponentProviderRec<'a, (ReadComponent<'a, H>, T)> for WD
where
H: 'a + StorageSpec<'a>,
H::Storage: ComponentStorage<'a>,
WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetComponent<'a, H>,
{
#[inline]
fn fetch(&'a self) -> (ReadComponent<'a, H>, T) {
(
ReadComponent {
storage: <Self as GetComponent<'a, H>>::get(self),
},
<Self as ComponentProviderRec<T>>::fetch(self),
)
}
}
impl<'a, H, T, WD> ComponentProviderRec<'a, (ReadResource<'a, H>, T)> for WD
where
H: 'a,
WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetResource<H>,
{
#[inline]
fn fetch(&'a self) -> (ReadResource<'a, H>, T) {
(
ReadResource {
resource: <Self as GetResource<H>>::get(self),
},
<Self as ComponentProviderRec<T>>::fetch(self),
)
}
}
impl<'a, H, T, WD> ComponentProviderRec<'a, (WriteResource<'a, H>, T)> for WD
where
H: 'a,
WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetResource<H>,
{
#[inline]
fn fetch(&'a self) -> (WriteResource<'a, H>, T) {
(
WriteResource {
resource: <Self as GetResource<H>>::get_mut(self),
},
<Self as ComponentProviderRec<T>>::fetch(self),
)
}
}
impl<'a, H, T, WD> ComponentProviderRec<'a, (WriteComponent<'a, H>, T)> for WD
where
H: 'a + StorageSpec<'a>,
H::Storage: ComponentStorage<'a>,
WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetComponent<'a, H>,
{
#[inline]
fn fetch(&'a self) -> (WriteComponent<'a, H>, T) {
(
WriteComponent {
storage: <Self as GetComponent<'a, H>>::get_mut(self),
},
<Self as ComponentProviderRec<T>>::fetch(self),
)
}
}
impl<'a, WD> ComponentProviderRec<'a, ()> for WD {
#[inline]
fn fetch(&'a self) -> () {
()
}
}
impl<'a, WD, T> ComponentProviderRec<'a, ReadComponent<'a, T>> for WD
where
T: 'a + StorageSpec<'a>,
WD: WorldInterface<'a> + GetComponent<'a, T>,
{
fn fetch(&'a self) -> ReadComponent<T> {
ReadComponent {
storage: <Self as GetComponent<'a, T>>::get(self),
}
}
}
impl<'a, WD, T> ComponentProviderRec<'a, WriteComponent<'a, T>> for WD
where
T: 'a + StorageSpec<'a>,
WD: WorldInterface<'a> + GetComponent<'a, T>,
{
fn fetch(&'a self) -> WriteComponent<T> {
WriteComponent {
storage: <Self as GetComponent<'a, T>>::get_mut(self),
}
}
}
pub trait System<'a> {
type Dependencies: Nest; fn run(&'a mut self, dependencies: Self::Dependencies);
}
pub enum SystemOutput<T> {
Ignore,
Delete,
Update(T),
}
impl<T> Default for SystemOutput<T> {
fn default() -> Self {
SystemOutput::Ignore
}
}
pub trait PureFunctionalSystem {
type Inputs;
type Outputs: SystemOutputTuple;
fn process(&self, data: &Self::Inputs) -> <Self::Outputs as SystemOutputTuple>::OutputTuple;
}
pub trait WorldInterface<'a>
where
Self: Sized,
{
type EntityBuilder: 'a;
type ComponentSet;
type AvailableTypes;
fn new_entity(&'a mut self) -> Self::EntityBuilder;
fn build_entity(&mut self, c: Self::ComponentSet) -> Entity;
fn delete_entity(&mut self, e: Entity);
fn run_system<'b, S, T >(&'a mut self, system: &'b mut S)
where
S: System<'b, Dependencies = T>,
T: Nest,
Self: ComponentProviderRec<'a, T::Nested>,
{
system.run(<Self as ComponentProvider<'a, T>>::fetch(self));
}
}
pub trait BuildWith<T> {
fn with(self, data: T) -> Self;
}
pub trait ResourceProvider {
type Resources;
fn get_resources(&mut self) -> &Self::Resources;
}
pub trait GetComponent<'a, T: StorageSpec<'a>> {
fn get(&self) -> std::cell::Ref<T::Storage>;
fn get_mut(&self) -> std::cell::RefMut<T::Storage>;
}
pub trait GetResource<T> {
fn get(&self) -> std::cell::Ref<T>;
fn get_mut(&self) -> std::cell::RefMut<T>;
fn set(&self, t: T);
}
mod private {
pub trait Sealed {}
impl Sealed for () {}
}
pub trait SystemOutputTuple: private::Sealed {
type OutputTuple;
}
macro_rules! impl_output_tuple {
(@impl_internal $($t:ident,)+) => {
impl<$($t),*> SystemOutputTuple for ($($t,)*) {
#[allow(unused_parens)]
type OutputTuple = ($(SystemOutput<$t>),*);
}
impl<$($t),*> private::Sealed for ($($t,)*) {}
};
(($($t:ident,)+);) => {
impl_output_tuple!(@impl_internal $($t,)*);
};
(($($t1:ident,)+); $t2:ident $(,)* $($t3:ident),*) => {
impl_output_tuple!(@impl_internal $($t1,)*);
impl_output_tuple!(($($t1),*, $t2,); $($t3),*);
};
($t1:ident, $($t:ident),+) => {
impl_output_tuple!(($t1,); $($t),*);
};
}
impl_output_tuple!(
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, AA, BB, CC, DD,
EE, FF
);