use crate::const_type_id::*;
use crate::*;
use const_list::*;
use private::*;
use std::any::*;
use std::mem::*;
macro_rules! implements {
($name: ident, $trait: ident) => {{
use std::cell::*;
struct TraitTest<'a, T: ?Sized> {
is_trait: &'a Cell<bool>,
data: PhantomData<T>,
}
impl<T: ?Sized> Clone for TraitTest<'_, T> {
#[inline(always)]
fn clone(&self) -> Self {
self.is_trait.set(false);
TraitTest {
is_trait: self.is_trait,
data: PhantomData,
}
}
}
impl<T: ?Sized + $trait> Copy for TraitTest<'_, T> {}
let is_trait = Cell::new(true);
_ = [TraitTest::<$name> {
is_trait: &is_trait,
data: PhantomData,
}]
.clone();
is_trait.get()
}};
}
pub trait GeeseSystem: 'static + Sized {
const DEPENDENCIES: Dependencies = dependencies();
const EVENT_HANDLERS: EventHandlers<Self> = event_handlers();
fn new(ctx: GeeseContextHandle<Self>) -> Self;
}
#[derive(Copy, Clone, Debug)]
pub struct Dependencies {
inner: ConstList<'static, Dependency>,
}
impl Dependencies {
#[inline(always)]
const fn new() -> Self {
Self {
inner: ConstList::new(),
}
}
#[inline(always)]
pub const fn with<S: DependencyRef>(&'static self) -> Self {
self.with_dependency(Dependency::new::<S>())
}
#[inline(always)]
pub const fn with_dependency(&'static self, dependency: Dependency) -> Self {
Self {
inner: self.inner.push(dependency),
}
}
#[inline(always)]
pub(crate) const fn as_inner(&self) -> &ConstList<'static, Dependency> {
&self.inner
}
#[inline(always)]
pub(crate) const fn index_of<S: GeeseSystem>(&self) -> Option<usize> {
let mut i = 0;
while i < self.inner.len() {
if const_unwrap(self.inner.get(i))
.dependency_id()
.eq(&ConstTypeId::of::<S>())
{
return Some(i);
}
i += 1;
}
None
}
}
#[inline(always)]
pub const fn dependencies() -> Dependencies {
Dependencies::new()
}
#[derive(Copy, Clone, Debug)]
pub struct Dependency {
descriptor_getter: fn() -> Box<dyn SystemDescriptor>,
dependencies: &'static Dependencies,
mutable: bool,
type_id: ConstTypeId,
}
impl Dependency {
#[inline(always)]
pub const fn new<S: DependencyRef>() -> Self {
Self {
descriptor_getter: Self::get_descriptor::<S::System>,
dependencies: &S::System::DEPENDENCIES,
mutable: S::MUTABLE,
type_id: ConstTypeId::of::<S::System>(),
}
}
#[inline(always)]
pub(crate) const fn dependency_id(&self) -> ConstTypeId {
self.type_id
}
#[inline(always)]
pub(crate) const fn mutable(&self) -> bool {
self.mutable
}
#[inline(always)]
pub(crate) fn descriptor(&self) -> Box<dyn SystemDescriptor> {
(self.descriptor_getter)()
}
#[inline(always)]
fn get_descriptor<S: GeeseSystem>() -> Box<dyn SystemDescriptor> {
Box::<TypedSystemDescriptor<S>>::default()
}
}
#[allow(unused_variables)]
pub struct EventHandlers<S: GeeseSystem> {
inner: ConstList<'static, EventHandlerRaw>,
data: PhantomData<fn(S)>,
}
impl<S: GeeseSystem> EventHandlers<S> {
#[inline(always)]
const fn new() -> Self {
Self {
inner: ConstList::new(),
data: PhantomData,
}
}
#[inline(always)]
pub const fn with<Q: MutableRef<S>, T: 'static + Send + Sync>(
&'static self,
handler: fn(Q, &T),
) -> Self {
Self {
inner: self.inner.push(EventHandlerRaw::new(handler)),
data: PhantomData,
}
}
pub const fn with_handler(&'static self, handler: EventHandler<S>) -> Self {
Self {
inner: self.inner.push(handler.raw),
data: PhantomData,
}
}
#[inline(always)]
fn as_inner(&self) -> &ConstList<'_, EventHandlerRaw> {
&self.inner
}
}
impl<S: GeeseSystem> Copy for EventHandlers<S> {}
impl<S: GeeseSystem> Clone for EventHandlers<S> {
fn clone(&self) -> Self {
*self
}
}
impl<S: GeeseSystem> std::fmt::Debug for EventHandlers<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventHandlers")
.field("inner", &self.inner)
.finish()
}
}
#[inline(always)]
pub const fn event_handlers<S: GeeseSystem>() -> EventHandlers<S> {
EventHandlers::new()
}
pub struct EventHandler<S: GeeseSystem> {
raw: EventHandlerRaw,
data: PhantomData<fn(S)>,
}
impl<S: GeeseSystem> EventHandler<S> {
#[inline(always)]
pub const fn new<Q: MutableRef<S>, T: 'static + Send + Sync>(handler: fn(Q, &T)) -> Self {
Self {
raw: EventHandlerRaw::new(handler),
data: PhantomData,
}
}
}
impl<S: GeeseSystem> Copy for EventHandler<S> {}
impl<S: GeeseSystem> Clone for EventHandler<S> {
fn clone(&self) -> Self {
*self
}
}
impl<S: GeeseSystem> std::fmt::Debug for EventHandler<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EventHandler")
.field("raw", &self.raw)
.finish()
}
}
#[derive(Copy, Clone, Debug)]
pub(crate) struct EventHandlerRaw {
event_id: fn() -> TypeId,
handler: EventInvoker,
}
impl EventHandlerRaw {
#[inline(always)]
pub const fn new<S: GeeseSystem, Q: MutableRef<S>, T: 'static + Send + Sync>(
handler: fn(Q, &T),
) -> Self {
Self {
event_id: TypeId::of::<T>,
handler: EventInvoker::new(handler),
}
}
#[inline(always)]
pub fn event_id(&self) -> TypeId {
(self.event_id)()
}
#[inline(always)]
pub fn handler(&self) -> &EventInvoker {
&self.handler
}
}
#[derive(Copy, Clone, Debug)]
pub(crate) struct EventInvoker {
pointer_flattener: Option<unsafe fn(*mut (), &dyn Any, *const ())>,
handler: *const (),
}
impl EventInvoker {
#[inline(always)]
pub const fn new<S: GeeseSystem, Q: MutableRef<S>, T: 'static + Send + Sync>(
handler: fn(Q, &T),
) -> Self {
Self {
pointer_flattener: Some(Self::pointer_flattener::<T>),
handler: handler as *const (),
}
}
#[inline(always)]
pub unsafe fn invoke(&self, system: *mut (), value: &dyn Any) {
(self.pointer_flattener.unwrap_unchecked())(system, value, self.handler);
}
#[inline(always)]
unsafe fn pointer_flattener<T: 'static + Send + Sync>(
system: *mut (),
value: &dyn Any,
to_run: *const (),
) {
transmute::<_, fn(*mut (), &T)>(to_run)(system, value.downcast_ref().unwrap_unchecked())
}
}
impl Default for EventInvoker {
#[inline(always)]
fn default() -> Self {
Self {
pointer_flattener: None,
handler: std::ptr::null_mut(),
}
}
}
unsafe impl Send for EventInvoker {}
unsafe impl Sync for EventInvoker {}
pub(super) trait SystemDescriptor: 'static + Send + Sync {
fn create(&self, handle: Arc<ContextHandleInner>) -> Box<dyn Any>;
fn dependencies(&self) -> &'static Dependencies;
fn dependency_len(&self) -> usize;
fn event_handlers(&self) -> &'static ConstList<'static, EventHandlerRaw>;
fn is_sync(&self) -> bool;
fn system_id(&self) -> TypeId;
}
pub(crate) struct TypedSystemDescriptor<S: GeeseSystem>(PhantomData<fn(S)>);
impl<S: GeeseSystem> Default for TypedSystemDescriptor<S> {
#[inline(always)]
fn default() -> Self {
Self(PhantomData)
}
}
impl<S: GeeseSystem> SystemDescriptor for TypedSystemDescriptor<S> {
fn create(&self, handle: Arc<ContextHandleInner>) -> Box<dyn Any> {
Box::new(S::new(GeeseContextHandle::new(handle)))
}
fn dependencies(&self) -> &'static Dependencies {
&S::DEPENDENCIES
}
fn dependency_len(&self) -> usize {
const_eval!(S::DEPENDENCIES.as_inner().len(), usize, S)
}
fn event_handlers(&self) -> &'static ConstList<'static, EventHandlerRaw> {
S::EVENT_HANDLERS.as_inner()
}
fn is_sync(&self) -> bool {
implements!(S, Sync)
}
fn system_id(&self) -> TypeId {
TypeId::of::<S>()
}
}
#[derive(Copy, Clone, Debug)]
pub struct Mut<S: GeeseSystem>(PhantomData<fn(S)>);
#[inline(always)]
pub(crate) const fn has_duplicate_dependencies(dependencies: &Dependencies) -> bool {
let inner_deps = dependencies.as_inner();
let mut i = 0;
while i < inner_deps.len() {
if has_duplicate_dependencies(const_unwrap(inner_deps.get(i)).dependencies) {
return true;
}
let mut j = i + 1;
while j < inner_deps.len() {
if const_unwrap(inner_deps.get(i))
.dependency_id()
.eq(&const_unwrap(inner_deps.get(j)).dependency_id())
{
return true;
}
j += 1;
}
i += 1;
}
false
}
pub trait EventQueue: Sized {
fn with<T: 'static + Send + Sync>(self, event: T) -> Self {
self.with_boxed(Box::new(event))
}
fn with_boxed(self, event: Box<dyn Any + Send + Sync>) -> Self {
self.with_many_boxed(std::iter::once(event))
}
fn with_buffer(self, events: EventBuffer) -> Self {
self.with_many_boxed(events.events)
}
fn with_many<T: 'static + Send + Sync>(self, events: impl IntoIterator<Item = T>) -> Self {
self.with_many_boxed(
events
.into_iter()
.map(|x| Box::new(x) as Box<dyn Any + Send + Sync>),
)
}
fn with_many_boxed(self, events: impl IntoIterator<Item = Box<dyn Any + Send + Sync>>) -> Self;
}
pub trait GeeseThreadPool: 'static + Send + Sync {
fn set_callback(&self, callback: Option<Arc<dyn Fn() + Send + Sync>>);
}
mod private {
use super::*;
pub trait DependencyRef {
type System: GeeseSystem;
const MUTABLE: bool;
}
impl<S: GeeseSystem> DependencyRef for S {
type System = S;
const MUTABLE: bool = false;
}
impl<S: GeeseSystem> DependencyRef for Mut<S> {
type System = S;
const MUTABLE: bool = true;
}
pub trait MutableRef<T> {}
impl<'a, T> MutableRef<T> for &'a mut T {}
}