oxc_index/
lib.rs

1//! This crate is a fork of `index_vec`, <https://github.com/thomcc/index_vec>
2//! It helps with defining "newtype"-style wrappers around `usize` (or
3//! other integers), `Vec<T>`, and `[T]` so that some additional type safety can
4//! be gained at zero cost.
5//!
6//! ## Example / Overview
7//! ```rust
8//! use oxc_index::{IndexVec, IndexSlice, index_vec};
9//!
10//! oxc_index::define_index_type! {
11//!     // Define StrIdx to use only 32 bits internally (you can use usize, u16,
12//!     // and even u8).
13//!     pub struct StrIdx = u32;
14//!
15//!     // The defaults are very reasonable, but this macro can let
16//!     // you customize things quite a bit:
17//!
18//!     // By default, creating a StrIdx would check an incoming `usize against
19//!     // `u32::max_value()`, as u32 is the wrapped index type. Lets imagine that
20//!     // StrIdx has to interface with an external system that uses signed ints.
21//!     // We can change the checking behavior to complain on i32::max_value()
22//!     // instead:
23//!     MAX_INDEX = i32::max_value() as usize;
24//!
25//!     // We can also disable checking all-together if we are more concerned with perf
26//!     // than any overflow problems, or even do so, but only for debug builds: Quite
27//!     // pointless here, but an okay example
28//!     DISABLE_MAX_INDEX_CHECK = cfg!(not(debug_assertions));
29//!
30//!     // And more too, see this macro's docs for more info.
31//! }
32//!
33//! // Create a vector which can be accessed using `StrIdx`s.
34//! let mut strs: IndexVec<StrIdx, &'static str> = index_vec!["strs", "bar", "baz"];
35//!
36//! // l is a `StrIdx`
37//! let l = strs.last_idx();
38//! assert_eq!(strs[l], "baz");
39//!
40//! let new_i = strs.push("quux");
41//! assert_eq!(strs[new_i], "quux");
42//!
43//! // The slice APIs are wrapped as well.
44//! let s: &IndexSlice<StrIdx, [&'static str]> = &strs[StrIdx::new(1)..];
45//! assert_eq!(s[0], "bar");
46//!
47//! // Indices are mostly interoperable with `usize`, and support
48//! // a lot of what you might want to do to an index.
49//!
50//! // Comparison
51//! assert_eq!(StrIdx::new(0), 0usize);
52//!
53//! // Addition
54//! assert_eq!(StrIdx::new(0) + 1, 1usize);
55//!
56//! // Subtraction
57//! assert_eq!(StrIdx::new(1) - 1, 0usize);
58//!
59//! // Wrapping
60//! assert_eq!(StrIdx::new(5) % strs.len(), 1usize);
61//! // ...
62//! ```
63//! ## Background
64//!
65//! The goal is to help with the pattern of using a `type FooIdx = usize` to
66//! access a `Vec<Foo>` with something that can statically prevent using a
67//! `FooIdx` in a `Vec<Bar>`. It's most useful if you have a bunch of indices
68//! referring to different sorts of vectors.
69//!
70//! The code was originally based on `rustc`'s `IndexVec` code, however that has
71//! been almost entirely rewritten (except for the cases where it's trivial,
72//! e.g. the Vec wrapper).
73//!
74//! ## Other crates
75//!
76//! The [`indexed_vec`](https://crates.io/crates/indexed_vec) crate predates
77//! this, and is a much closer copy of the code from `rustc`. Unfortunately,
78//! this means it does not compile on stable.
79//!
80//! If you're looking for something further from a vec and closer to a map, you
81//! might find [`handy`](https://crates.io/crates/handy),
82//! [`slotmap`](https://crates.io/crates/slotmap), or
83//! [`slab`](https://crates.io/crates/slab) to be closer what you want.
84//!
85//! ## FAQ
86//!
87//! #### Wouldn't `define_index_type` be better as a proc macro?
88//!
89//! Probably. It's not a proc macro because I tend to avoid them where possible
90//! due to wanting to minimize compile times. If the issues around proc-macro
91//! compile times are fixed, then I'll revisit this.
92//!
93//! I also may eventually add a proc-macro feature which is not required, but
94//! avoids some of the grossness.
95//!
96//! #### Does `define_index_type` do too much?
97//!
98//! Possibly. It defines a type, implements a bunch of functions on it, and
99//! quite a few traits. That said, it's intended to be a very painless journey
100//! from `Vec<T>` + `usize` to `IndexVec<I, T>`. If it left it up to the
101//! developer to do those things, it would be too annoying to be worth using.
102//!
103//! #### The syntax for the options in `define_index_type` is terrible.
104//!
105//! I'm open to suggestions.
106//!
107//! #### Does it support no_std?
108//!
109//! Yes, although it uses `extern crate alloc;`, of course.
110//!
111//! #### Does it support serde?
112//!
113//! Yes, but only if you turn on the `serialize` feature.
114//!
115//! #### Does it support NonMaxU32?
116//!
117//! Yes! With the `nonmax` feature enabled, you can use the `define_nonmax_u32_index_type!` macro
118//! to create index types backed by `NonMaxU32` from the `nonmax` crate. This is useful for
119//! memory-efficient `Option<Index>` representations.
120//!
121//! ```rust,ignore
122//! oxc_index::define_nonmax_u32_index_type! {
123//!     pub struct MyIndex;
124//! }
125//! ```
126//!
127//! #### What features are planned?
128//!
129//! Planned is a bit strong but here are the things I would find useful.
130//!
131//! - Support any remaining parts of the slice/vec api.
132//! - Add typesafe wrappers for SmallVec/ArrayVec (behind a cargo `feature`, of
133//!   course).
134//! - Better syntax for the define_index_type macro (no concrete ideas).
135//! - Allow the generated type to be a tuple struct, or use a specific field
136//!   name.
137//! - Allow use of indices for string types (the primary benefit here would
138//!   probably be the ability to e.g. use u32 without too much pain rather than
139//!   mixing up indices from different strings -- but you never know!)
140//! - ...
141//!
142#![allow(clippy::inline_always)]
143#![allow(clippy::partialeq_ne_impl)]
144#![no_std]
145extern crate alloc;
146
147use alloc::{
148    borrow::{Cow, ToOwned},
149    boxed::Box,
150    vec,
151    vec::Vec,
152};
153use core::{
154    borrow::{Borrow, BorrowMut},
155    fmt,
156    fmt::Debug,
157    hash::Hash,
158    iter::{self, FromIterator},
159    marker::PhantomData,
160    ops::Range,
161    slice,
162};
163mod idxslice;
164mod indexing;
165pub use idxslice::{IndexBox, IndexSlice};
166pub use indexing::{IdxRangeBounds, IdxSliceIndex};
167#[cfg(feature = "nonmax")]
168pub use nonmax;
169#[cfg(feature = "rayon")]
170pub use rayon_impl::*;
171#[cfg(feature = "serde")]
172pub use serde;
173#[cfg(feature = "rayon")]
174mod rayon_impl;
175
176#[macro_use]
177mod macros;
178
179/// Represents a wrapped value convertible to and from a `usize`.
180///
181/// Generally you implement this via the [`define_index_type!`] macro, rather
182/// than manually implementing it.
183///
184/// # Overflow
185///
186/// `Idx` impls are allowed to be smaller than `usize`, which means converting
187/// `usize` to an `Idx` implementation might have to handle overflow.
188///
189/// The way overflow is handled is up to the implementation of `Idx`, but it's
190/// generally panicking, unless it was turned off via the
191/// `DISABLE_MAX_INDEX_CHECK` option in [`define_index_type!`]. If you need more
192/// subtle handling than this, then you're on your own (or, well, either handle
193/// it earlier, or pick a bigger index type).
194///
195/// Note: I'm open for suggestions on how to handle this case, but do not want
196/// the typical cases (E.g. Idx is a newtyped `usize` or `u32`), to become more
197/// complex.
198pub trait Idx: Copy + 'static + Ord + Debug + Hash {
199    /// The maximum value that can be represented by this index type.
200    const MAX: usize;
201
202    /// Construct an index from a `usize` without bounds checking.
203    ///
204    /// # Safety
205    /// The caller must ensure that `idx <= Self::MAX`.
206    unsafe fn from_usize_unchecked(idx: usize) -> Self;
207
208    /// Get the underlying index. This is equivalent to `Into<usize>`
209    fn index(self) -> usize;
210
211    /// Construct an Index from a `usize`. This is equivalent to `From<usize>`.
212    ///
213    /// Note that this will panic if `idx` does not fit (unless checking has
214    /// been disabled, as mentioned above). Also note that `Idx` implementations
215    /// are free to define what "fit" means as they desire.
216    fn from_usize(idx: usize) -> Self {
217        assert!(idx <= Self::MAX);
218        // SAFETY: We checked `idx` is valid
219        unsafe { Self::from_usize_unchecked(idx) }
220    }
221}
222
223/// A macro equivalent to the stdlib's `vec![]`, but producing an `IndexVec`.
224#[macro_export]
225macro_rules! index_vec {
226    ($($tokens:tt)*) => {
227        $crate::IndexVec::from_vec(vec![$($tokens)*])
228    }
229}
230
231/// A macro similar to the stdlib's `vec![]`, but producing an
232/// `Box<IndexSlice<I, [T]>>` (That is, an `IndexBox<I, [T]>`).
233#[macro_export]
234macro_rules! index_box {
235    ($($tokens:tt)*) => {
236        $crate::IndexVec::from_vec(vec![$($tokens)*]).into_boxed_slice()
237    }
238}
239
240/// A Vec that only accepts indices of a specific type.
241///
242/// This is a thin wrapper around `Vec`, to the point where the backing vec is a
243/// public property (called `raw`). This is in part because I know this API is
244/// not a complete mirror of Vec's (patches welcome). In the worst case, you can
245/// always do what you need to the Vec itself.
246///
247/// Note that this implements Deref/DerefMut to [`IndexSlice`], and so all the
248/// methods on IndexSlice are available as well. See it's documentation for some
249/// further information.
250///
251/// The following extensions to the Vec APIs are added (in addition to the ones
252/// mentioned in IndexSlice's documentation):
253///
254/// - [`IndexVec::next_idx`], [`IndexSlice::last_idx`] give the next and most
255///   recent index returned by `push`.
256/// - [`IndexVec::push`] returns the index the item was inserted at.
257#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
258pub struct IndexVec<I: Idx, T> {
259    /// Our wrapped Vec.
260    pub raw: Vec<T>,
261    _marker: PhantomData<fn(&I)>,
262}
263
264// SAFETY: Whether `IndexVec` is `Send` depends only on the data,
265// not the phantom data.
266unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
267
268impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexVec<I, T> {
269    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
270        fmt::Debug::fmt(&self.raw, fmt)
271    }
272}
273type Enumerated<Iter, I, T> = iter::Map<iter::Enumerate<Iter>, fn((usize, T)) -> (I, T)>;
274
275impl<I: Idx, T> IndexVec<I, T> {
276    /// Construct a new IndexVec.
277    #[inline]
278    pub const fn new() -> Self {
279        IndexVec { raw: Vec::new(), _marker: PhantomData }
280    }
281
282    /// Construct a `IndexVec` from a `Vec<T>`.
283    ///
284    /// Panics if it's length is too large for our index type.
285    #[inline]
286    pub fn from_vec(vec: Vec<T>) -> Self {
287        // See if `I::from_usize` might be upset by this length.
288        let _ = I::from_usize(vec.len());
289        IndexVec { raw: vec, _marker: PhantomData }
290    }
291
292    /// Construct an IndexVec that can hold at least `capacity` items before
293    /// reallocating. See [`Vec::with_capacity`].
294    #[inline]
295    pub fn with_capacity(capacity: usize) -> Self {
296        IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData }
297    }
298
299    /// Similar to `self.into_iter().enumerate()` but with indices of `I` and
300    /// not `usize`.
301    #[inline(always)]
302    pub fn into_iter_enumerated(self) -> Enumerated<vec::IntoIter<T>, I, T> {
303        self.raw.into_iter().enumerate().map(|(i, t)| (I::from_usize(i), t))
304    }
305
306    /// Creates a splicing iterator that replaces the specified range in the
307    /// vector with the given `replace_with` iterator and yields the removed
308    /// items. See [`Vec::splice`]
309    #[inline]
310    pub fn splice<R, It>(
311        &mut self,
312        range: R,
313        replace_with: It,
314    ) -> vec::Splice<'_, <It as IntoIterator>::IntoIter>
315    where
316        It: IntoIterator<Item = T>,
317        R: IdxRangeBounds<I>,
318    {
319        self.raw.splice(range.into_range(), replace_with)
320    }
321
322    /// Similar to `self.drain(r).enumerate()` but with indices of `I` and not
323    /// `usize`.
324    #[inline]
325    pub fn drain_enumerated<R: IdxRangeBounds<I>>(
326        &mut self,
327        range: R,
328    ) -> Enumerated<vec::Drain<'_, T>, I, T> {
329        self.raw.drain(range.into_range()).enumerate().map(|(i, t)| (I::from_usize(i), t))
330    }
331
332    /// Gives the next index that will be assigned when `push` is
333    /// called.
334    #[inline]
335    pub fn next_idx(&self) -> I {
336        I::from_usize(self.len())
337    }
338
339    /// Get a the storage as a `&[T]`
340    #[inline(always)]
341    pub fn as_raw_slice(&self) -> &[T] {
342        &self.raw
343    }
344
345    /// Get a the storage as a `&mut [T]`
346    #[inline(always)]
347    pub fn as_raw_slice_mut(&mut self) -> &mut [T] {
348        &mut self.raw
349    }
350
351    /// Equivalent to accessing our `raw` field, but as a function.
352    #[inline(always)]
353    pub const fn as_vec(&self) -> &Vec<T> {
354        &self.raw
355    }
356
357    /// Equivalent to accessing our `raw` field mutably, but as a function, if
358    /// that's what you'd prefer.
359    #[inline(always)]
360    pub const fn as_mut_vec(&mut self) -> &mut Vec<T> {
361        &mut self.raw
362    }
363
364    /// Push a new item onto the vector, and return it's index.
365    #[inline]
366    pub fn push(&mut self, d: T) -> I {
367        let len = self.len();
368        // SAFETY: The length of a Vec is always valid for indexing.
369        // If len > I::MAX, the Vec would have panicked on allocation long before this point,
370        // as it cannot allocate more than isize::MAX bytes (and typically much less).
371        let idx = unsafe { I::from_usize_unchecked(len) };
372        self.raw.push(d);
373        idx
374    }
375
376    /// Pops the last item off, returning it. See [`Vec::pop`].
377    #[inline]
378    pub fn pop(&mut self) -> Option<T> {
379        self.raw.pop()
380    }
381
382    /// Converts the vector into an owned [`IndexSlice`], dropping excess capacity.
383    #[inline]
384    pub fn into_boxed_slice(self) -> Box<IndexSlice<I, [T]>> {
385        let b = self.raw.into_boxed_slice();
386        // SAFETY: `IndexSlice` is a thin wrapper around `[T]` with the added marker for the index.
387        unsafe { Box::from_raw(Box::into_raw(b) as *mut IndexSlice<I, [T]>) }
388    }
389
390    /// Return an iterator that removes the items from the requested range. See
391    /// [`Vec::drain`].
392    ///
393    /// See also [`IndexVec::drain_enumerated`], which gives you indices (of the
394    /// correct type) as you iterate.
395    #[inline]
396    pub fn drain<R: IdxRangeBounds<I>>(&mut self, range: R) -> vec::Drain<'_, T> {
397        self.raw.drain(range.into_range())
398    }
399
400    /// Shrinks the capacity of the vector as much as possible.
401    #[inline]
402    pub fn shrink_to_fit(&mut self) {
403        self.raw.shrink_to_fit();
404    }
405
406    /// Shrinks the capacity of the vector with a lower bound.
407    #[inline]
408    pub fn shrink_to(&mut self, min_capacity: usize) {
409        self.raw.shrink_to(min_capacity);
410    }
411
412    /// Shortens the vector, keeping the first `len` elements and dropping
413    /// the rest. See [`Vec::truncate`]
414    #[inline]
415    pub fn truncate(&mut self, a: usize) {
416        self.raw.truncate(a);
417    }
418
419    /// Clear our vector. See [`Vec::clear`].
420    #[inline]
421    pub fn clear(&mut self) {
422        self.raw.clear();
423    }
424
425    /// Reserve capacity for `c` more elements. See [`Vec::reserve`]
426    #[inline]
427    pub fn reserve(&mut self, c: usize) {
428        self.raw.reserve(c);
429    }
430
431    /// Get a ref to the item at the provided index, or None for out of bounds.
432    #[inline]
433    pub fn get<J: IdxSliceIndex<I, T>>(&self, index: J) -> Option<&J::Output> {
434        index.get(self.as_slice())
435    }
436
437    /// Get a mut ref to the item at the provided index, or None for out of
438    /// bounds
439    #[inline]
440    pub fn get_mut<J: IdxSliceIndex<I, T>>(&mut self, index: J) -> Option<&mut J::Output> {
441        index.get_mut(self.as_mut_slice())
442    }
443
444    /// Resize ourselves in-place to `new_len`. See [`Vec::resize`].
445    #[inline]
446    pub fn resize(&mut self, new_len: usize, value: T)
447    where
448        T: Clone,
449    {
450        self.raw.resize(new_len, value);
451    }
452
453    /// Resize ourselves in-place to `new_len`. See [`Vec::resize_with`].
454    #[inline]
455    pub fn resize_with<F: FnMut() -> T>(&mut self, new_len: usize, f: F) {
456        self.raw.resize_with(new_len, f);
457    }
458
459    /// Moves all the elements of `other` into `Self`, leaving `other` empty.
460    /// See [`Vec::append`].
461    #[inline]
462    pub fn append(&mut self, other: &mut Self) {
463        self.raw.append(&mut other.raw);
464    }
465
466    /// Splits the collection into two at the given index. See
467    /// [`Vec::split_off`].
468    #[inline]
469    #[must_use]
470    pub fn split_off(&mut self, idx: I) -> Self {
471        Self::from_vec(self.raw.split_off(idx.index()))
472    }
473
474    /// Remove the item at `index`. See [`Vec::remove`].
475    #[inline]
476    pub fn remove(&mut self, index: I) -> T {
477        self.raw.remove(index.index())
478    }
479
480    /// Remove the item at `index` without maintaining order. See
481    /// [`Vec::swap_remove`].
482    #[inline]
483    pub fn swap_remove(&mut self, index: I) -> T {
484        self.raw.swap_remove(index.index())
485    }
486
487    /// Insert an item at `index`. See [`Vec::insert`].
488    #[inline]
489    pub fn insert(&mut self, index: I, element: T) {
490        self.raw.insert(index.index(), element);
491    }
492
493    /// Append all items in the slice to the end of our vector.
494    ///
495    /// See [`Vec::extend_from_slice`].
496    #[inline]
497    pub fn extend_from_slice(&mut self, other: &IndexSlice<I, [T]>)
498    where
499        T: Clone,
500    {
501        self.raw.extend_from_slice(&other.raw);
502    }
503
504    /// Forwards to the `Vec::retain` implementation.
505    #[inline]
506    pub fn retain<F: FnMut(&T) -> bool>(&mut self, f: F) {
507        self.raw.retain(f);
508    }
509
510    /// Forwards to the `Vec::dedup_by_key` implementation.
511    #[inline]
512    pub fn dedup_by_key<F: FnMut(&mut T) -> K, K: PartialEq>(&mut self, key: F) {
513        self.raw.dedup_by_key(key);
514    }
515
516    /// Forwards to the `Vec::dedup` implementation.
517    #[inline]
518    pub fn dedup(&mut self)
519    where
520        T: PartialEq,
521    {
522        self.raw.dedup();
523    }
524
525    /// Forwards to the `Vec::dedup_by` implementation.
526    #[inline]
527    pub fn dedup_by<F: FnMut(&mut T, &mut T) -> bool>(&mut self, same_bucket: F) {
528        self.raw.dedup_by(same_bucket);
529    }
530
531    /// Get a IndexSlice over this vector. See `as_raw_slice` for converting to
532    /// a `&[T]` (or access `self.raw`).
533    #[inline(always)]
534    pub fn as_slice(&self) -> &IndexSlice<I, [T]> {
535        IndexSlice::new(&self.raw)
536    }
537
538    /// Get a mutable IndexSlice over this vector. See `as_raw_slice_mut` for
539    /// converting to a `&mut [T]` (or access `self.raw`).
540    #[inline(always)]
541    pub fn as_mut_slice(&mut self) -> &mut IndexSlice<I, [T]> {
542        IndexSlice::new_mut(&mut self.raw)
543    }
544}
545
546impl<I: Idx, T> Default for IndexVec<I, T> {
547    #[inline]
548    fn default() -> Self {
549        Self::new()
550    }
551}
552
553impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
554    #[inline]
555    fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
556        self.raw.extend(iter);
557    }
558}
559
560impl<'a, I: Idx, T: 'a + Copy> Extend<&'a T> for IndexVec<I, T> {
561    #[inline]
562    fn extend<J: IntoIterator<Item = &'a T>>(&mut self, iter: J) {
563        self.raw.extend(iter);
564    }
565}
566
567impl<I: Idx, T> FromIterator<T> for IndexVec<I, T> {
568    #[inline]
569    fn from_iter<J>(iter: J) -> Self
570    where
571        J: IntoIterator<Item = T>,
572    {
573        IndexVec { raw: FromIterator::from_iter(iter), _marker: PhantomData }
574    }
575}
576
577impl<I: Idx, T> IntoIterator for IndexVec<I, T> {
578    type IntoIter = vec::IntoIter<T>;
579    type Item = T;
580
581    #[inline]
582    fn into_iter(self) -> vec::IntoIter<T> {
583        self.raw.into_iter()
584    }
585}
586
587impl<'a, I: Idx, T> IntoIterator for &'a IndexVec<I, T> {
588    type IntoIter = slice::Iter<'a, T>;
589    type Item = &'a T;
590
591    #[inline]
592    fn into_iter(self) -> slice::Iter<'a, T> {
593        self.raw.iter()
594    }
595}
596
597impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec<I, T> {
598    type IntoIter = slice::IterMut<'a, T>;
599    type Item = &'a mut T;
600
601    #[inline]
602    fn into_iter(self) -> slice::IterMut<'a, T> {
603        self.raw.iter_mut()
604    }
605}
606
607impl<I: Idx, T> From<IndexVec<I, T>> for Box<IndexSlice<I, [T]>> {
608    #[inline]
609    fn from(src: IndexVec<I, T>) -> Self {
610        src.into_boxed_slice()
611    }
612}
613
614impl<I: Idx, T> From<Box<IndexSlice<I, [T]>>> for IndexVec<I, T> {
615    #[inline]
616    fn from(src: Box<IndexSlice<I, [T]>>) -> Self {
617        src.into_vec()
618    }
619}
620
621impl<'a, I: Idx, T> From<Cow<'a, IndexSlice<I, [T]>>> for IndexVec<I, T>
622where
623    IndexSlice<I, [T]>: ToOwned<Owned = IndexVec<I, T>>,
624{
625    #[inline]
626    fn from(s: Cow<'a, IndexSlice<I, [T]>>) -> IndexVec<I, T> {
627        s.into_owned()
628    }
629}
630
631impl<'a, I: Idx, T: Clone> From<&'a IndexSlice<I, [T]>> for IndexVec<I, T> {
632    #[inline]
633    fn from(src: &'a IndexSlice<I, [T]>) -> Self {
634        src.to_owned()
635    }
636}
637impl<'a, I: Idx, T: Clone> From<&'a mut IndexSlice<I, [T]>> for IndexVec<I, T> {
638    #[inline]
639    fn from(src: &'a mut IndexSlice<I, [T]>) -> Self {
640        src.to_owned()
641    }
642}
643
644impl<I: Idx, T> From<Vec<T>> for IndexVec<I, T> {
645    #[inline]
646    fn from(v: Vec<T>) -> Self {
647        Self { raw: v, _marker: PhantomData }
648    }
649}
650
651impl<I: Idx, T: Clone> Clone for IndexVec<I, T> {
652    #[inline]
653    fn clone(&self) -> Self {
654        Self { raw: self.raw.clone(), _marker: PhantomData }
655    }
656
657    #[inline]
658    fn clone_from(&mut self, o: &Self) {
659        self.raw.clone_from(&o.raw);
660    }
661}
662
663impl<I: Idx, A> AsRef<[A]> for IndexVec<I, A> {
664    #[inline]
665    fn as_ref(&self) -> &[A] {
666        &self.raw
667    }
668}
669
670impl<I: Idx, A> AsMut<[A]> for IndexVec<I, A> {
671    #[inline]
672    fn as_mut(&mut self) -> &mut [A] {
673        &mut self.raw
674    }
675}
676
677impl<I: Idx, A> AsRef<IndexSlice<I, [A]>> for IndexVec<I, A> {
678    #[inline]
679    fn as_ref(&self) -> &IndexSlice<I, [A]> {
680        IndexSlice::new(&self.raw)
681    }
682}
683
684impl<I: Idx, A> AsMut<IndexSlice<I, [A]>> for IndexVec<I, A> {
685    #[inline]
686    fn as_mut(&mut self) -> &mut IndexSlice<I, [A]> {
687        IndexSlice::new_mut(&mut self.raw)
688    }
689}
690
691impl<I: Idx, A> core::ops::Deref for IndexVec<I, A> {
692    type Target = IndexSlice<I, [A]>;
693
694    #[inline]
695    fn deref(&self) -> &IndexSlice<I, [A]> {
696        IndexSlice::new(&self.raw)
697    }
698}
699
700impl<I: Idx, A> core::ops::DerefMut for IndexVec<I, A> {
701    #[inline]
702    fn deref_mut(&mut self) -> &mut IndexSlice<I, [A]> {
703        IndexSlice::new_mut(&mut self.raw)
704    }
705}
706
707impl<I: Idx, T> Borrow<IndexSlice<I, [T]>> for IndexVec<I, T> {
708    #[inline]
709    fn borrow(&self) -> &IndexSlice<I, [T]> {
710        self.as_slice()
711    }
712}
713
714impl<I: Idx, T> BorrowMut<IndexSlice<I, [T]>> for IndexVec<I, T> {
715    #[inline]
716    fn borrow_mut(&mut self) -> &mut IndexSlice<I, [T]> {
717        self.as_mut_slice()
718    }
719}
720
721macro_rules! impl_partialeq {
722    ($Lhs: ty, $Rhs: ty) => {
723        impl<'a, 'b, A, B, I: Idx> PartialEq<$Rhs> for $Lhs
724        where
725            A: PartialEq<B>,
726        {
727            #[inline]
728            fn eq(&self, other: &$Rhs) -> bool {
729                self[..] == other[..]
730            }
731
732            #[inline]
733            fn ne(&self, other: &$Rhs) -> bool {
734                self[..] != other[..]
735            }
736        }
737    };
738}
739
740macro_rules! impl_partialeq2 {
741    ($Lhs: ty, $Rhs: ty) => {
742        impl<'a, 'b, A, B, I: Idx, J: Idx> PartialEq<$Rhs> for $Lhs
743        where
744            A: PartialEq<B>,
745        {
746            #[inline]
747            fn eq(&self, other: &$Rhs) -> bool {
748                self.raw[..] == other.raw[..]
749            }
750
751            #[inline]
752            fn ne(&self, other: &$Rhs) -> bool {
753                self.raw[..] != other.raw[..]
754            }
755        }
756    };
757}
758
759impl_partialeq! { IndexVec<I, A>, Vec<B> }
760impl_partialeq! { IndexVec<I, A>, &'b [B] }
761impl_partialeq! { IndexVec<I, A>, &'b mut [B] }
762
763impl_partialeq2! { IndexVec<I, A>, &'b IndexSlice<J, [B]> }
764impl_partialeq2! { IndexVec<I, A>, &'b mut IndexSlice<J, [B]> }
765
766impl_partialeq! { &'a IndexSlice<I, [A]>, Vec<B> }
767impl_partialeq! { &'a mut IndexSlice<I, [A]>, Vec<B> }
768
769impl_partialeq! { IndexSlice<I, [A]>, &'b [B] }
770impl_partialeq! { IndexSlice<I, [A]>, &'b mut [B] }
771
772impl_partialeq2! { &'a IndexSlice<I, [A]>, IndexVec<J, B> }
773impl_partialeq2! { &'a mut IndexSlice<I, [A]>, IndexVec<J, B> }
774
775impl_partialeq2! { IndexSlice<I, [A]>, &'a IndexSlice<J, [B]> }
776impl_partialeq2! { IndexSlice<I, [A]>, &'a mut IndexSlice<J, [B]> }
777
778macro_rules! array_impls {
779    ($($N: expr_2021)+) => {$(
780        impl_partialeq! { IndexVec<I, A>, [B; $N] }
781        impl_partialeq! { IndexVec<I, A>, &'b [B; $N] }
782        impl_partialeq! { IndexSlice<I, [A]>, [B; $N] }
783        impl_partialeq! { IndexSlice<I, [A]>, &'b [B; $N] }
784        // impl_partialeq! { &'a IndexSlice<I, [A]>, [B; $N] }
785        // impl_partialeq! { &'a IndexSlice<I, [A]>, &'b [B; $N] }
786    )+};
787}
788
789array_impls! {
790     0  1  2  3  4  5  6  7  8  9
791    10 11 12 13 14 15 16 17 18 19
792    20 21 22 23 24 25 26 27 28 29
793    30 31 32
794}
795
796#[inline(never)]
797#[cold]
798#[doc(hidden)]
799pub fn __max_check_fail(u: usize, max: usize) -> ! {
800    panic!("index_vec index overflow: {} is outside the range [0, {})", u, max,)
801}
802
803#[cfg(feature = "serde")]
804impl<I: Idx, T: crate::serde::ser::Serialize> crate::serde::ser::Serialize for IndexVec<I, T> {
805    fn serialize<S: crate::serde::ser::Serializer>(
806        &self,
807        serializer: S,
808    ) -> Result<S::Ok, S::Error> {
809        self.raw.serialize(serializer)
810    }
811}
812
813#[cfg(feature = "serde")]
814impl<'de, I: Idx, T: crate::serde::de::Deserialize<'de>> crate::serde::de::Deserialize<'de>
815    for IndexVec<I, T>
816{
817    fn deserialize<D: crate::serde::de::Deserializer<'de>>(
818        deserializer: D,
819    ) -> Result<Self, D::Error> {
820        Vec::deserialize(deserializer).map(Self::from_vec)
821    }
822}
823
824#[cfg(feature = "serde")]
825impl<I: Idx, T: crate::serde::ser::Serialize> crate::serde::ser::Serialize for IndexBox<I, T> {
826    fn serialize<S: crate::serde::ser::Serializer>(
827        &self,
828        serializer: S,
829    ) -> Result<S::Ok, S::Error> {
830        self.raw.serialize(serializer)
831    }
832}
833
834#[cfg(feature = "serde")]
835impl<'de, I: Idx, T: crate::serde::de::Deserialize<'de>> crate::serde::de::Deserialize<'de>
836    for IndexBox<I, [T]>
837{
838    fn deserialize<D: crate::serde::de::Deserializer<'de>>(
839        deserializer: D,
840    ) -> Result<Self, D::Error> {
841        Box::<[T]>::deserialize(deserializer).map(Into::into)
842    }
843}
844
845#[cfg(test)]
846#[expect(clippy::legacy_numeric_constants)]
847mod test {
848    use super::*;
849
850    define_index_type! {
851        pub struct TestIdx = u32;
852    }
853
854    #[test]
855    fn test_resize() {
856        let mut v = IndexVec::<TestIdx, u32>::with_capacity(10);
857        assert_eq!(v.len(), 0);
858        assert!(v.is_empty());
859
860        v.push(1);
861        assert_eq!(v.len(), 1);
862
863        v.resize(5, 1);
864        assert_eq!(v.len(), 5);
865        assert_eq!(v.as_slice(), &[1, 1, 1, 1, 1]);
866
867        v.shrink_to_fit();
868        assert_eq!(v.len(), 5);
869    }
870
871    #[test]
872    fn test_push_pop() {
873        let mut v = IndexVec::<TestIdx, u32>::new();
874        v.push(1);
875        assert_eq!(v.pop(), Some(1));
876    }
877
878    #[test]
879    fn test_clear() {
880        let mut v: IndexVec<TestIdx, u32> = [1, 2, 3].into_iter().collect();
881        assert_eq!(v.len(), 3);
882
883        v.clear();
884        assert_eq!(v.len(), 0);
885        assert_eq!(v.as_slice(), &[]);
886        assert_eq!(v, IndexVec::<TestIdx, u32>::new());
887    }
888}