Skip to main content

cranelift_entity/
lib.rs

1//! Array-based data structures using densely numbered entity references as mapping keys.
2//!
3//! This crate defines a number of data structures based on arrays. The arrays are not indexed by
4//! `usize` as usual, but by *entity references* which are integers wrapped in new-types. This has
5//! a couple advantages:
6//!
7//! - Improved type safety. The various map and set types accept a specific key type, so there is
8//!   no confusion about the meaning of an array index, as there is with plain arrays.
9//! - Smaller indexes. The normal `usize` index is often 64 bits which is way too large for most
10//!   purposes. The entity reference types can be smaller, allowing for more compact data
11//!   structures.
12//!
13//! The `EntityRef` trait should be implemented by types to be used as indexed. The `entity_impl!`
14//! macro provides convenient defaults for types wrapping `u32` which is common.
15//!
16//! - [`PrimaryMap`](struct.PrimaryMap.html) is used to keep track of a vector of entities,
17//!   assigning a unique entity reference to each.
18//! - [`SecondaryMap`](struct.SecondaryMap.html) is used to associate secondary information to an
19//!   entity. The map is implemented as a simple vector, so it does not keep track of which
20//!   entities have been inserted. Instead, any unknown entities map to the default value.
21//! - [`SparseMap`](struct.SparseMap.html) is used to associate secondary information to a small
22//!   number of entities. It tracks accurately which entities have been inserted. This is a
23//!   specialized data structure which can use a lot of memory, so read the documentation before
24//!   using it.
25//! - [`EntitySet`](struct.EntitySet.html) is used to represent a secondary set of entities.
26//!   The set is implemented as a simple vector, so it does not keep track of which entities have
27//!   been inserted into the primary map. Instead, any unknown entities are not in the set.
28//! - [`EntityList`](struct.EntityList.html) is a compact representation of lists of entity
29//!   references allocated from an associated memory pool. It has a much smaller footprint than
30//!   `Vec`.
31
32#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
33#![warn(unused_import_braces)]
34#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
35#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
36#![cfg_attr(
37    feature = "cargo-clippy",
38    warn(
39        clippy::float_arithmetic,
40        clippy::mut_mut,
41        clippy::nonminimal_bool,
42        clippy::option_map_unwrap_or,
43        clippy::option_map_unwrap_or_else,
44        clippy::print_stdout,
45        clippy::unicode_not_nfc,
46        clippy::use_self
47    )
48)]
49#![no_std]
50
51extern crate alloc;
52
53// Re-export core so that the macros works with both std and no_std crates
54#[doc(hidden)]
55pub extern crate core as __core;
56
57/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
58/// of an `SecondaryMap` or `SparseMap`.
59pub trait EntityRef: Copy + Eq {
60    /// Create a new entity reference from a small integer.
61    /// This should crash if the requested index is not representable.
62    fn new(_: usize) -> Self;
63
64    /// Get the index that was used to create this entity reference.
65    fn index(self) -> usize;
66}
67
68/// Macro which provides the common implementation of a 32-bit entity reference.
69#[macro_export]
70macro_rules! entity_impl {
71    // Basic traits.
72    ($entity:ident) => {
73        impl $crate::EntityRef for $entity {
74            fn new(index: usize) -> Self {
75                debug_assert!(index < ($crate::__core::u32::MAX as usize));
76                $entity(index as u32)
77            }
78
79            fn index(self) -> usize {
80                self.0 as usize
81            }
82        }
83
84        impl $crate::packed_option::ReservedValue for $entity {
85            fn reserved_value() -> $entity {
86                $entity($crate::__core::u32::MAX)
87            }
88        }
89
90        impl $entity {
91            /// Return the underlying index value as a `u32`.
92            #[allow(dead_code)]
93            pub fn from_u32(x: u32) -> Self {
94                debug_assert!(x < $crate::__core::u32::MAX);
95                $entity(x)
96            }
97
98            /// Return the underlying index value as a `u32`.
99            #[allow(dead_code)]
100            pub fn as_u32(self) -> u32 {
101                self.0
102            }
103        }
104    };
105
106    // Include basic `Display` impl using the given display prefix.
107    // Display an `Ebb` reference as "ebb12".
108    ($entity:ident, $display_prefix:expr) => {
109        entity_impl!($entity);
110
111        impl $crate::__core::fmt::Display for $entity {
112            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
113                write!(f, concat!($display_prefix, "{}"), self.0)
114            }
115        }
116
117        impl $crate::__core::fmt::Debug for $entity {
118            fn fmt(&self, f: &mut $crate::__core::fmt::Formatter) -> $crate::__core::fmt::Result {
119                (self as &dyn $crate::__core::fmt::Display).fmt(f)
120            }
121        }
122    };
123}
124
125pub mod packed_option;
126
127mod boxed_slice;
128mod iter;
129mod keys;
130mod list;
131mod map;
132mod primary;
133mod set;
134mod sparse;
135
136pub use self::boxed_slice::BoxedSlice;
137pub use self::iter::{Iter, IterMut};
138pub use self::keys::Keys;
139pub use self::list::{EntityList, ListPool};
140pub use self::map::SecondaryMap;
141pub use self::primary::PrimaryMap;
142pub use self::set::EntitySet;
143pub use self::sparse::{SparseMap, SparseMapValue, SparseSet};