index_vec
This crate helps with defining "newtype"-style wrappers around usize
(or
other integers), and Vec<T>
so that some additional type safety can be
gained at zero cost.
```rust use indexvec::{IndexVec, IndexSlice, indexvec};
indexvec::defineindex_type! { // Define StrIdx to use only 32 bits internally (you can use usize, u16, // and even u8). pub struct StrIdx = u32;
// The defaults are very reasonable, but this macro can let
// you customize things quite a bit:
// By default, creating a StrIdx would check an incoming `usize against
// `u32::max_value()`, as u32 is the wrapped index type. Lets imagine that
// StrIdx has to interface with an external system that uses signed ints.
// We can change the checking behavior to complain on i32::max_value()
// instead:
MAX_INDEX = i32::max_value() as usize;
// We can also disable checking all-together if we are more concerned with perf
// than any overflow problems, or even do so, but only for debug builds: Quite
// pointless here, but an okay example
DISABLE_MAX_INDEX_CHECK = cfg!(not(debug_assertions));
// And more too, see this macro's docs for more info.
}
// Create a vector which can be accessed using StrIdx
s.
let mut strs: IndexVec
// l is a StrIdx
let l = strs.lastidx();
asserteq!(strs[l], "baz");
let newi = strs.push("quux"); asserteq!(strs[new_i], "quux");
// The slice APIs are wrapped as well.
let s: &IndexSlice // Indices are mostly interoperable with // Comparison
assert_eq!(StrIdx::new(0), 0usize); // Addition
assert_eq!(StrIdx::new(0) + 1, StrIdx::new(1)); // Subtraction
assert_eq!(StrIdx::new(1) - 1, StrIdx::new(0)); // Wrapping
assert_eq!(StrIdx::new(5) % strs.len(), StrIdx::new(1));
// ...
``` The goal is to help with the pattern of using a The code was originally based on The If you're looking for something further from a vec and closer to a map, you
might find Probably. It's not a proc macro because I tend to avoid them where possible
due to wanting to minimize compile times. If the issues around proc-macro
compile times are fixed, then I'll revisit this. I also may eventually add a proc-macro feature which is not required, but
avoids some of the grossness. Possibly. It defines a type, implements a bunch of functions on it, and
quite a few traits. That said, it's intended to be a very painless journey
from I'm open to suggestions. Yes, although it uses Yes, but only if you turn on the Planned is a bit strong but here are the things I would find useful. This is based on code from usize
, and support
// a lot of what you might want to do to an index.Background
type FooIdx = usize
to
access a Vec<Foo>
with something that can statically prevent using a
FooIdx
in a Vec<Bar>
. It's most useful if you have a bunch of indices
referring to different sorts of vectors.rustc
's IndexVec
code, however that has
been almost entirely rewritten (except for the cases where it's trivial,
e.g. the Vec wrapper).Other crates
indexed_vec
crate predates
this, and is a much closer copy of the code from rustc
. Unfortunately,
this means it does not compile on stable.handy
,
slotmap
, or
slab
to be closer what you want.FAQ
Wouldn't
define_index_type
be better as a proc macro?Does
define_index_type
do too much?Vec<T>
+ usize
to IndexVec<I, T>
. If it left it up to the
developer to do those things, it would be too annoying to be worth using.The syntax for the options in
define_index_type
is terrible.Does it support no_std?
extern crate alloc;
, of course.Does it support serde?
serde
feature.What features are planned?
feature
, of
course).License
rustc
's source, and retains it's status as
dual-licensed under MIT (LICENSE-MIT) / Apache 2.0 (LICENSE-APACHE).