use alloc::vec::Vec;
use crate::{Fetch, FetchItem};
use super::{FetchAccessData, FmtQuery, PreparedFetch};
pub struct Map<Q, F> {
pub(crate) query: Q,
pub(crate) func: F,
}
impl<Q, F> Map<Q, F> {
pub const fn new(query: Q, func: F) -> Self {
Self { query, func }
}
}
impl<'q, Q, F, T> FetchItem<'q> for Map<Q, F>
where
Q: FetchItem<'q>,
F: Fn(Q::Item) -> T,
F: 'static,
{
type Item = T;
}
impl<'w, Q, F, T> Fetch<'w> for Map<Q, F>
where
Q: Fetch<'w>,
F: for<'q> Fn(<Q as FetchItem<'q>>::Item) -> T,
F: 'static,
T: 'static,
{
const MUTABLE: bool = Q::MUTABLE;
type Prepared = Map<Q::Prepared, &'w F>;
fn prepare(&'w self, data: super::FetchPrepareData<'w>) -> Option<Self::Prepared> {
Some(Map {
query: self.query.prepare(data)?,
func: &self.func,
})
}
fn filter_arch(&self, data: FetchAccessData) -> bool {
self.query.filter_arch(data)
}
fn access(&self, data: super::FetchAccessData, dst: &mut Vec<crate::system::Access>) {
self.query.access(data, dst)
}
fn describe(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Map").field(&FmtQuery(&self.query)).finish()
}
}
impl<'w, 'q, Q, F, T> PreparedFetch<'q> for Map<Q, &'w F>
where
Q: PreparedFetch<'q>,
F: Fn(Q::Item) -> T,
F: 'static,
T: 'static,
{
type Item = T;
type Chunk = (&'q F, Q::Chunk);
const HAS_FILTER: bool = Q::HAS_FILTER;
unsafe fn create_chunk(&'q mut self, slots: crate::archetype::Slice) -> Self::Chunk {
(self.func, self.query.create_chunk(slots))
}
unsafe fn fetch_next(chunk: &mut Self::Chunk) -> Self::Item {
(chunk.0)(Q::fetch_next(&mut chunk.1))
}
unsafe fn filter_slots(&mut self, slots: crate::archetype::Slice) -> crate::archetype::Slice {
self.query.filter_slots(slots)
}
}