andex
andex (Array iNDEX) is a single-file, zero-dependency, rust crate that helps us create a strongly-typed, zero-cost, safe array index and the corresponding array type.
This is specially useful in scenarios where we have different arrays
inside a struct and we want reference members without holding "hard"
references. May also be useful when programming an
Entity Component System.
Basic usage
use *;
use impl_andex_for;
// Create the type alias:
type MyIdx = ;
// Create the array wrapper:
;
// Use `impl_andex_for` to make it indexable:
impl_andex_for!;
Creating index instances
When an andex is created, it knows at compile time the size of the array it indexes, and all instances are assumed to be within bounds.
For this reason, it's useful to limit the way andex's are created. The ways we can get an instance is:
-
Via
new, passing the value as a generic const argument:const first = ::This checks that the value is valid at compile time, as long as you use it to create
constvariables. -
Via
try_from, which returnsResult<Andex,Error>that has to be checked or explicitly ignored:if let Ok = try_from -
By iterating:
for idx in iter
The assumption that the instances can only hold valid values allows us
to use get_unsafe and get_unsafe_mut in the indexer
implementation, which provides a bit of optimization by preventing the
bound check when indexing.
Creating the indexable array wrapper
To use the index, we first create the array wrapper, and then use the
impl_andex_for to make it indexable by the andex:
impl_andex_for!;
This macro creates the appropriate Index and IndexMut
implementations. These implementations use get_unchecked and
get_unchecked_mut under the wraps, as the array bounds are checked
when the andex instance is created and we don't have to check them
again.
Note: the user is responsible for making the limit of the andex and the wrapper equal.
Full example
use *;
use TryFrom;
/// A player with score
/// All players in the game
;
/// The player identifier
type PlayerId = ;
// Make Players[PlayerId] work
impl_andex_for!;
/// The game state
Alternatives
These alternatives may fit better cases where we need unbound indexes (into vector, for instance):