Files
wasmtime/lib/entity/src/lib.rs
Dan Gohman 9c87f3ac87 Fix some warnings in no_std builds.
The dbg! macro expands to nothing in no_std mode, so variables that are
only used for debugging prompt unused variable warnings.

Also, allow unstable_features in no_std builds, since they use
feature(alloc), which is an unstable feature.
2018-04-30 14:04:14 -07:00

135 lines
5.3 KiB
Rust

//! Array-based data structures using densely numbered entity references as mapping keys.
//!
//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
//! a couple advantages:
//!
//! - Improved type safety. The various map and set types accept a specific key type, so there is
//! no confusion about the meaning of an array index, as there is with plain arrays.
//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
//! purposes. The entity reference types can be smaller, allowing for more compact data
//! structures.
//!
//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
//! macro provides convenient defaults for types wrapping `u32` which is common.
//!
//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
//! assigning a unique entity reference to each.
//! - [`EntityMap`](struct.EntityMap.html) is used to associate secondary information to an entity.
//! The map is implemented as a simple vector, so it does not keep track of which entities have
//! been inserted. Instead, any unknown entities map to the default value.
//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
//! number of entities. It tracks accurately which entities have been inserted. This is a
//! specialized data structure which can use a lot of memory, so read the documentation before
//! using it.
//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
//! The set is implemented as a simple vector, so it does not keep track of which entities have
//! been inserted into the primary map. Instead, any unknown entities are not in the set.
//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
//! references allocated from an associated memory pool. It has a much smaller footprint than
//! `Vec`.
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "std", warn(unstable_features))]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
#![cfg_attr(feature = "cargo-clippy",
allow(new_without_default, new_without_default_derive))]
#![cfg_attr(feature="cargo-clippy", warn(
float_arithmetic,
mut_mut,
nonminimal_bool,
option_map_unwrap_or,
option_map_unwrap_or_else,
print_stdout,
unicode_not_nfc,
use_self,
))]
// Turns on no_std and alloc features if std is not available.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
/// This replaces `std` in builds with `core`.
#[cfg(not(feature = "std"))]
mod std {
extern crate alloc;
pub use self::alloc::{boxed, string, vec};
pub use core::*;
}
// Re-export core so that the macros works with both std and no_std crates
#[doc(hidden)]
pub extern crate core as __core;
/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `EntityMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
/// Create a new entity reference from a small integer.
/// This should crash if the requested index is not representable.
fn new(usize) -> Self;
/// Get the index that was used to create this entity reference.
fn index(self) -> usize;
}
/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
// Basic traits.
($entity:ident) => {
impl $crate::EntityRef for $entity {
fn new(index: usize) -> Self {
debug_assert!(index < ($crate::__core::u32::MAX as usize));
$entity(index as u32)
}
fn index(self) -> usize {
self.0 as usize
}
}
impl $crate::packed_option::ReservedValue for $entity {
fn reserved_value() -> $entity {
$entity($crate::__core::u32::MAX)
}
}
};
// Include basic `Display` impl using the given display prefix.
// Display an `Ebb` reference as "ebb12".
($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 &$crate::__core::fmt::Display).fmt(f)
}
}
};
}
pub mod packed_option;
mod iter;
mod keys;
mod list;
mod map;
mod primary;
mod set;
mod sparse;
pub use self::iter::{Iter, IterMut};
pub use self::keys::Keys;
pub use self::list::{EntityList, ListPool};
pub use self::map::EntityMap;
pub use self::primary::PrimaryMap;
pub use self::set::EntitySet;
pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};