use std::{ptr::NonNull, marker::PhantomData}; use crate::{world::World, View, Query, Access}; pub mod graph; /// A system that does not mutate the world pub trait System { fn world_access(&self) -> Access; fn execute(&mut self, world: NonNull) -> anyhow::Result<()>; } /// A trait for converting something into a system. pub trait IntoSystem { type System: System; fn into_system(self) -> Self::System; } trait FnArg { type Arg<'a>; fn new() -> Self; unsafe fn get<'a>(&mut self, world: &'a World) -> Self::Arg<'a>; } pub struct FnSystem { inner: F,//for<'a> fn(Args) -> anyhow::Result<()> //args: Args, _p: PhantomData, } /* impl<'a, F, Q> System for FnSystem where Q: FnArg, F: Fn(Q::Arg<'a>,) -> anyhow::Result<()>, */ impl System for FnSystem where A: FnArg, F: for<'a> FnMut(A::Arg<'a>) -> anyhow::Result<()>, { fn world_access(&self) -> Access { todo!() } fn execute(&mut self, world: NonNull) -> anyhow::Result<()> { let world = unsafe { world.as_ref() }; let mut a = A::new(); let a = unsafe { a.get(world) }; (self.inner)(a)?; Ok(()) } } /* impl IntoSystem for F where A: FnArg, F: for<'a> Fn(A::Arg<'a>) -> anyhow::Result<()>, { type System = FnSystem; fn into_system(self) -> Self::System { FnSystem { _p: PhantomData, inner: self } } } */ /* impl IntoSystem for F where Q: Query, F: for<'a> Fn( as FnArg>::Arg<'a>) -> anyhow::Result<()>, { type System = FnSystem>; fn into_system(self) -> Self::System { FnSystem { _p: PhantomData, inner: self } } } */ impl IntoSystem for F where Q: Query, F: for<'a> FnMut( as FnArg>::Arg<'a>) -> anyhow::Result<()>, { type System = FnSystem>; fn into_system(self) -> Self::System { FnSystem { _p: PhantomData, inner: self } } } pub struct FnArgStorage { query: Q, } impl FnArg for FnArgStorage { type Arg<'b> = View<'b, Q>; fn new() -> Self { FnArgStorage { query: Q::new(), } } unsafe fn get<'b>(&mut self, world: &'b World) -> Self::Arg<'b> { let arch = world.archetypes.values().collect(); let v = View::new(world, self.query, arch); v } } #[cfg(test)] mod tests { use std::{ptr::NonNull, sync::atomic::{AtomicU8, Ordering}, rc::Rc, ops::Add}; use crate::{tests::{Vec2, Vec3}, View, QueryBorrow, world::World}; use super::{System, IntoSystem}; #[test] fn simple_system() { let mut world = World::new(); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); let mut count = 0; let test_system = |view: View>| -> anyhow::Result<()> { for v in view.into_iter() { println!("Got v at: {:?}", v); count += 1; } Ok(()) }; test_system.into_system().execute(NonNull::from(&world)).unwrap(); assert_eq!(count, 4); } #[test] fn multi_system() { let mut world = World::new(); world.spawn((Vec2::rand(), Vec3::rand())); world.spawn((Vec2::rand(), Vec3::rand())); world.spawn((Vec2::rand(),)); world.spawn((Vec2::rand(),)); let mut count = 0; let test_system = |view: View<(QueryBorrow, QueryBorrow)>| -> anyhow::Result<()> { for (v2, v3) in view.into_iter() { println!("Got v2 at '{:?}' and v3 at: '{:?}'", v2, v3); count += 1; } Ok(()) }; test_system.into_system().execute(NonNull::from(&world)).unwrap(); assert_eq!(count, 2); } }