#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
#![cfg_attr(
feature = "cargo-clippy",
warn(
clippy::float_arithmetic,
clippy::mut_mut,
clippy::nonminimal_bool,
clippy::map_unwrap_or,
clippy::clippy::print_stdout,
clippy::unicode_not_nfc,
clippy::use_self
)
)]
#![no_std]
extern crate alloc;
#[doc(hidden)]
pub extern crate core as __core;
pub trait EntityRef: Copy + Eq {
fn new(_: usize) -> Self;
fn index(self) -> usize;
}
#[macro_export]
macro_rules! entity_impl {
($entity:ident) => {
impl $crate::EntityRef for $entity {
#[inline]
fn new(index: usize) -> Self {
debug_assert!(index < ($crate::__core::u32::MAX as usize));
$entity(index as u32)
}
#[inline]
fn index(self) -> usize {
self.0 as usize
}
}
impl $crate::packed_option::ReservedValue for $entity {
#[inline]
fn reserved_value() -> $entity {
$entity($crate::__core::u32::MAX)
}
#[inline]
fn is_reserved_value(&self) -> bool {
self.0 == $crate::__core::u32::MAX
}
}
impl $entity {
#[allow(dead_code)]
#[inline]
pub fn from_u32(x: u32) -> Self {
debug_assert!(x < $crate::__core::u32::MAX);
$entity(x)
}
#[allow(dead_code)]
#[inline]
pub fn as_u32(self) -> u32 {
self.0
}
#[allow(dead_code)]
#[inline]
pub fn as_bits(self) -> u32 {
self.0
}
#[allow(dead_code)]
#[inline]
pub fn from_bits(x: u32) -> Self {
$entity(x)
}
}
};
($entity:ident, $display_prefix:expr) => {
entity_impl!($entity);
impl $crate::__core::fmt::Display for $entity {
fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
write!(f, concat!($display_prefix, "{}"), self.0)
}
}
impl $crate::__core::fmt::Debug for $entity {
fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
(self as &dyn $crate::__core::fmt::Display).fmt(f)
}
}
};
($entity:ident, $display_prefix:expr, $arg:ident, $to_expr:expr, $from_expr:expr) => {
impl $crate::EntityRef for $entity {
#[inline]
fn new(index: usize) -> Self {
debug_assert!(index < ($crate::__core::u32::MAX as usize));
let $arg = index as u32;
$to_expr
}
#[inline]
fn index(self) -> usize {
let $arg = self;
$from_expr as usize
}
}
impl $crate::packed_option::ReservedValue for $entity {
#[inline]
fn reserved_value() -> $entity {
$entity::from_u32($crate::__core::u32::MAX)
}
#[inline]
fn is_reserved_value(&self) -> bool {
self.as_u32() == $crate::__core::u32::MAX
}
}
impl $entity {
#[allow(dead_code)]
#[inline]
pub fn from_u32(x: u32) -> Self {
debug_assert!(x < $crate::__core::u32::MAX);
let $arg = x;
$to_expr
}
#[allow(dead_code)]
#[inline]
pub fn as_u32(self) -> u32 {
let $arg = self;
$from_expr
}
}
impl $crate::__core::fmt::Display for $entity {
fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
write!(f, concat!($display_prefix, "{}"), self.as_u32())
}
}
impl $crate::__core::fmt::Debug for $entity {
fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
(self as &dyn $crate::__core::fmt::Display).fmt(f)
}
}
};
}
pub mod packed_option;
mod boxed_slice;
mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;
pub use self::boxed_slice::BoxedSlice;
pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::SecondaryMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};
#[cfg(test)]
mod tests {
macro_rules! entity_test {
($entity:ident) => {
#[test]
fn from_usize_to_u32() {
let e = $entity::new(42);
assert_eq!(e.as_u32(), 42_u32);
}
#[test]
fn from_u32_to_usize() {
let e = $entity::from_u32(42);
assert_eq!(e.index(), 42_usize);
}
#[test]
fn comparisons_work() {
let a = $entity::from_u32(42);
let b = $entity::new(42);
assert_eq!(a, b);
}
#[should_panic]
#[test]
fn cannot_construct_from_reserved_u32() {
use crate::packed_option::ReservedValue;
let reserved = $entity::reserved_value().as_u32();
let _ = $entity::from_u32(reserved); }
#[should_panic]
#[test]
fn cannot_construct_from_reserved_usize() {
use crate::packed_option::ReservedValue;
let reserved = $entity::reserved_value().index();
let _ = $entity::new(reserved); }
};
}
mod basic_entity {
use crate::EntityRef;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct BasicEntity(u32);
entity_impl!(BasicEntity);
entity_test!(BasicEntity);
}
mod prefix_entity {
use crate::EntityRef;
#[derive(Clone, Copy, PartialEq, Eq)]
struct PrefixEntity(u32);
entity_impl!(PrefixEntity, "prefix-");
entity_test!(PrefixEntity);
#[test]
fn display_prefix_works() {
let e = PrefixEntity::new(0);
assert_eq!(alloc::format!("{}", e), "prefix-0");
}
}
mod other_entity {
mod inner {
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct InnerEntity(u32);
impl From<u32> for InnerEntity {
fn from(x: u32) -> Self {
Self(x)
}
}
impl From<InnerEntity> for u32 {
fn from(x: InnerEntity) -> Self {
x.0
}
}
}
use {self::inner::InnerEntity, crate::EntityRef};
entity_impl!(InnerEntity, "inner-", i, InnerEntity::from(i), u32::from(i));
entity_test!(InnerEntity);
#[test]
fn display_prefix_works() {
let e = InnerEntity::new(0);
assert_eq!(alloc::format!("{}", e), "inner-0");
}
}
}