typed-index-collections

CI Latest Version Documentation GitHub license Rust Version

The typed-index-collections crate provides [TiSlice] and [TiVec] structs that are typed index versions of the Rust [slice] and [std::vec::Vec] types.

Introduction

The extensive use of slices and vectors instead of references and smart pointers might be useful for optimization, Data-Oriented Design and when using Struct of Arrays. But when dealing with a bunch of slices and vectors it is easy to accidentally use the wrong index, which is a common source of bugs.

About

This crate provides [TiSlice<K, V>][TiSlice] and [TiVec<K, V>][TiVec] containers that can be indexed only by the specified index type K. These containers are only wrappers around the slice primitive [[V]][slice] and the container [std::vec::Vec<V>][std::vec::Vec]. Crate containers mirror the stable API of the matched Rust containers and forward to them as much as possible.

[TiSlice] and [TiVec] can be easily converted to matched Rust containers and back using [From], [Into], [AsRef] and [AsMut] traits. Also, they expose raw property with the original data type. Containers only require the index to implement [From<usize>][From] and [Into<usize>][Into] traits that can be easily done with [derive_more] crate and #[derive(From, Into)].

Usage

First, add the following to your Cargo.toml:

toml [dependencies] typed-index-collections = "3.0"

This crate depends on the standard library by default that is useful for debugging and for some extra functionality. To use this crate in a #![no_std] context, use default-features = false in your Cargo.toml as shown below:

toml [dependencies.typed-index-collections] version = "3.0" default-features = false features = ["alloc"]

If you want to use [derive_more] for [From<usize>][From] and [Into<usize>][Into] implementation add it to your Cargo.toml as shown below:

toml [dependencies] derive_more = "0.99" typed-index-collections = "3.0"

Examples

Simple example with [derive_more]: ```rust use typedindexcollections::TiVec; use derive_more::{From, Into};

[derive(From, Into)]

struct FooId(usize);

let mut tivec: TiVec = std::vec![10, 11, 13].into(); tivec.insert(FooId(2), 12); asserteq!(tivec[FooId(2)], 12); ```

If a wrong index type is used, compilation will fail: ```rust use typedindexcollections::TiVec; use derive_more::{From, Into};

[derive(From, Into)]

struct FooId(usize);

[derive(From, Into)]

struct BarId(usize);

let mut ti_vec: TiVec = std::vec![10, 11, 13].into();

tivec.insert(BarId(2), 12); // ^^^^^^^^ expected struct FooId, found struct BarId asserteq!(ti_vec[BarId(2)], 12); // ^^^^^^^^^^^^^^^^ the trait ... is not implemented for BarId ```

Another more detailed example with [derive_more]: ```rust use typedindexcollections::{TiSlice, TiVec}; use derive_more::{From, Into};

[derive(Clone, Copy, Debug, From, Into, Eq, PartialEq)]

struct FooId(usize);

[derive(Clone, Copy, Debug, Eq, PartialEq)]

struct Foo { value: usize, }

let first = Foo { value: 1 }; let second = Foo { value: 2 };

let sliceref = &[first, second][..]; let vec = std::vec![first, second]; let boxedslice = std::vec![first, second].intoboxedslice();

let tisliceref: &TiSlice = sliceref.asref(); let tivec: TiVec = vec.into(); let tiboxedslice: std::boxed::Box> = boxedslice.into();

asserteq!(tivec[FooId(1)], second); asserteq!(tivec.raw[1], second); asserteq!(tivec.last(), Some(&second)); asserteq!(tivec.lastkeyvalue(), Some((FooId(1), &second))); asserteq!(tivec.iter_enumerated().next(), Some((FooId(0), &first)));

let sliceref: &[Foo] = tisliceref.asref(); let _vec: std::vec::Vec = tivec.into(); let boxedslice: std::boxed::Box<[Foo]> = tiboxedslice.into(); ```

Documentation

[API Documentation]

Feature Flags

Similar crates

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.