use crate::{
archetype,
component::Component,
registry::{
Null,
Registry,
},
};
use alloc::vec::Vec;
use core::mem::ManuallyDrop;
pub trait Sealed: Registry {
unsafe fn component_eq<R>(
components_a: &[(*mut u8, usize)],
components_b: &[(*mut u8, usize)],
length: usize,
identifier_iter: archetype::identifier::Iter<R>,
) -> bool
where
R: Registry;
}
impl Sealed for Null {
unsafe fn component_eq<R>(
_components_a: &[(*mut u8, usize)],
_components_b: &[(*mut u8, usize)],
_length: usize,
_identifier_iter: archetype::identifier::Iter<R>,
) -> bool
where
R: Registry,
{
true
}
}
impl<C, R> Sealed for (C, R)
where
C: Component + PartialEq,
R: Sealed,
{
unsafe fn component_eq<R_>(
mut components_a: &[(*mut u8, usize)],
mut components_b: &[(*mut u8, usize)],
length: usize,
mut identifier_iter: archetype::identifier::Iter<R_>,
) -> bool
where
R_: Registry,
{
if
unsafe { identifier_iter.next().unwrap_unchecked() } {
let component_column_a =
unsafe { components_a.get_unchecked(0) };
let component_column_b =
unsafe { components_b.get_unchecked(0) };
if ManuallyDrop::new(
unsafe {
Vec::from_raw_parts(
component_column_a.0.cast::<C>(),
length,
component_column_a.1,
)
},
) != ManuallyDrop::new(
unsafe {
Vec::from_raw_parts(
component_column_b.0.cast::<C>(),
length,
component_column_b.1,
)
},
) {
return false;
}
components_a =
unsafe { components_a.get_unchecked(1..) };
components_b =
unsafe { components_b.get_unchecked(1..) };
}
unsafe { R::component_eq(components_a, components_b, length, identifier_iter) }
}
}
#[cfg(test)]
mod tests {
use super::Sealed;
use crate::{
archetype::Identifier,
Registry,
};
use alloc::vec;
#[test]
fn components_equal() {
#[derive(PartialEq)]
struct A(usize);
#[derive(PartialEq)]
struct B(bool);
#[derive(PartialEq)]
struct C;
type Registry = Registry!(A, B, C);
let identifier = unsafe { Identifier::<Registry>::new(vec![7]) };
let mut a_column_a = vec![A(0), A(1), A(2)];
let mut b_column_a = vec![B(false), B(true), B(true)];
let mut c_column_a = vec![C, C, C];
let components_a = vec![
(a_column_a.as_mut_ptr().cast::<u8>(), a_column_a.capacity()),
(b_column_a.as_mut_ptr().cast::<u8>(), b_column_a.capacity()),
(c_column_a.as_mut_ptr().cast::<u8>(), c_column_a.capacity()),
];
let mut a_column_b = vec![A(0), A(1), A(2)];
let mut b_column_b = vec![B(false), B(true), B(true)];
let mut c_column_b = vec![C, C, C];
let components_b = vec![
(a_column_b.as_mut_ptr().cast::<u8>(), a_column_b.capacity()),
(b_column_b.as_mut_ptr().cast::<u8>(), b_column_b.capacity()),
(c_column_b.as_mut_ptr().cast::<u8>(), c_column_b.capacity()),
];
assert!(unsafe {
Registry::component_eq(&components_a, &components_b, 3, identifier.iter())
});
}
#[test]
fn components_not_equal() {
#[derive(PartialEq)]
struct A(usize);
#[derive(PartialEq)]
struct B(bool);
#[derive(PartialEq)]
struct C;
type Registry = Registry!(A, B, C);
let identifier = unsafe { Identifier::<Registry>::new(vec![7]) };
let mut a_column_a = vec![A(0), A(1), A(2)];
let mut b_column_a = vec![B(false), B(true), B(true)];
let mut c_column_a = vec![C, C, C];
let components_a = vec![
(a_column_a.as_mut_ptr().cast::<u8>(), a_column_a.capacity()),
(b_column_a.as_mut_ptr().cast::<u8>(), b_column_a.capacity()),
(c_column_a.as_mut_ptr().cast::<u8>(), c_column_a.capacity()),
];
let mut a_column_b = vec![A(0), A(1), A(2)];
let mut b_column_b = vec![B(false), B(false), B(true)];
let mut c_column_b = vec![C, C, C];
let components_b = vec![
(a_column_b.as_mut_ptr().cast::<u8>(), a_column_b.capacity()),
(b_column_b.as_mut_ptr().cast::<u8>(), b_column_b.capacity()),
(c_column_b.as_mut_ptr().cast::<u8>(), c_column_b.capacity()),
];
assert!(!unsafe {
Registry::component_eq(&components_a, &components_b, 3, identifier.iter())
});
}
}