pub trait CollectionExtract<S>: Send + Sync {
type Item;
fn extract<'s>(&self, s: &'s S) -> &'s [Self::Item];
fn change_source(&self) -> ChangeSource {
ChangeSource::Unknown
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChangeSource {
Unknown,
Static,
Descriptor(usize),
}
impl ChangeSource {
#[inline]
pub fn reacts_to(self, descriptor_index: usize) -> bool {
match self {
Self::Unknown => true,
Self::Static => false,
Self::Descriptor(index) => index == descriptor_index,
}
}
#[inline]
pub fn owns_descriptor(self, descriptor_index: usize) -> bool {
matches!(self, Self::Descriptor(index) if index == descriptor_index)
}
#[inline]
pub fn is_unknown(self) -> bool {
matches!(self, Self::Unknown)
}
#[inline]
pub fn same_index_domain(self, other: Self) -> bool {
matches!((self, other), (Self::Descriptor(left), Self::Descriptor(right)) if left == right)
}
#[inline]
pub fn assert_localizes(self, descriptor_index: usize, constraint_name: &str) -> bool {
if self.owns_descriptor(descriptor_index) {
return true;
}
if self.reacts_to(descriptor_index) {
panic!(
"constraint `{constraint_name}` received descriptor {descriptor_index}, but source {self:?} cannot localize entity indexes"
);
}
false
}
}
pub trait FlattenExtract<P>: Send + Sync {
type Item;
fn extract<'s>(&self, parent: &'s P) -> &'s [Self::Item];
}
impl<S, A, F> CollectionExtract<S> for F
where
F: for<'a> Fn(&'a S) -> &'a [A] + Send + Sync,
{
type Item = A;
#[inline]
fn extract<'s>(&self, s: &'s S) -> &'s [A] {
self(s)
}
}
impl<P, B, F> FlattenExtract<P> for F
where
F: for<'a> Fn(&'a P) -> &'a [B] + Send + Sync,
{
type Item = B;
#[inline]
fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
self(parent)
}
}
#[derive(Clone, Copy)]
pub struct FlattenVecExtract<F>(pub F);
impl<P, B, F> FlattenExtract<P> for FlattenVecExtract<F>
where
F: for<'a> Fn(&'a P) -> &'a Vec<B> + Send + Sync,
{
type Item = B;
#[inline]
fn extract<'s>(&self, parent: &'s P) -> &'s [B] {
(self.0)(parent).as_slice()
}
}
#[derive(Clone, Copy)]
pub struct SourceExtract<E> {
extractor: E,
change_source: ChangeSource,
}
impl<E> SourceExtract<E> {
pub fn new(extractor: E, change_source: ChangeSource) -> Self {
Self {
extractor,
change_source,
}
}
pub fn extractor(&self) -> &E {
&self.extractor
}
}
impl<S, E> CollectionExtract<S> for SourceExtract<E>
where
E: CollectionExtract<S>,
{
type Item = E::Item;
#[inline]
fn extract<'s>(&self, s: &'s S) -> &'s [Self::Item] {
self.extractor.extract(s)
}
fn change_source(&self) -> ChangeSource {
self.change_source
}
}
pub struct VecExtract<F>(pub F);
impl<S, A, F> CollectionExtract<S> for VecExtract<F>
where
F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
{
type Item = A;
#[inline]
fn extract<'s>(&self, s: &'s S) -> &'s [A] {
(self.0)(s).as_slice()
}
}
pub fn vec<S, A, F>(f: F) -> VecExtract<F>
where
F: for<'a> Fn(&'a S) -> &'a Vec<A> + Send + Sync,
{
VecExtract(f)
}
pub fn source<E>(extractor: E, change_source: ChangeSource) -> SourceExtract<E> {
SourceExtract::new(extractor, change_source)
}