index_type
A Rust library providing strongly typed indices for collections, designed for both std and no_std environments.
What are typed indices?
In standard Rust, collections use usize for indexing. This works well but provides no compile-time
protection against using an index from one collection with another. Typed indices solve this by
creating custom index types that are statically associated with specific collections.
Consider this bug in standard Rust:
let nodes = vec!;
let edges = vec!;
let bad_index = 3;
nodes; // Works fine
edges; // Also works, but may be a bug if you meant nodes[bad_index]
With typed indices, this becomes a compile error:
;
;
let nodes: = ...;
let edges: = ...;
let id = NodeId;
nodes; // OK
edges; // COMPILE ERROR: expected EdgeId, found NodeId
Features
- Type Safety: Prevents accidental misuse of indices between different collections at compile time
no_stdSupport: Works in embedded systems and otherno_stdenvironments- Memory Efficiency: Use smaller integer types (
u8,u16) for indices when collections are bounded - Niche Optimization: Supports
NonZerotypes soOption<Index>has the same size asIndex - Rich Collections: Provides
TypedSlice,TypedVec,TypedArray, andTypedArrayVec - Derive Macros: Easy to define custom index types with
#[derive(IndexType)] - Range Iterators: Iterate over ranges using custom index types
Quick Start
use IndexType;
use TypedVec;
;
let mut vec: = new;
let idx = vec.push;
assert_eq!;
// vec[0usize]; // This won't compile - requires MyIndex type
Defining Index Types
Use the #[derive(IndexType)] macro on a newtype struct:
use IndexType;
;
The macro automatically implements the [IndexType] trait for your custom type. By default,
it generates an error type MyIndexTooBigError. You can specify a custom error type:
use IndexType;
use IndexTooBigError;
;
;
Typed Collections
TypedVec
A growable vector with typed indexing. See TypedVec for the full API.
use IndexType;
use TypedVec;
;
let mut nodes: = new;
let id0 = nodes.push;
let id1 = nodes.push;
println!;
Operations that can fail due to index overflow have both panicking and fallible variants:
let mut vec: = new;
vec.push; // Panics if index too big
let result = vec.try_push; // Returns Result<(), Error>
TypedSlice
A slice wrapper with typed indexing. See TypedSlice for the full API.
use IndexType;
use TypedVec;
use TypedSlice;
;
let vec: = from_vec;
let slice: & = vec.as_slice;
// Safe indexing with custom type
let first = slice;
TypedArray
A fixed-size array with typed indexing. The array length N is checked at compile time
to ensure it fits within the index type's range. See TypedArray for the full API.
use IndexType;
use TypedArray;
;
let mut pixels: = default;
pixels = ; // Red
pixels = ; // Green
TypedArrayVec
A fixed-capacity vector ideal for embedded systems. It never allocates after creation.
See TypedArrayVec for the full API.
use IndexType;
use TypedArrayVec;
;
let mut buffer: = new;
buffer.push;
assert_eq!;
A TypedArrayVec<u8, u8, 3> is only 4 bytes (3 bytes for data + 1 byte for length).
Memory-Efficient Indices
Using smaller integer types reduces memory when storing many indices:
; // Only 1 byte per index!
println!;
println!;
For collections with at most 255 elements, u8 saves 75% memory compared to u32.
NonZero Indices and Niche Optimization
Using NonZero types enables niche optimization, where Option<Index>
has the same size as Index:
use IndexType;
use NonZeroU32;
;
// Option<SafeId> takes only 4 bytes, not 8!
assert_eq!;
assert_eq!;
Range Iterators
Standard Rust ranges require the unstable Step trait. This crate provides
TypedRangeIterExt for iterating over ranges with custom index types:
use IndexType;
use TypedRangeIterExt;
;
let start = MyIdx;
let end = MyIdx;
for idx in .iter
Typed Enumerate
Use TypedIteratorExt to enumerate any iterator with typed indices:
use IndexType;
use TypedIteratorExt;
;
let pairs: =
.into_iter
.
.collect;
assert_eq!;
assert_eq!;
Macros
Convenience macros for creating typed collections:
use ;
use TypedVec;
use TypedArray;
use TypedArrayVec;
use TypedSlice;
;
// Create a TypedVec
let v: = typed_vec!;
// Create a TypedArray
let a: = typed_array!;
// Create a TypedArrayVec
let av: = typed_array_vec!;
// Create a TypedSlice reference
let s: & = typed_slice!;
Error Handling
Operations that can fail due to index overflow return Result types:
use IndexType;
use TypedVec;
; // MAX_RAW_INDEX = 255
let mut vec: = new;
// Fill up to capacity
for i in 0..255
// This fails gracefully
assert!;
no_std Compatibility
This crate is no_std compatible. The alloc feature (enabled by default) enables
heap-allocated collections (TypedVec and related macros).
For pure no_std environments without heap allocation, disable the alloc feature:
[]
= { = "0.1", = false }