1//! The `typed-index-collections` crate provides [`TiSlice`] and [`TiVec`]
2//! structs that are typed index versions of the Rust [`slice`] and
3//! [`std::vec::Vec`] types.
4//!
5//! # Introduction
6//!
7//! The extensive use of slices and vectors instead of references
8//! and smart pointers might be useful for optimization,
9//! Data-Oriented Design and when using Struct of Arrays.
10//! But when dealing with a bunch of slices and vectors
11//! it is easy to accidentally use the wrong index,
12//! which is a common source of bugs.
13//!
14//! # About
15//!
16//! This crate provides [`TiSlice<K, V>`][`TiSlice`] and
17//! [`TiVec<K, V>`][`TiVec`] containers that can be indexed only by the
18//! specified index type `K`. These containers are only wrappers around
19//! the slice primitive [`[V]`][`slice`] and the container
20//! [`std::vec::Vec<V>`][`std::vec::Vec`]. Crate containers mirror the stable
21//! API of the matched Rust containers and forward to them as much as possible.
22//!
23//! [`TiSlice`] and [`TiVec`] can be easily converted to matched Rust containers
24//! and back using [`From`], [`Into`], [`AsRef`] and [`AsMut`] traits.
25//! Also, they expose `raw` property with the original data type.
26//! Containers only require the index to implement
27//! [`From<usize>`][`From`] and [`Into<usize>`][`Into`] traits
28//! that can be easily done with [`derive_more`] crate and
29//! `#[derive(From, Into)]`.
30//!
31//! # Usage
32//!
33//! First, add the following to your `Cargo.toml`:
34//!
35//! ```toml
36//! [dependencies]
37//! typed-index-collections = "3.2.3"
38//! ```
39//!
40//! This crate depends on the standard library by default that is useful
41//! for debugging and for some extra functionality.
42//! To use this crate in a `#![no_std]` context, use `default-features = false`
43//! in your `Cargo.toml` as shown below:
44//!
45//! ```toml
46//! [dependencies.typed-index-collections]
47//! version = "3.2.3"
48//! default-features = false
49//! features = ["alloc"]
50//! ```
51//!
52//! If you want to use [`derive_more`] for
53//! [`From<usize>`][`From`] and [`Into<usize>`][`Into`] implementation
54//! add it to your `Cargo.toml` as shown below:
55//!
56//! ```toml
57//! [dependencies]
58//! derive_more = "0.99"
59//! typed-index-collections = "3.2.3"
60//! ```
61//!
62//! # Examples
63//!
64//! Simple example with [`derive_more`]:
65#![cfg_attr(feature = "alloc", doc = " ```rust")]
66#![cfg_attr(not(feature = "alloc"), doc = " ```rust,compile_fail")]
67//! use typed_index_collections::TiVec;
68//! use derive_more::{From, Into};
69//!
70//! #[derive(From, Into)]
71//! struct FooId(usize);
72//!
73//! let mut ti_vec: TiVec<FooId, usize> = std::vec![10, 11, 13].into();
74//! ti_vec.insert(FooId(2), 12);
75//! assert_eq!(ti_vec[FooId(2)], 12);
76#![doc = " ```"]
77#![doc = ""]
78//! If a wrong index type is used, compilation will fail:
79//! ```compile_fail
80//! use typed_index_collections::TiVec;
81//! use derive_more::{From, Into};
82//!
83//! #[derive(From, Into)]
84//! struct FooId(usize);
85//!
86//! #[derive(From, Into)]
87//! struct BarId(usize);
88//!
89//! let mut ti_vec: TiVec<FooId, usize> = std::vec![10, 11, 13].into();
90//!
91//! ti_vec.insert(BarId(2), 12);
92//! // ^^^^^^^^ expected struct `FooId`, found struct `BarId`
93//! assert_eq!(ti_vec[BarId(2)], 12);
94//! // ^^^^^^^^^^^^^^^^ the trait ... is not implemented for `BarId`
95//! ```
96//!
97//! Another more detailed example with [`derive_more`]:
98#![cfg_attr(feature = "alloc", doc = " ```rust")]
99#![cfg_attr(not(feature = "alloc"), doc = " ```rust,compile_fail")]
100//! use typed_index_collections::{TiSlice, TiVec};
101//! use derive_more::{From, Into};
102//!
103//! #[derive(Clone, Copy, Debug, From, Into, Eq, PartialEq)]
104//! struct FooId(usize);
105//!
106//! #[derive(Clone, Copy, Debug, Eq, PartialEq)]
107//! struct Foo {
108//! value: usize,
109//! }
110//!
111//! let first = Foo { value: 1 };
112//! let second = Foo { value: 2 };
113//!
114//! let slice_ref = &[first, second][..];
115//! let vec = std::vec![first, second];
116//! let boxed_slice = std::vec![first, second].into_boxed_slice();
117//!
118//! let ti_slice_ref: &TiSlice<FooId, Foo> = slice_ref.as_ref();
119//! let ti_vec: TiVec<FooId, Foo> = vec.into();
120//! let ti_boxed_slice: std::boxed::Box<TiSlice<FooId, Foo>> =
121//! boxed_slice.into();
122//!
123//! assert_eq!(ti_vec[FooId(1)], second);
124//! assert_eq!(ti_vec.raw[1], second);
125//! assert_eq!(ti_vec.last(), Some(&second));
126//! assert_eq!(ti_vec.last_key_value(), Some((FooId(1), &second)));
127//! assert_eq!(ti_vec.iter_enumerated().next(), Some((FooId(0), &first)));
128//!
129//! let _slice_ref: &[Foo] = ti_slice_ref.as_ref();
130//! let _vec: std::vec::Vec<Foo> = ti_vec.into();
131//! let _boxed_slice: std::boxed::Box<[Foo]> = ti_boxed_slice.into();
132#![doc = " ```"]
133#![doc = ""]
134//! # Feature Flags
135//!
136//! - `alloc` (implied by `std`, enabled by default): Enables the Rust `alloc`
137//! library, enables [`TiVec`] type, [`ti_vec!`] macro, trait implementations
138//! for [`Box`]`<`[`TiSlice`]`>`, and some [`TiSlice`] methods that require
139//! memory allocation.
140//! - `std` (enabled by default): Enables `alloc` feature, the Rust `std`
141//! library, implements [`std::io::Write`] for [`TiVec`] and implements
142//! [`std::io::Read`] and [`std::io::Write`] for [`TiSlice`],
143//! - `serde`: Implements [`Serialize`] trait for [`TiSlice`] and [`TiVec`]
144//! containers and [`Deserialize`] trait for [`Box`]`<`[`TiSlice`]`>` and
145//! [`TiVec`].
146//!
147//! # Similar crates
148//!
149//! - [`typed_index_collection`] provides a `Vec` wrapper with a very limited
150//! API. Indices are u32 wrappers, they are not customizable and can only
151//! index a specific type of container.
152//! - [`indexed_vec`] is the closest copy of the `IndexVec` struct from
153//! `librustc_index`, but API is also different from standard Rust
154//! [`std::vec::Vec`] and it has no typed index [`slice`] alternative.
155//! - [`index_vec`] have both [`slice`] and [`std::vec::Vec`] wrapper and API
156//! closer to standard API. But it implicitly allows you to use `usize` for
157//! get methods and index expressions that reduce type-safety, and the macro
158//! `define_index_type!` which is used to generate a newtyped index struct,
159//! implicitly implements a lot of traits that in my opinion would be better
160//! implemented only when necessary using crates intended for this, such as
161//! [`derive_more`].
162//!
163//! # License
164//!
165//! Licensed under either of
166//!
167//! - Apache License, Version 2.0 ([LICENSE-APACHE](https://github.com/zheland/typed-index-collections/blob/master/LICENSE-APACHE)
168//! or <https://www.apache.org/licenses/LICENSE-2.0>)
169//! - MIT license ([LICENSE-MIT](https://github.com/zheland/typed-index-collections/blob/master/LICENSE-MIT)
170//! or <https://opensource.org/licenses/MIT>)
171//!
172//! at your option.
173//!
174//! ## Contribution
175//!
176//! Unless you explicitly state otherwise, any contribution intentionally
177//! submitted for inclusion in the work by you, as defined in the Apache-2.0
178//! license, shall be dual licensed as above, without any
179//! additional terms or conditions.
180//!
181//! [`TiSlice`]: struct.TiSlice.html
182//! [`TiVec`]: struct.TiVec.html
183//! [`ti_vec!`]: macro.ti_vec.html
184//! [`slice`]: https://doc.rust-lang.org/std/primitive.slice.html
185//! [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
186//! [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
187//! [`Weak`]: https://doc.rust-lang.org/std/rc/struct.Weak.html
188//! [`std::vec::Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
189//! [`std::io::Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
190//! [`std::io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
191//! [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
192//! [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html
193//! [`AsRef`]: https://doc.rust-lang.org/std/convert/trait.AsRef.html
194//! [`AsMut`]: https://doc.rust-lang.org/std/convert/trait.AsMut.html
195//! [`derive_more`]: https://crates.io/crates/derive_more
196//! [`typed_index_collection`]: https://crates.io/crates/typed_index_collection
197//! [`indexed_vec`]: https://crates.io/crates/indexed_vec
198//! [`index_vec`]: https://crates.io/crates/index_vec
199//! [`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html
200//! [`Deserialize`]: https://docs.serde.rs/serde/trait.Deserialize.html
201
202#![cfg_attr(docsrs, feature(doc_cfg))]
203#![no_std]
204
205#[cfg(any(feature = "alloc", test))]
206extern crate alloc;
207
208#[cfg(feature = "std")]
209extern crate std;
210
211#[cfg(test)]
212#[macro_use]
213mod test_util;
214
215mod iter;
216mod range;
217mod slice;
218
219#[cfg(feature = "alloc")]
220#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
221mod macros;
222#[cfg(feature = "alloc")]
223#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
224mod vec;
225
226pub use iter::{TiEnumerated, TiSliceKeys, TiSliceMutMap, TiSliceRefMap};
227pub use range::TiRangeBounds;
228pub use slice::{TiSlice, TiSliceIndex};
229#[cfg(feature = "alloc")]
230#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
231pub use vec::TiVec;
232
233#[cfg(test)]
234mod integration_tests_deps {
235 use {readme_sync as _, serde_json as _, version_sync as _};
236}
237
238#[doc(hidden)]
239pub mod macro_deps {
240 #[cfg(feature = "alloc")]
241 pub use alloc::vec;
242}
243