mod iterator_wrapper;
mod tuple_track;
pub use iterator_wrapper::{Inserted, InsertedOrModified, Modified};
pub use tuple_track::TupleTrack;
use crate::component::Component;
use crate::entity_id::EntityId;
use crate::seal::Sealed;
use crate::sparse_set::SparseSet;
pub trait Tracking: 'static + Sized + Sealed + Send + Sync {
const VALUE: u32;
#[doc(hidden)]
fn track_insertion() -> bool {
Self::VALUE & 0b0001 != 0
}
#[doc(hidden)]
fn track_modification() -> bool {
Self::VALUE & 0b0010 != 0
}
#[doc(hidden)]
fn track_deletion() -> bool {
Self::VALUE & 0b0100 != 0
}
#[doc(hidden)]
fn track_removal() -> bool {
Self::VALUE & 0b1000 != 0
}
#[doc(hidden)]
fn name() -> &'static str;
#[doc(hidden)]
#[inline]
fn is_inserted<T: Component>(
_sparse_set: &SparseSet<T>,
_entity: EntityId,
_last: TrackingTimestamp,
_current: TrackingTimestamp,
) -> bool {
false
}
#[doc(hidden)]
#[inline]
fn is_modified<T: Component>(
_sparse_set: &SparseSet<T>,
_entity: EntityId,
_last: TrackingTimestamp,
_current: TrackingTimestamp,
) -> bool {
false
}
#[doc(hidden)]
#[inline]
fn is_deleted<T: Component>(
_sparse_set: &SparseSet<T>,
_entity: EntityId,
_last: TrackingTimestamp,
_current: TrackingTimestamp,
) -> bool {
false
}
#[doc(hidden)]
#[inline]
fn is_removed<T: Component>(
_sparse_set: &SparseSet<T>,
_entity: EntityId,
_last: TrackingTimestamp,
_current: TrackingTimestamp,
) -> bool {
false
}
}
pub trait InsertionTracking: Tracking {}
pub trait ModificationTracking: Tracking {}
pub trait RemovalTracking: Tracking + RemovalOrDeletionTracking {}
pub trait DeletionTracking: Tracking + RemovalOrDeletionTracking {}
pub trait RemovalOrDeletionTracking: Tracking {
#[doc(hidden)]
#[allow(clippy::type_complexity)]
fn removed_or_deleted<T: Component>(
sparse_set: &SparseSet<T>,
) -> core::iter::Chain<
core::iter::Map<
core::slice::Iter<'_, (EntityId, TrackingTimestamp, T)>,
fn(&(EntityId, TrackingTimestamp, T)) -> (EntityId, TrackingTimestamp),
>,
core::iter::Copied<core::slice::Iter<'_, (EntityId, TrackingTimestamp)>>,
>;
#[doc(hidden)]
fn clear_all_removed_and_deleted<T: Component>(sparse_set: &mut SparseSet<T>);
#[doc(hidden)]
fn clear_all_removed_and_deleted_older_than_timestamp<T: Component>(
sparse_set: &mut SparseSet<T>,
_timestamp: TrackingTimestamp,
);
}
#[inline]
pub(crate) fn map_deletion_data<T>(
&(entity_id, timestamp, _): &(EntityId, TrackingTimestamp, T),
) -> (EntityId, TrackingTimestamp) {
(entity_id, timestamp)
}
#[derive(Clone, Copy, Debug)]
pub struct TrackingTimestamp(u64);
impl TrackingTimestamp {
#[inline]
pub fn new(now: u64) -> TrackingTimestamp {
TrackingTimestamp(now)
}
#[inline]
pub fn origin() -> TrackingTimestamp {
TrackingTimestamp::new(0)
}
#[inline]
pub(crate) fn get(self) -> u64 {
self.0
}
#[inline]
pub fn is_within(self, last: TrackingTimestamp, current: TrackingTimestamp) -> bool {
last.0 < self.0 && self.0 <= current.0
}
#[inline]
pub fn is_older_than(self, other: TrackingTimestamp) -> bool {
self.0 < other.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_within_bounds() {
let tests = [
(5, 0, 10, true),
(11, 0, 10, false),
(1, 2, 0, false),
(1, 1, 0, false),
(1, 0, 1, true),
];
for (timestamp, last, current, expected) in tests {
assert_eq!(
TrackingTimestamp::new(timestamp).is_within(
TrackingTimestamp::new(last),
TrackingTimestamp::new(current)
),
expected,
"t: {timestamp}, l: {last}, c: {current}"
);
}
}
#[test]
fn is_older() {
let tests = [
(0, 0, false),
(5, 10, true),
(11, 10, false),
(1, 1, false),
];
for (timestamp, other, expected) in tests {
assert_eq!(
TrackingTimestamp::new(timestamp).is_older_than(TrackingTimestamp::new(other)),
expected,
"t: {timestamp}, o: {other}"
);
}
}
}