pulz-schedule 0.1.0-alpha2

For scheduling systems and managing their resources
Documentation
use std::marker::PhantomData;

use crate::{
    label::SystemLabel,
    resource::{ResourceAccess, Resources, ResourcesSend},
};

mod boxed;
mod data;
mod func_system;

pub use data::{SystemData, SystemDataSend};
pub use func_system::FuncSystem;
pub use pulz_schedule_macros::{into_system as System, system};

pub(crate) use self::boxed::BoxedSystem;

pub trait SystemInit: 'static {
    fn init(&mut self, res: &mut Resources);
    fn system_type_name(&self) -> &'static str {
        std::any::type_name::<Self>()
    }
    fn system_type_id(&self) -> std::any::TypeId {
        std::any::TypeId::of::<Self>()
    }
    fn system_label(&self) -> SystemLabel {
        SystemLabel(self.system_type_id(), self.system_type_name())
    }
}

pub trait ExclusiveSystem: SystemInit {
    fn run_exclusive(&mut self, res: &mut Resources);
}

pub trait System: ExclusiveSystem {
    fn run(&mut self, res: &Resources);
    fn update_access(&self, res: &Resources, access: &mut ResourceAccess);
}

pub trait SendSystem: System + Send + Sync {
    fn run_send(&mut self, res: &ResourcesSend);
}

pub trait IntoSystem<Marker> {
    type System: ExclusiveSystem;

    fn into_system(self) -> Self::System;
}

#[doc(hidden)]
pub struct SelfSystemMarker<S>(PhantomData<fn(S)>);

#[diagnostic::do_not_recommend]
impl<S: ExclusiveSystem> IntoSystem<SelfSystemMarker<S>> for S {
    type System = S;

    #[inline]
    fn into_system(self) -> Self::System {
        self
    }
}

#[doc(hidden)]
pub struct IntoSystemFnMarker;

#[diagnostic::do_not_recommend]
impl<S, F> IntoSystem<IntoSystemFnMarker> for F
where
    F: FnOnce() -> S,
    S: ExclusiveSystem,
{
    type System = S;

    #[inline]
    fn into_system(self) -> Self::System {
        self()
    }
}

#[diagnostic::do_not_recommend]
impl<S: System> ExclusiveSystem for S {
    #[inline]
    fn run_exclusive<'a>(&'a mut self, res: &'a mut Resources) {
        self.run(res)
    }
}