use crate::{
archetype,
registry::{
contains::Contained,
Length,
Registry,
},
};
use core::slice;
pub trait Sealed<C, I> {
const INDEX: usize;
unsafe fn set_component<R>(
index: usize,
component: C,
components: &[(*mut u8, usize)],
length: usize,
identifier_iter: archetype::identifier::Iter<R>,
) where
R: Registry;
}
impl<C, R> Sealed<C, Contained> for (C, R)
where
R: Length,
{
const INDEX: usize = R::LEN;
unsafe fn set_component<R_>(
index: usize,
component: C,
components: &[(*mut u8, usize)],
length: usize,
_identifier_iter: archetype::identifier::Iter<R_>,
) where
R_: Registry,
{
unsafe {
*slice::from_raw_parts_mut(components.get_unchecked(0).0.cast::<C>(), length)
.get_unchecked_mut(index) = component;
}
}
}
impl<C, C_, I, R> Sealed<C_, (I,)> for (C, R)
where
R: Sealed<C_, I>,
{
const INDEX: usize = R::INDEX;
unsafe fn set_component<R_>(
index: usize,
component: C_,
mut components: &[(*mut u8, usize)],
length: usize,
mut identifier_iter: archetype::identifier::Iter<R_>,
) where
R_: Registry,
{
if unsafe { identifier_iter.next().unwrap_unchecked() } {
components = unsafe { components.get_unchecked(1..) };
}
unsafe {
R::set_component(index, component, components, length, identifier_iter);
}
}
}
#[cfg(test)]
mod tests {
use super::Sealed;
use crate::Registry;
struct A;
struct B;
struct C;
struct D;
struct E;
type Registry = Registry!(A, B, C, D, E);
#[test]
fn contains_start() {
assert_eq!(<Registry as Sealed<A, _>>::INDEX, 4);
}
#[test]
fn contains_middle() {
assert_eq!(<Registry as Sealed<C, _>>::INDEX, 2);
}
#[test]
fn contains_end() {
assert_eq!(<Registry as Sealed<E, _>>::INDEX, 0);
}
}