diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b95b0b9381c7c..59aa5bbd58e18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,7 @@ jobs: RUSTFLAGS: "--cfg tokio_unstable -C target-feature=+atomics,+bulk-memory,+mutable-globals,+simd128 -C link-args=--max-memory=67108864" CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --dir=${{ github.workspace }}::${{ github.workspace }} --" # Insta is not able to run on wasmtime, omit the packages that depend on it - TEST_FLAGS: "-p oxc_ast -p oxc_cfg -p oxc_index -p oxc_regular_expression -p oxc_module_lexer -- --nocapture" + TEST_FLAGS: "-p oxc_ast -p oxc_cfg -p oxc_regular_expression -p oxc_module_lexer -- --nocapture" steps: - uses: taiki-e/checkout-action@v1 - uses: Boshen/setup-rust@main diff --git a/Cargo.lock b/Cargo.lock index ec4ede77370ec..ae714250b440b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1406,7 +1406,6 @@ dependencies = [ "oxc_cfg", "oxc_codegen", "oxc_diagnostics", - "oxc_index", "oxc_isolated_declarations", "oxc_mangler", "oxc_minifier", @@ -1650,9 +1649,10 @@ dependencies = [ [[package]] name = "oxc_index" -version = "0.37.0" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe15d5f5b96fa820c5ba2709eceabf395c4a93a578c792bdd65da6e88a77e14" dependencies = [ - "rayon", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 803a73db4c4d9..e6cda84fdbc9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,7 +88,6 @@ oxc_data_structures = { version = "0.37.0", path = "crates/oxc_data_structures" oxc_diagnostics = { version = "0.37.0", path = "crates/oxc_diagnostics" } oxc_ecmascript = { version = "0.37.0", path = "crates/oxc_ecmascript" } oxc_estree = { version = "0.37.0", path = "crates/oxc_estree" } -oxc_index = { version = "0.37.0", path = "crates/oxc_index" } oxc_isolated_declarations = { version = "0.37.0", path = "crates/oxc_isolated_declarations" } oxc_mangler = { version = "0.37.0", path = "crates/oxc_mangler" } oxc_minifier = { version = "0.37.0", path = "crates/oxc_minifier" } @@ -168,6 +167,7 @@ num-bigint = "0.4.6" num-traits = "0.2.19" once_cell = "1.20.2" oxc-browserslist = "1.1.0" +oxc_index = "1.0.0" oxc_resolver = "2.0.0" petgraph = "0.6.5" phf = "0.11.2" diff --git a/crates/oxc/Cargo.toml b/crates/oxc/Cargo.toml index a458b18246e5c..da2a02fefc4f2 100644 --- a/crates/oxc/Cargo.toml +++ b/crates/oxc/Cargo.toml @@ -34,7 +34,6 @@ oxc_regular_expression = { workspace = true } oxc_cfg = { workspace = true, optional = true } oxc_codegen = { workspace = true, optional = true } oxc_diagnostics = { workspace = true } -oxc_index = { workspace = true } oxc_isolated_declarations = { workspace = true, optional = true } oxc_mangler = { workspace = true, optional = true } oxc_minifier = { workspace = true, optional = true } diff --git a/crates/oxc/src/lib.rs b/crates/oxc/src/lib.rs index 74f2aaffc247d..8a3fb70f1cf79 100644 --- a/crates/oxc/src/lib.rs +++ b/crates/oxc/src/lib.rs @@ -30,14 +30,6 @@ pub mod diagnostics { pub use oxc_diagnostics::*; } -pub mod index { - //! A Vec with newtype indexing. - //! - //! See the [`oxc_index` module-level documentation](oxc_index) for more information. - #[doc(inline)] - pub use oxc_index::*; -} - pub mod parser { //! JavaScript/TypeScript parser. //! diff --git a/crates/oxc_index/CHANGELOG.md b/crates/oxc_index/CHANGELOG.md deleted file mode 100644 index 6cbefad3e0d5d..0000000000000 --- a/crates/oxc_index/CHANGELOG.md +++ /dev/null @@ -1,74 +0,0 @@ -# Changelog - -All notable changes to this package will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0. - -## [0.34.0] - 2024-10-26 - -### Refactor - -- 423d54c rust: Remove the annoying `clippy::wildcard_imports` (#6860) (Boshen) - -## [0.30.0] - 2024-09-23 - -### Testing - -- 84b7d1a index: Add unit tests to `oxc_index` (#5979) (DonIsaac) - -## [0.29.0] - 2024-09-13 - -- 71116a1 index: [**BREAKING**] Remove ability to index `IndexVec` with `usize` (#5733) (overlookmotel) - -### Features - -- a362f51 index: Add `IndexVec::shrink_to` (#5713) (overlookmotel) - -### Performance - -- 333e2e0 index: Remove `Idx` bounds-checks from `first` + `last` methods (#5726) (overlookmotel) - -## [0.28.0] - 2024-09-11 - -### Refactor - -- 2de6ea0 index, traverse: Remove unnecessary type annotations (#5650) (overlookmotel)- 26d9235 Enable clippy::ref_as_ptr (#5577) (夕舞八弦) - -## [0.27.0] - 2024-09-06 - -### Features - -- 4cb63fe index: Impl rayon related to trait for IndexVec (#5421) (IWANABETHATGUY) - -### Documentation -- 00511fd Use `oxc_index` instead of `index_vec` in doc comments (#5423) (IWANABETHATGUY) - -## [0.24.3] - 2024-08-18 - -### Refactor - -- 786bf07 index: Shorten code and correct comment (#4905) (overlookmotel) - -## [0.13.0] - 2024-05-14 - -### Bug Fixes - -- 51de41c index: Add `example_generated` to create the docs. (#3106) (Ali Rezvani) - -## [0.10.0] - 2024-03-14 - -### Features -- 697b6b7 Merge features `serde` and `wasm` to `serialize` (#2716) (Boshen) - -## [0.5.0] - 2024-01-12 - -### Features - -- f1b433b playground: Visualize symbol (#1886) (Dunqing) - -## [0.4.0] - 2023-12-08 - -### Refactor - -- 1a576f6 rust: Move to workspace lint table (#1444) (Boshen) - diff --git a/crates/oxc_index/Cargo.toml b/crates/oxc_index/Cargo.toml deleted file mode 100644 index 6272bd6839ad4..0000000000000 --- a/crates/oxc_index/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "oxc_index" -version = "0.37.0" -authors.workspace = true -categories.workspace = true -edition.workspace = true -homepage.workspace = true -include = ["/src"] -keywords.workspace = true -license.workspace = true -publish = true -repository.workspace = true -rust-version.workspace = true -description.workspace = true - -[lints] -workspace = true - -[lib] -doctest = false - -[dependencies] -rayon = { workspace = true, optional = true } -serde = { workspace = true, optional = true } - -[features] -serialize = ["dep:serde"] -rayon = ["dep:rayon"] diff --git a/crates/oxc_index/src/idxslice.rs b/crates/oxc_index/src/idxslice.rs deleted file mode 100644 index dd01f02ca6fa1..0000000000000 --- a/crates/oxc_index/src/idxslice.rs +++ /dev/null @@ -1,841 +0,0 @@ -use super::*; - -/// A slice that only accepts indices of a specific type. Note that the intended -/// usage is as `IndexSlice`. -/// -/// This is a thin wrapper around a `[T]`, to the point where the backing is a -/// public property (called `raw`). This is in part because I know this API is -/// not a complete mirror of Vec's (patches welcome). In the worst case, you can -/// always do what you need to the slice itself. -/// -/// ## Some notes on the APIs -/// -/// - Most of the Slice APIs are present. -/// - Any that aren't can be trivially accessed on the underlying `raw` -/// field, which is public. -/// -/// - Apis that take or return usizes referring to the positions of items were -/// replaced with ones that take Idx. -/// -/// - Apis that take `R: RangeBounds` take an -/// [`IdxRangeBounds`][IdxRangeBounds], which is basically a -/// `RangeBounds`. -/// - Apis that take `SliceIndex` take an -/// [`IdxSliceIndex`][IdxSliceIndex], which is basically a `SliceIndex`. -/// -/// - Most iterator functions where `the_iter().enumerate()` would refer to -/// indices have been given `_enumerated` variants. E.g. -/// [`IndexSlice::iter_enumerated`], etc. This is because -/// `v.iter().enumerate()` would be `(usize, &T)`, but you want `(I, &T)`. -/// -/// The following extensions are added: -/// -/// - [`IndexSlice::indices`]: an Iterator over the indices of type `I`. -/// - Various `enumerated` iterators mentioned earlier -/// - [`IndexSlice::position`], [`IndexSlice::rposition`] as -/// `self.iter().position()` will return a `Option` -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct IndexSlice { - _marker: PhantomData, - pub raw: T, -} - -// SAFETY: Whether `IndexSlice` is `Send` depends only on the data, -// not the phantom data. -unsafe impl Send for IndexSlice where T: Send {} - -impl fmt::Debug for IndexSlice { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.raw, fmt) - } -} -/// `IndexBox`: An alias for indexed boxed slice. -pub type IndexBox = Box>; - -type SliceMapped = iter::Map &IndexSlice>; -type SliceMappedMut = iter::Map &mut IndexSlice>; - -impl IndexSlice { - /// Construct a new IdxSlice by wrapping an existing slice. - #[inline(always)] - pub fn new + ?Sized>(s: &S) -> &Self { - Self::from_slice(s.as_ref()) - } - - /// Construct a new mutable IdxSlice by wrapping an existing mutable slice. - #[inline(always)] - pub fn new_mut + ?Sized>(s: &mut S) -> &mut Self { - Self::from_slice_mut(s.as_mut()) - } - - /// Construct a new IdxSlice by wrapping an existing slice. - #[inline(always)] - pub fn from_slice(s: &[T]) -> &Self { - // SAFETY: `IndexSlice` is a thin wrapper around `[T]` with the added marker for the index. - unsafe { &*(core::ptr::from_ref(s) as *const Self) } - } - - /// Construct a new mutable IdxSlice by wrapping an existing mutable slice. - #[inline(always)] - pub fn from_slice_mut(s: &mut [T]) -> &mut Self { - // SAFETY: `IndexSlice` is a thin wrapper around `[T]` with the added marker for the index. - unsafe { &mut *(core::ptr::from_mut(s) as *mut Self) } - } - - /// Copies `self` into a new `IndexVec`. - #[inline] - pub fn to_vec(&self) -> IndexVec - where - T: Clone, - { - IndexVec::from_vec(self.raw.to_vec()) - } - - /// Converts `self` into a vector without clones or allocation. - /// - /// The resulting vector can be converted back into a box via - /// `IndexVec`'s `into_boxed_slice` method. - #[inline] - #[allow(clippy::wrong_self_convention)] - pub fn into_vec(self: Box) -> IndexVec { - // SAFETY: Both the `IndexSlice` and the `IndexVec` are - // thin wrappers around `[T]` and `Vec` with the added marker for the index. - - unsafe { - let len = self.len(); - let b = Box::into_raw(self); - let xs = Vec::from_raw_parts(b.cast::(), len, len); - IndexVec::from_vec(xs) - } - } - - /// Returns the underlying slice. - #[inline(always)] - pub fn as_raw_slice_mut(&mut self) -> &mut [T] { - &mut self.raw - } - - /// Returns the underlying slice. - #[inline(always)] - pub fn as_raw_slice(&self) -> &[T] { - &self.raw - } - - /// Returns an unsafe mutable pointer to the slice's buffer. - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - self.raw.as_mut_ptr() - } - - /// Returns an unsafe pointer to the slice's buffer. - /// - /// # Panics - #[inline] - pub fn as_ptr(&self) -> *const T { - self.raw.as_ptr() - } - - /// Return the index of the last element, or panic. - /// - /// # Panics - #[inline] - pub fn last_idx(&self) -> I { - // TODO: should this still be a panic even when `I` has disabled - // checking? - assert!(!self.is_empty()); - I::from_usize(self.len() - 1) - } - - /// Returns the length of our slice. - #[inline] - pub fn len(&self) -> usize { - self.raw.len() - } - - /// Returns the length of our slice as an `I`. - #[inline] - pub fn len_idx(&self) -> I { - I::from_usize(self.raw.len()) - } - - /// Returns true if we're empty. - #[inline] - pub fn is_empty(&self) -> bool { - self.raw.is_empty() - } - - /// Get a iterator over reverences to our values. - /// - /// See also [`IndexSlice::iter_enumerated`], which gives you indices (of the - /// correct type) as you iterate. - #[inline] - pub fn iter(&self) -> slice::Iter<'_, T> { - self.raw.iter() - } - - /// Get a iterator over mut reverences to our values. - /// - /// See also [`IndexSlice::iter_mut_enumerated`], which gives you indices (of - /// the correct type) as you iterate. - #[inline] - pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> { - self.raw.iter_mut() - } - - /// Similar to `self.iter().enumerate()` but with indices of `I` and not - /// `usize`. - #[inline(always)] - pub fn iter_enumerated(&self) -> Enumerated, I, &T> { - self.raw.iter().enumerate().map(|(i, t)| (I::from_usize(i), t)) - } - - /// Get an iterator over all our indices. - #[inline(always)] - pub fn indices(&self) -> iter::Map, fn(usize) -> I> { - (0..self.raw.len()).map(I::from_usize) - } - - /// Similar to `self.iter_mut().enumerate()` but with indices of `I` and not - /// `usize`. - #[inline(always)] - pub fn iter_mut_enumerated(&mut self) -> Enumerated, I, &mut T> { - self.raw.iter_mut().enumerate().map(|(i, t)| (I::from_usize(i), t)) - } - - /// Forwards to the slice's `sort` implementation. - #[inline] - pub fn sort(&mut self) - where - T: Ord, - { - self.raw.sort(); - } - - /// Forwards to the slice's `sort_by` implementation. - #[inline] - pub fn sort_by core::cmp::Ordering>(&mut self, compare: F) { - self.raw.sort_by(compare); - } - - /// Forwards to the slice's `sort_by_key` implementation. - #[inline] - pub fn sort_by_key K, K: Ord>(&mut self, f: F) { - self.raw.sort_by_key(f); - } - - /// Forwards to the slice's `sort_by_cached_key` implementation. - #[inline] - pub fn sort_by_cached_key K, K: Ord>(&mut self, f: F) { - self.raw.sort_by_cached_key(f); - } - - /// Forwards to the slice's `sort_unstable` implementation. - #[inline] - pub fn sort_unstable(&mut self) - where - T: Ord, - { - self.raw.sort_unstable(); - } - - /// Forwards to the slice's `sort_unstable_by` implementation. - #[inline] - pub fn sort_unstable_by core::cmp::Ordering>(&mut self, compare: F) { - self.raw.sort_unstable_by(compare); - } - - /// Forwards to the slice's `sort_unstable_by_key` implementation. - #[inline] - pub fn sort_unstable_by_key K, K: Ord>(&mut self, f: F) { - self.raw.sort_unstable_by_key(f); - } - - /// Forwards to the slice's `ends_with` implementation. - #[inline] - pub fn ends_with + ?Sized>(&self, needle: &S) -> bool - where - T: PartialEq, - { - self.raw.ends_with(needle.as_ref()) - } - - /// Forwards to the slice's `starts_with` implementation. - #[inline] - pub fn starts_with + ?Sized>(&self, needle: &S) -> bool - where - T: PartialEq, - { - self.raw.starts_with(needle.as_ref()) - } - - /// Forwards to the slice's `contains` implementation. - #[inline] - pub fn contains(&self, x: &T) -> bool - where - T: PartialEq, - { - self.raw.contains(x) - } - - /// Forwards to the slice's `reverse` implementation. - #[inline] - pub fn reverse(&mut self) { - self.raw.reverse(); - } - - /// Call `slice::binary_search` converting the indices it gives us back as - /// needed. - /// - /// # Errors - #[inline] - pub fn binary_search(&self, value: &T) -> Result - where - T: Ord, - { - match self.raw.binary_search(value) { - Ok(i) => Ok(I::from_usize(i)), - Err(i) => Err(I::from_usize(i)), - } - } - - /// Binary searches this sorted vec with a comparator function, converting - /// the indices it gives us back to our Idx type. - /// - /// # Errors - #[inline] - pub fn binary_search_by<'a, F: FnMut(&'a T) -> core::cmp::Ordering>( - &'a self, - f: F, - ) -> Result { - match self.raw.binary_search_by(f) { - Ok(i) => Ok(I::from_usize(i)), - Err(i) => Err(I::from_usize(i)), - } - } - - /// Copies all elements from `src` into `self`, using a memcpy. - #[inline] - pub fn copy_from_slice(&mut self, src: &Self) - where - T: Copy, - { - self.raw.copy_from_slice(&src.raw); - } - - /// Copies the elements from `src` into `self`. - #[inline] - pub fn clone_from_slice(&mut self, src: &Self) - where - T: Clone, - { - self.raw.clone_from_slice(&src.raw); - } - - /// Swaps all elements in `self` with those in `other`. - #[inline] - pub fn swap_with_slice(&mut self, other: &mut Self) { - self.raw.swap_with_slice(&mut other.raw); - } - - /// Binary searches this sorted vec with a key extraction function, converting - /// the indices it gives us back to our Idx type. - /// - /// # Errors - #[inline] - pub fn binary_search_by_key<'a, B: Ord, F: FnMut(&'a T) -> B>( - &'a self, - b: &B, - f: F, - ) -> Result { - match self.raw.binary_search_by_key(b, f) { - Ok(i) => Ok(I::from_usize(i)), - Err(i) => Err(I::from_usize(i)), - } - } - - /// Searches for an element in an iterator, returning its index. This is - /// equivalent to `Iterator::position`, but returns `I` and not `usize`. - #[inline(always)] - pub fn position bool>(&self, f: F) -> Option { - self.raw.iter().position(f).map(I::from_usize) - } - - /// Searches for an element in an iterator from the right, returning its - /// index. This is equivalent to `Iterator::position`, but returns `I` and - /// not `usize`. - #[inline(always)] - pub fn rposition bool>(&self, f: F) -> Option { - self.raw.iter().rposition(f).map(I::from_usize) - } - - /// Swaps two elements in our vector. - #[inline] - pub fn swap(&mut self, a: I, b: I) { - self.raw.swap(a.index(), b.index()); - } - - /// Divides our slice into two at an index. - #[inline] - pub fn split_at(&self, a: I) -> (&Self, &Self) { - let (a, b) = self.raw.split_at(a.index()); - (Self::new(a), Self::new(b)) - } - - /// Divides our slice into two at an index. - #[inline] - pub fn split_at_mut(&mut self, a: I) -> (&mut Self, &mut Self) { - let (a, b) = self.raw.split_at_mut(a.index()); - (Self::new_mut(a), Self::new_mut(b)) - } - - /// Rotates our data in-place such that the first `mid` elements of the - /// slice move to the end while the last `self.len() - mid` elements move to - /// the front - #[inline] - pub fn rotate_left(&mut self, mid: I) { - self.raw.rotate_left(mid.index()); - } - - /// Rotates our data in-place such that the first `self.len() - k` elements - /// of the slice move to the end while the last `k` elements move to the - /// front - #[inline] - pub fn rotate_right(&mut self, k: I) { - self.raw.rotate_right(k.index()); - } - - /// Return the the last element, if we are not empty. - #[inline(always)] - pub fn last(&self) -> Option<&T> { - self.raw.last() - } - - /// Return the the last element, if we are not empty. - #[inline] - pub fn last_mut(&mut self) -> Option<&mut T> { - self.raw.last_mut() - } - - /// Return the the first element, if we are not empty. - #[inline] - pub fn first(&self) -> Option<&T> { - self.raw.first() - } - - /// Return the the first element, if we are not empty. - #[inline] - pub fn first_mut(&mut self) -> Option<&mut T> { - self.raw.first_mut() - } - - /// Copies elements from one part of the slice to another part of itself, - /// using a memmove. - #[inline] - pub fn copy_within>(&mut self, src: R, dst: I) - where - T: Copy, - { - self.raw.copy_within(src.into_range(), dst.index()); - } - - /// Get a ref to the item at the provided index, or None for out of bounds. - #[inline] - pub fn get>(&self, index: J) -> Option<&J::Output> { - index.get(self) - } - - /// Get a mut ref to the item at the provided index, or None for out of - /// bounds - #[inline] - pub fn get_mut>(&mut self, index: J) -> Option<&mut J::Output> { - index.get_mut(self) - } - - /// Wraps the underlying slice's `windows` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn windows(&self, size: usize) -> SliceMapped, I, T> { - self.raw.windows(size).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `chunks` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn chunks(&self, size: usize) -> SliceMapped, I, T> { - self.raw.chunks(size).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `chunks_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn chunks_mut(&mut self, size: usize) -> SliceMappedMut, I, T> { - self.raw.chunks_mut(size).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `chunks_exact` iterator with one that - /// yields `IndexSlice`s with the correct index type. - #[inline] - pub fn chunks_exact(&self, chunk_size: usize) -> SliceMapped, I, T> { - self.raw.chunks_exact(chunk_size).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `chunks_exact_mut` iterator with one that - /// yields `IndexSlice`s with the correct index type. - #[inline] - pub fn chunks_exact_mut( - &mut self, - chunk_size: usize, - ) -> SliceMappedMut, I, T> { - self.raw.chunks_exact_mut(chunk_size).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `rchunks` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rchunks(&self, size: usize) -> SliceMapped, I, T> { - self.raw.rchunks(size).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `rchunks_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rchunks_mut(&mut self, size: usize) -> SliceMappedMut, I, T> { - self.raw.rchunks_mut(size).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `rchunks_exact` iterator with one that - /// yields `IndexSlice`s with the correct index type. - #[inline] - pub fn rchunks_exact( - &self, - chunk_size: usize, - ) -> SliceMapped, I, T> { - self.raw.rchunks_exact(chunk_size).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `rchunks_exact_mut` iterator with one that - /// yields `IndexSlice`s with the correct index type. - #[inline] - pub fn rchunks_exact_mut( - &mut self, - chunk_size: usize, - ) -> SliceMappedMut, I, T> { - self.raw.rchunks_exact_mut(chunk_size).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `split` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn split bool>(&self, f: F) -> SliceMapped, I, T> { - self.raw.split(f).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `split_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn split_mut bool>( - &mut self, - f: F, - ) -> SliceMappedMut, I, T> { - self.raw.split_mut(f).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `rsplit` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rsplit bool>(&self, f: F) -> SliceMapped, I, T> { - self.raw.rsplit(f).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `rsplit_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rsplit_mut bool>( - &mut self, - f: F, - ) -> SliceMappedMut, I, T> { - self.raw.rsplit_mut(f).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `splitn` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn splitn bool>( - &self, - n: usize, - f: F, - ) -> SliceMapped, I, T> { - self.raw.splitn(n, f).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `splitn_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn splitn_mut bool>( - &mut self, - n: usize, - f: F, - ) -> SliceMappedMut, I, T> { - self.raw.splitn_mut(n, f).map(IndexSlice::new_mut) - } - - /// Wraps the underlying slice's `rsplitn` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rsplitn bool>( - &self, - n: usize, - f: F, - ) -> SliceMapped, I, T> { - self.raw.rsplitn(n, f).map(IndexSlice::new) - } - - /// Wraps the underlying slice's `rsplitn_mut` iterator with one that yields - /// `IndexSlice`s with the correct index type. - #[inline] - pub fn rsplitn_mut bool>( - &mut self, - n: usize, - f: F, - ) -> SliceMappedMut, I, T> { - self.raw.rsplitn_mut(n, f).map(IndexSlice::new_mut) - } - - /// Create a IdxSlice from its pointer and length. - /// - /// # Safety - /// - /// This is equivalent to `core::slice::from_raw_parts` and has the same - /// safety caveats. - #[inline] - - pub unsafe fn from_raw_parts<'a>(data: *const T, len: usize) -> &'a Self { - Self::new(slice::from_raw_parts(data, len)) - } - - /// Create a mutable IdxSlice from its pointer and length. - /// - /// # Safety - /// - /// This is equivalent to `core::slice::from_raw_parts_mut` and has the same - /// safety caveats. - #[inline] - - pub unsafe fn from_raw_parts_mut<'a>(data: *mut T, len: usize) -> &'a mut Self { - Self::new_mut(slice::from_raw_parts_mut(data, len)) - } - - /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. - #[inline] - pub fn split_first(&self) -> Option<(&T, &IndexSlice)> { - if self.is_empty() { - None - } else { - Some((&self[I::from_usize(0)], &self[I::from_usize(1)..])) - } - } - - /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. - #[inline] - pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut IndexSlice)> { - if self.is_empty() { - None - } else { - let split = self.split_at_mut(I::from_usize(1)); - Some((&mut split.0[I::from_usize(0)], split.1)) - } - } - - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. - #[inline] - pub fn split_last(&self) -> Option<(&T, &IndexSlice)> { - if self.is_empty() { - None - } else { - let last = self.last_idx(); - Some((&self[last], &self[..last])) - } - } - - /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. - #[inline] - pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut IndexSlice)> { - if self.is_empty() { - None - } else { - let last = self.last_idx(); - let split = self.split_at_mut(last); - Some((&mut split.1[I::from_usize(0)], split.0)) - } - } -} - -impl PartialEq> for IndexSlice -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &IndexSlice) -> bool { - PartialEq::eq(&self.raw, &other.raw) - } - - #[inline] - fn ne(&self, other: &IndexSlice) -> bool { - PartialEq::ne(&self.raw, &other.raw) - } -} - -impl Eq for IndexSlice {} - -impl PartialEq<[B]> for IndexSlice -where - A: PartialEq, -{ - #[inline] - fn eq(&self, other: &[B]) -> bool { - PartialEq::eq(&self.raw, other) - } - - #[inline] - fn ne(&self, other: &[B]) -> bool { - PartialEq::ne(&self.raw, other) - } -} - -impl PartialOrd for IndexSlice { - #[inline] - fn partial_cmp(&self, other: &IndexSlice) -> Option { - PartialOrd::partial_cmp(&self.raw, &other.raw) - } -} - -impl core::cmp::Ord for IndexSlice { - #[inline] - fn cmp(&self, other: &IndexSlice) -> core::cmp::Ordering { - core::cmp::Ord::cmp(&self.raw, &other.raw) - } -} - -impl core::hash::Hash for IndexSlice { - #[inline] - fn hash(&self, h: &mut H) { - self.raw.hash(h); - } -} - -impl alloc::borrow::ToOwned for IndexSlice -where - T: Clone, -{ - type Owned = IndexVec; - - #[inline] - fn to_owned(&self) -> Self::Owned { - IndexVec::from(self.raw.to_vec()) - } -} - -impl<'a, I: Idx, T> IntoIterator for &'a IndexSlice { - type IntoIter = slice::Iter<'a, T>; - type Item = &'a T; - - #[inline] - fn into_iter(self) -> slice::Iter<'a, T> { - self.raw.iter() - } -} - -impl<'a, I: Idx, T> IntoIterator for &'a mut IndexSlice { - type IntoIter = slice::IterMut<'a, T>; - type Item = &'a mut T; - - #[inline] - fn into_iter(self) -> slice::IterMut<'a, T> { - self.raw.iter_mut() - } -} - -impl Default for &IndexSlice { - #[inline] - fn default() -> Self { - IndexSlice::new(&[]) - } -} - -impl Default for &mut IndexSlice { - #[inline] - fn default() -> Self { - IndexSlice::new_mut(&mut []) - } -} - -impl<'a, I: Idx, T> From<&'a [T]> for &'a IndexSlice { - #[inline] - fn from(a: &'a [T]) -> Self { - IndexSlice::new(a) - } -} - -impl<'a, I: Idx, T> From<&'a mut [T]> for &'a mut IndexSlice { - #[inline] - fn from(a: &'a mut [T]) -> Self { - IndexSlice::new_mut(a) - } -} - -impl From> for Box> { - #[inline] - fn from(b: Box<[T]>) -> Self { - // SAFETY: `IndexSlice` is a thin wrapper around `[T]` with the added marker for the index. - - unsafe { Box::from_raw(Box::into_raw(b) as *mut IndexSlice) } - } -} - -impl AsRef<[A]> for IndexSlice { - #[inline] - fn as_ref(&self) -> &[A] { - &self.raw - } -} - -impl AsMut<[A]> for IndexSlice { - #[inline] - fn as_mut(&mut self) -> &mut [A] { - &mut self.raw - } -} - -impl Clone for Box> { - #[inline] - fn clone(&self) -> Self { - // Suboptimal, I think. - self.to_vec().into_boxed_slice() - } -} - -impl FromIterator for Box> { - #[inline] - fn from_iter>(iter: T) -> Self { - iter.into_iter().collect::>().into_boxed_slice() - } -} - -impl IntoIterator for Box> { - type IntoIter = vec::IntoIter; - type Item = A; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - let v: IndexVec = self.into(); - v.into_iter() - } -} - -impl Default for Box> { - #[inline(always)] - fn default() -> Self { - index_vec![].into() - } -} diff --git a/crates/oxc_index/src/indexing.rs b/crates/oxc_index/src/indexing.rs deleted file mode 100644 index ddbbc92bc8233..0000000000000 --- a/crates/oxc_index/src/indexing.rs +++ /dev/null @@ -1,214 +0,0 @@ -use crate::{Idx, IndexSlice}; - -mod private_slice_index { - pub trait Sealed {} -} - -/// This is the equivalent of the sealed `core::slice::SliceIndex` trait. It -/// cannot be overridden from user, code nor should it normally need use -/// directly (Outside of trait bounds, I guess). -pub trait IdxSliceIndex: private_slice_index::Sealed { - type Output: ?Sized; - - fn get(self, slice: &IndexSlice) -> Option<&Self::Output>; - fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut Self::Output>; - - fn index(self, slice: &IndexSlice) -> &Self::Output; - fn index_mut(self, slice: &mut IndexSlice) -> &mut Self::Output; -} - -// Does this defeat the point of sealing? -impl private_slice_index::Sealed for I {} - -impl IdxSliceIndex for I { - type Output = T; - - #[inline] - fn get(self, slice: &IndexSlice) -> Option<&Self::Output> { - slice.raw.get(self.index()) - } - - #[inline] - fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut Self::Output> { - slice.raw.get_mut(self.index()) - } - - #[inline] - fn index(self, slice: &IndexSlice) -> &Self::Output { - &slice.raw[self.index()] - } - - #[inline] - fn index_mut(self, slice: &mut IndexSlice) -> &mut Self::Output { - &mut slice.raw[self.index()] - } -} - -macro_rules! range_slice { - ($r:ty) => { - impl IdxSliceIndex for $r { - type Output = IndexSlice; - - #[inline] - fn get(self, slice: &IndexSlice) -> Option<&Self::Output> { - slice.raw.get(self.into_range()).map(IndexSlice::new) - } - - #[inline] - fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut Self::Output> { - slice.raw.get_mut(self.into_range()).map(IndexSlice::new_mut) - } - - #[inline] - fn index(self, slice: &IndexSlice) -> &Self::Output { - IndexSlice::new(&slice.raw[self.into_range()]) - } - - #[inline] - fn index_mut(self, slice: &mut IndexSlice) -> &mut Self::Output { - IndexSlice::new_mut(&mut slice.raw[self.into_range()]) - } - } - }; -} - -impl private_slice_index::Sealed for core::ops::Range {} -impl private_slice_index::Sealed for core::ops::RangeFrom {} -impl private_slice_index::Sealed for core::ops::RangeTo {} -impl private_slice_index::Sealed for core::ops::RangeInclusive {} -impl private_slice_index::Sealed for core::ops::RangeToInclusive {} - -range_slice!(core::ops::Range); -range_slice!(core::ops::RangeFrom); -range_slice!(core::ops::RangeTo); -range_slice!(core::ops::RangeInclusive); -range_slice!(core::ops::RangeToInclusive); -// range_slice!(core::ops::RangeFull); -impl private_slice_index::Sealed for core::ops::RangeFull {} -impl IdxSliceIndex for core::ops::RangeFull { - type Output = IndexSlice; - - #[inline] - fn get(self, slice: &IndexSlice) -> Option<&Self::Output> { - Some(slice) - } - - #[inline] - fn get_mut(self, slice: &mut IndexSlice) -> Option<&mut Self::Output> { - Some(slice) - } - - #[inline] - fn index(self, slice: &IndexSlice) -> &Self::Output { - slice - } - - #[inline] - fn index_mut(self, slice: &mut IndexSlice) -> &mut Self::Output { - slice - } -} - -/// This trait to function in API signatures where `Vec` or `[T]` use `R: -/// RangeBounds`. There are blanket implementations for the basic range -/// types in `core::ops` for all Idx types. e.g. `Range`, `RangeFrom`, `RangeTo`, etc all implement it. -/// -/// IMO it's unfortunate that this needs to be present in the API, but it -/// doesn't hurt that much. -pub trait IdxRangeBounds: private_range_bounds::Sealed -where - I: Idx, -{ - type Range: core::ops::RangeBounds; - fn into_range(self) -> Self::Range; -} - -mod private_range_bounds { - pub trait Sealed {} -} - -impl private_range_bounds::Sealed for core::ops::Range {} -impl private_range_bounds::Sealed for core::ops::RangeFrom {} -impl private_range_bounds::Sealed for core::ops::RangeTo {} -impl private_range_bounds::Sealed for core::ops::RangeInclusive {} -impl private_range_bounds::Sealed for core::ops::RangeToInclusive {} -impl private_range_bounds::Sealed for core::ops::RangeFull {} - -impl IdxRangeBounds for core::ops::Range { - type Range = core::ops::Range; - - #[inline] - fn into_range(self) -> Self::Range { - self.start.index()..self.end.index() - } -} - -impl IdxRangeBounds for core::ops::RangeFrom { - type Range = core::ops::RangeFrom; - - #[inline] - fn into_range(self) -> Self::Range { - self.start.index().. - } -} - -impl IdxRangeBounds for core::ops::RangeFull { - type Range = core::ops::RangeFull; - - #[inline] - fn into_range(self) -> Self::Range { - self - } -} - -impl IdxRangeBounds for core::ops::RangeTo { - type Range = core::ops::RangeTo; - - #[inline] - fn into_range(self) -> Self::Range { - ..self.end.index() - } -} - -impl IdxRangeBounds for core::ops::RangeInclusive { - type Range = core::ops::RangeInclusive; - - #[inline] - fn into_range(self) -> Self::Range { - self.start().index()..=self.end().index() - } -} - -impl IdxRangeBounds for core::ops::RangeToInclusive { - type Range = core::ops::RangeToInclusive; - - #[inline] - fn into_range(self) -> Self::Range { - ..=self.end.index() - } -} - -impl core::ops::Index for IndexSlice -where - I: Idx, - R: IdxSliceIndex, -{ - type Output = R::Output; - - #[inline] - fn index(&self, index: R) -> &R::Output { - index.index(self) - } -} - -impl core::ops::IndexMut for IndexSlice -where - I: Idx, - R: IdxSliceIndex, -{ - #[inline] - fn index_mut(&mut self, index: R) -> &mut R::Output { - index.index_mut(self) - } -} diff --git a/crates/oxc_index/src/lib.rs b/crates/oxc_index/src/lib.rs deleted file mode 100644 index c075c08c63067..0000000000000 --- a/crates/oxc_index/src/lib.rs +++ /dev/null @@ -1,842 +0,0 @@ -//! This crate is a fork of `index_vec`, -//! It helps with defining "newtype"-style wrappers around `usize` (or -//! other integers), `Vec`, and `[T]` so that some additional type safety can -//! be gained at zero cost. -//! -//! ## Example / Overview -//! ```rust -//! use oxc_index::{IndexVec, IndexSlice, index_vec}; -//! -//! oxc_index::define_index_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 = index_vec!["strs", "bar", "baz"]; -//! -//! // l is a `StrIdx` -//! let l = strs.last_idx(); -//! assert_eq!(strs[l], "baz"); -//! -//! let new_i = strs.push("quux"); -//! assert_eq!(strs[new_i], "quux"); -//! -//! // The slice APIs are wrapped as well. -//! let s: &IndexSlice = &strs[StrIdx::new(1)..]; -//! assert_eq!(s[0], "bar"); -//! -//! // Indices are mostly interoperable with `usize`, and support -//! // a lot of what you might want to do to an index. -//! -//! // Comparison -//! assert_eq!(StrIdx::new(0), 0usize); -//! -//! // Addition -//! assert_eq!(StrIdx::new(0) + 1, 1usize); -//! -//! // Subtraction -//! assert_eq!(StrIdx::new(1) - 1, 0usize); -//! -//! // Wrapping -//! assert_eq!(StrIdx::new(5) % strs.len(), 1usize); -//! // ... -//! ``` -//! ## Background -//! -//! The goal is to help with the pattern of using a `type FooIdx = usize` to -//! access a `Vec` with something that can statically prevent using a -//! `FooIdx` in a `Vec`. It's most useful if you have a bunch of indices -//! referring to different sorts of vectors. -//! -//! The code was originally based on `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 -//! -//! The [`indexed_vec`](https://crates.io/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. -//! -//! If you're looking for something further from a vec and closer to a map, you -//! might find [`handy`](https://crates.io/crates/handy), -//! [`slotmap`](https://crates.io/crates/slotmap), or -//! [`slab`](https://crates.io/crates/slab) to be closer what you want. -//! -//! ## FAQ -//! -//! #### Wouldn't `define_index_type` be better as a proc macro? -//! -//! 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. -//! -//! #### Does `define_index_type` do too much? -//! -//! 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 `Vec` + `usize` to `IndexVec`. 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. -//! -//! I'm open to suggestions. -//! -//! #### Does it support no_std? -//! -//! Yes, although it uses `extern crate alloc;`, of course. -//! -//! #### Does it support serde? -//! -//! Yes, but only if you turn on the `serialize` feature. -//! -//! #### What features are planned? -//! -//! Planned is a bit strong but here are the things I would find useful. -//! -//! - Support any remaining parts of the slice/vec api. -//! - Add typesafe wrappers for SmallVec/ArrayVec (behind a cargo `feature`, of -//! course). -//! - Better syntax for the define_index_type macro (no concrete ideas). -//! - Allow the generated type to be a tuple struct, or use a specific field -//! name. -//! - Allow use of indices for string types (the primary benefit here would -//! probably be the ability to e.g. use u32 without too much pain rather than -//! mixing up indices from different strings -- but you never know!) -//! - Allow index types such as NonZeroU32 and such, if it can be done sanely. -//! - ... -//! -#![allow(clippy::inline_always)] -#![allow(clippy::partialeq_ne_impl)] -#![no_std] -extern crate alloc; - -use alloc::{ - borrow::{Cow, ToOwned}, - boxed::Box, - vec, - vec::Vec, -}; -use core::{ - borrow::{Borrow, BorrowMut}, - fmt, - fmt::Debug, - hash::Hash, - iter::{self, FromIterator}, - marker::PhantomData, - ops::Range, - slice, -}; -mod idxslice; -mod indexing; -pub use idxslice::{IndexBox, IndexSlice}; -pub use indexing::{IdxRangeBounds, IdxSliceIndex}; -#[cfg(feature = "rayon")] -pub use rayon_impl::*; -#[cfg(feature = "rayon")] -mod rayon_impl; - -#[macro_use] -mod macros; - -/// Represents a wrapped value convertible to and from a `usize`. -/// -/// Generally you implement this via the [`define_index_type!`] macro, rather -/// than manually implementing it. -/// -/// # Overflow -/// -/// `Idx` impls are allowed to be smaller than `usize`, which means converting -/// `usize` to an `Idx` implementation might have to handle overflow. -/// -/// The way overflow is handled is up to the implementation of `Idx`, but it's -/// generally panicking, unless it was turned off via the -/// `DISABLE_MAX_INDEX_CHECK` option in [`define_index_type!`]. If you need more -/// subtle handling than this, then you're on your own (or, well, either handle -/// it earlier, or pick a bigger index type). -/// -/// Note: I'm open for suggestions on how to handle this case, but do not want -/// the typical cases (E.g. Idx is a newtyped `usize` or `u32`), to become more -/// complex. -pub trait Idx: Copy + 'static + Ord + Debug + Hash { - /// Construct an Index from a `usize`. This is equivalent to `From`. - /// - /// Note that this will panic if `idx` does not fit (unless checking has - /// been disabled, as mentioned above). Also note that `Idx` implementations - /// are free to define what "fit" means as they desire. - fn from_usize(idx: usize) -> Self; - - /// Get the underlying index. This is equivalent to `Into` - fn index(self) -> usize; -} - -/// A macro equivalent to the stdlib's `vec![]`, but producing an `IndexVec`. -#[macro_export] -macro_rules! index_vec { - ($($tokens:tt)*) => { - $crate::IndexVec::from_vec(vec![$($tokens)*]) - } -} - -/// A macro similar to the stdlib's `vec![]`, but producing an -/// `Box>` (That is, an `IndexBox`). -#[macro_export] -macro_rules! index_box { - ($($tokens:tt)*) => { - $crate::IndexVec::from_vec(vec![$($tokens)*]).into_boxed_slice() - } -} - -/// A Vec that only accepts indices of a specific type. -/// -/// This is a thin wrapper around `Vec`, to the point where the backing vec is a -/// public property (called `raw`). This is in part because I know this API is -/// not a complete mirror of Vec's (patches welcome). In the worst case, you can -/// always do what you need to the Vec itself. -/// -/// Note that this implements Deref/DerefMut to [`IndexSlice`], and so all the -/// methods on IndexSlice are available as well. See it's documentation for some -/// further information. -/// -/// The following extensions to the Vec APIs are added (in addition to the ones -/// mentioned in IndexSlice's documentation): -/// -/// - [`IndexVec::next_idx`], [`IndexSlice::last_idx`] give the next and most -/// recent index returned by `push`. -/// - [`IndexVec::push`] returns the index the item was inserted at. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct IndexVec { - /// Our wrapped Vec. - pub raw: Vec, - _marker: PhantomData, -} - -// SAFETY: Whether `IndexVec` is `Send` depends only on the data, -// not the phantom data. -unsafe impl Send for IndexVec where T: Send {} - -impl fmt::Debug for IndexVec { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.raw, fmt) - } -} -type Enumerated = iter::Map, fn((usize, T)) -> (I, T)>; - -impl IndexVec { - /// Construct a new IndexVec. - #[inline] - pub fn new() -> Self { - IndexVec { raw: Vec::new(), _marker: PhantomData } - } - - /// Construct a `IndexVec` from a `Vec`. - /// - /// Panics if it's length is too large for our index type. - #[inline] - pub fn from_vec(vec: Vec) -> Self { - // See if `I::from_usize` might be upset by this length. - let _ = I::from_usize(vec.len()); - IndexVec { raw: vec, _marker: PhantomData } - } - - /// Construct an IndexVec that can hold at least `capacity` items before - /// reallocating. See [`Vec::with_capacity`]. - #[inline] - pub fn with_capacity(capacity: usize) -> Self { - IndexVec { raw: Vec::with_capacity(capacity), _marker: PhantomData } - } - - /// Similar to `self.into_iter().enumerate()` but with indices of `I` and - /// not `usize`. - #[inline(always)] - pub fn into_iter_enumerated(self) -> Enumerated, I, T> { - self.raw.into_iter().enumerate().map(|(i, t)| (I::from_usize(i), t)) - } - - /// Creates a splicing iterator that replaces the specified range in the - /// vector with the given `replace_with` iterator and yields the removed - /// items. See [`Vec::splice`] - #[inline] - pub fn splice( - &mut self, - range: R, - replace_with: It, - ) -> vec::Splice<::IntoIter> - where - It: IntoIterator, - R: IdxRangeBounds, - { - self.raw.splice(range.into_range(), replace_with) - } - - /// Similar to `self.drain(r).enumerate()` but with indices of `I` and not - /// `usize`. - #[inline] - pub fn drain_enumerated>( - &mut self, - range: R, - ) -> Enumerated, I, T> { - self.raw.drain(range.into_range()).enumerate().map(|(i, t)| (I::from_usize(i), t)) - } - - /// Gives the next index that will be assigned when `push` is - /// called. - #[inline] - pub fn next_idx(&self) -> I { - I::from_usize(self.len()) - } - - /// Get a the storage as a `&[T]` - #[inline(always)] - pub fn as_raw_slice(&self) -> &[T] { - &self.raw - } - - /// Get a the storage as a `&mut [T]` - #[inline(always)] - pub fn as_raw_slice_mut(&mut self) -> &mut [T] { - &mut self.raw - } - - /// Equivalent to accessing our `raw` field, but as a function. - #[inline(always)] - pub fn as_vec(&self) -> &Vec { - &self.raw - } - - /// Equivalent to accessing our `raw` field mutably, but as a function, if - /// that's what you'd prefer. - #[inline(always)] - pub fn as_mut_vec(&mut self) -> &mut Vec { - &mut self.raw - } - - /// Push a new item onto the vector, and return it's index. - #[inline] - pub fn push(&mut self, d: T) -> I { - let idx = I::from_usize(self.len()); - self.raw.push(d); - idx - } - - /// Pops the last item off, returning it. See [`Vec::pop`]. - #[inline] - pub fn pop(&mut self) -> Option { - self.raw.pop() - } - - /// Converts the vector into an owned [`IndexSlice`], dropping excess capacity. - #[inline] - pub fn into_boxed_slice(self) -> Box> { - let b = self.raw.into_boxed_slice(); - // SAFETY: `IndexSlice` is a thin wrapper around `[T]` with the added marker for the index. - unsafe { Box::from_raw(Box::into_raw(b) as *mut IndexSlice) } - } - - /// Return an iterator that removes the items from the requested range. See - /// [`Vec::drain`]. - /// - /// See also [`IndexVec::drain_enumerated`], which gives you indices (of the - /// correct type) as you iterate. - #[inline] - pub fn drain>(&mut self, range: R) -> vec::Drain<'_, T> { - self.raw.drain(range.into_range()) - } - - /// Shrinks the capacity of the vector as much as possible. - #[inline] - pub fn shrink_to_fit(&mut self) { - self.raw.shrink_to_fit(); - } - - /// Shrinks the capacity of the vector with a lower bound. - #[inline] - pub fn shrink_to(&mut self, min_capacity: usize) { - self.raw.shrink_to(min_capacity); - } - - /// Shortens the vector, keeping the first `len` elements and dropping - /// the rest. See [`Vec::truncate`] - #[inline] - pub fn truncate(&mut self, a: usize) { - self.raw.truncate(a); - } - - /// Clear our vector. See [`Vec::clear`]. - #[inline] - pub fn clear(&mut self) { - self.raw.clear(); - } - - /// Reserve capacity for `c` more elements. See [`Vec::reserve`] - #[inline] - pub fn reserve(&mut self, c: usize) { - self.raw.reserve(c); - } - - /// Get a ref to the item at the provided index, or None for out of bounds. - #[inline] - pub fn get>(&self, index: J) -> Option<&J::Output> { - index.get(self.as_slice()) - } - - /// Get a mut ref to the item at the provided index, or None for out of - /// bounds - #[inline] - pub fn get_mut>(&mut self, index: J) -> Option<&mut J::Output> { - index.get_mut(self.as_mut_slice()) - } - - /// Resize ourselves in-place to `new_len`. See [`Vec::resize`]. - #[inline] - pub fn resize(&mut self, new_len: usize, value: T) - where - T: Clone, - { - self.raw.resize(new_len, value); - } - - /// Resize ourselves in-place to `new_len`. See [`Vec::resize_with`]. - #[inline] - pub fn resize_with T>(&mut self, new_len: usize, f: F) { - self.raw.resize_with(new_len, f); - } - - /// Moves all the elements of `other` into `Self`, leaving `other` empty. - /// See [`Vec::append`]. - #[inline] - pub fn append(&mut self, other: &mut Self) { - self.raw.append(&mut other.raw); - } - - /// Splits the collection into two at the given index. See - /// [`Vec::split_off`]. - #[inline] - #[must_use] - pub fn split_off(&mut self, idx: I) -> Self { - Self::from_vec(self.raw.split_off(idx.index())) - } - - /// Remove the item at `index`. See [`Vec::remove`]. - #[inline] - pub fn remove(&mut self, index: I) -> T { - self.raw.remove(index.index()) - } - - /// Remove the item at `index` without maintaining order. See - /// [`Vec::swap_remove`]. - #[inline] - pub fn swap_remove(&mut self, index: I) -> T { - self.raw.swap_remove(index.index()) - } - - /// Insert an item at `index`. See [`Vec::insert`]. - #[inline] - pub fn insert(&mut self, index: I, element: T) { - self.raw.insert(index.index(), element); - } - - /// Append all items in the slice to the end of our vector. - /// - /// See [`Vec::extend_from_slice`]. - #[inline] - pub fn extend_from_slice(&mut self, other: &IndexSlice) - where - T: Clone, - { - self.raw.extend_from_slice(&other.raw); - } - - /// Forwards to the `Vec::retain` implementation. - #[inline] - pub fn retain bool>(&mut self, f: F) { - self.raw.retain(f); - } - - /// Forwards to the `Vec::dedup_by_key` implementation. - #[inline] - pub fn dedup_by_key K, K: PartialEq>(&mut self, key: F) { - self.raw.dedup_by_key(key); - } - - /// Forwards to the `Vec::dedup` implementation. - #[inline] - pub fn dedup(&mut self) - where - T: PartialEq, - { - self.raw.dedup(); - } - - /// Forwards to the `Vec::dedup_by` implementation. - #[inline] - pub fn dedup_by bool>(&mut self, same_bucket: F) { - self.raw.dedup_by(same_bucket); - } - - /// Get a IndexSlice over this vector. See `as_raw_slice` for converting to - /// a `&[T]` (or access `self.raw`). - #[inline(always)] - pub fn as_slice(&self) -> &IndexSlice { - IndexSlice::new(&self.raw) - } - - /// Get a mutable IndexSlice over this vector. See `as_raw_slice_mut` for - /// converting to a `&mut [T]` (or access `self.raw`). - #[inline(always)] - pub fn as_mut_slice(&mut self) -> &mut IndexSlice { - IndexSlice::new_mut(&mut self.raw) - } -} - -impl Default for IndexVec { - #[inline] - fn default() -> Self { - Self::new() - } -} - -impl Extend for IndexVec { - #[inline] - fn extend>(&mut self, iter: J) { - self.raw.extend(iter); - } -} - -impl<'a, I: Idx, T: 'a + Copy> Extend<&'a T> for IndexVec { - #[inline] - fn extend>(&mut self, iter: J) { - self.raw.extend(iter); - } -} - -impl FromIterator for IndexVec { - #[inline] - fn from_iter(iter: J) -> Self - where - J: IntoIterator, - { - IndexVec { raw: FromIterator::from_iter(iter), _marker: PhantomData } - } -} - -impl IntoIterator for IndexVec { - type IntoIter = vec::IntoIter; - type Item = T; - - #[inline] - fn into_iter(self) -> vec::IntoIter { - self.raw.into_iter() - } -} - -impl<'a, I: Idx, T> IntoIterator for &'a IndexVec { - type IntoIter = slice::Iter<'a, T>; - type Item = &'a T; - - #[inline] - fn into_iter(self) -> slice::Iter<'a, T> { - self.raw.iter() - } -} - -impl<'a, I: Idx, T> IntoIterator for &'a mut IndexVec { - type IntoIter = slice::IterMut<'a, T>; - type Item = &'a mut T; - - #[inline] - fn into_iter(self) -> slice::IterMut<'a, T> { - self.raw.iter_mut() - } -} - -impl From> for Box> { - #[inline] - fn from(src: IndexVec) -> Self { - src.into_boxed_slice() - } -} - -impl From>> for IndexVec { - #[inline] - fn from(src: Box>) -> Self { - src.into_vec() - } -} - -impl<'a, I: Idx, T> From>> for IndexVec -where - IndexSlice: ToOwned>, -{ - #[inline] - fn from(s: Cow<'a, IndexSlice>) -> IndexVec { - s.into_owned() - } -} - -impl<'a, I: Idx, T: Clone> From<&'a IndexSlice> for IndexVec { - #[inline] - fn from(src: &'a IndexSlice) -> Self { - src.to_owned() - } -} -impl<'a, I: Idx, T: Clone> From<&'a mut IndexSlice> for IndexVec { - #[inline] - fn from(src: &'a mut IndexSlice) -> Self { - src.to_owned() - } -} - -impl From> for IndexVec { - #[inline] - fn from(v: Vec) -> Self { - Self { raw: v, _marker: PhantomData } - } -} - -impl Clone for IndexVec { - #[inline] - fn clone(&self) -> Self { - Self { raw: self.raw.clone(), _marker: PhantomData } - } - - #[inline] - fn clone_from(&mut self, o: &Self) { - self.raw.clone_from(&o.raw); - } -} - -impl AsRef<[A]> for IndexVec { - #[inline] - fn as_ref(&self) -> &[A] { - &self.raw - } -} - -impl AsMut<[A]> for IndexVec { - #[inline] - fn as_mut(&mut self) -> &mut [A] { - &mut self.raw - } -} - -impl AsRef> for IndexVec { - #[inline] - fn as_ref(&self) -> &IndexSlice { - IndexSlice::new(&self.raw) - } -} - -impl AsMut> for IndexVec { - #[inline] - fn as_mut(&mut self) -> &mut IndexSlice { - IndexSlice::new_mut(&mut self.raw) - } -} - -impl core::ops::Deref for IndexVec { - type Target = IndexSlice; - - #[inline] - fn deref(&self) -> &IndexSlice { - IndexSlice::new(&self.raw) - } -} - -impl core::ops::DerefMut for IndexVec { - #[inline] - fn deref_mut(&mut self) -> &mut IndexSlice { - IndexSlice::new_mut(&mut self.raw) - } -} - -impl Borrow> for IndexVec { - #[inline] - fn borrow(&self) -> &IndexSlice { - self.as_slice() - } -} - -impl BorrowMut> for IndexVec { - #[inline] - fn borrow_mut(&mut self) -> &mut IndexSlice { - self.as_mut_slice() - } -} - -macro_rules! impl_partialeq { - ($Lhs: ty, $Rhs: ty) => { - impl<'a, 'b, A, B, I: Idx> PartialEq<$Rhs> for $Lhs - where - A: PartialEq, - { - #[inline] - fn eq(&self, other: &$Rhs) -> bool { - self[..] == other[..] - } - - #[inline] - fn ne(&self, other: &$Rhs) -> bool { - self[..] != other[..] - } - } - }; -} - -macro_rules! impl_partialeq2 { - ($Lhs: ty, $Rhs: ty) => { - impl<'a, 'b, A, B, I: Idx, J: Idx> PartialEq<$Rhs> for $Lhs - where - A: PartialEq, - { - #[inline] - fn eq(&self, other: &$Rhs) -> bool { - self.raw[..] == other.raw[..] - } - - #[inline] - fn ne(&self, other: &$Rhs) -> bool { - self.raw[..] != other.raw[..] - } - } - }; -} - -impl_partialeq! { IndexVec, Vec } -impl_partialeq! { IndexVec, &'b [B] } -impl_partialeq! { IndexVec, &'b mut [B] } - -impl_partialeq2! { IndexVec, &'b IndexSlice } -impl_partialeq2! { IndexVec, &'b mut IndexSlice } - -impl_partialeq! { &'a IndexSlice, Vec } -impl_partialeq! { &'a mut IndexSlice, Vec } - -impl_partialeq! { IndexSlice, &'b [B] } -impl_partialeq! { IndexSlice, &'b mut [B] } - -impl_partialeq2! { &'a IndexSlice, IndexVec } -impl_partialeq2! { &'a mut IndexSlice, IndexVec } - -impl_partialeq2! { IndexSlice, &'a IndexSlice } -impl_partialeq2! { IndexSlice, &'a mut IndexSlice } - -macro_rules! array_impls { - ($($N: expr)+) => {$( - impl_partialeq! { IndexVec, [B; $N] } - impl_partialeq! { IndexVec, &'b [B; $N] } - impl_partialeq! { IndexSlice, [B; $N] } - impl_partialeq! { IndexSlice, &'b [B; $N] } - // impl_partialeq! { &'a IndexSlice, [B; $N] } - // impl_partialeq! { &'a IndexSlice, &'b [B; $N] } - )+}; -} - -array_impls! { - 0 1 2 3 4 5 6 7 8 9 - 10 11 12 13 14 15 16 17 18 19 - 20 21 22 23 24 25 26 27 28 29 - 30 31 32 -} - -#[inline(never)] -#[cold] -#[doc(hidden)] -pub fn __max_check_fail(u: usize, max: usize) -> ! { - panic!("index_vec index overflow: {} is outside the range [0, {})", u, max,) -} - -#[cfg(feature = "serialize")] -impl serde::ser::Serialize for IndexVec { - fn serialize(&self, serializer: S) -> Result { - self.raw.serialize(serializer) - } -} - -#[cfg(feature = "serialize")] -impl<'de, I: Idx, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for IndexVec { - fn deserialize>(deserializer: D) -> Result { - Vec::deserialize(deserializer).map(Self::from_vec) - } -} - -#[cfg(feature = "serialize")] -impl serde::ser::Serialize for IndexBox { - fn serialize(&self, serializer: S) -> Result { - self.raw.serialize(serializer) - } -} - -#[cfg(feature = "serialize")] -impl<'de, I: Idx, T: serde::de::Deserialize<'de>> serde::de::Deserialize<'de> for IndexBox { - fn deserialize>(deserializer: D) -> Result { - Box::<[T]>::deserialize(deserializer).map(Into::into) - } -} - -#[cfg(test)] -#[allow(clippy::legacy_numeric_constants)] -mod test { - use super::*; - - define_index_type! { - pub struct TestIdx = u32; - } - - #[test] - fn test_resize() { - let mut v = IndexVec::::with_capacity(10); - assert_eq!(v.len(), 0); - assert!(v.is_empty()); - - v.push(1); - assert_eq!(v.len(), 1); - - v.resize(5, 1); - assert_eq!(v.len(), 5); - assert_eq!(v.as_slice(), &[1, 1, 1, 1, 1]); - - v.shrink_to_fit(); - assert_eq!(v.len(), 5); - } - - #[test] - fn test_push_pop() { - let mut v = IndexVec::::new(); - v.push(1); - assert_eq!(v.pop(), Some(1)); - } - - #[test] - fn test_clear() { - let mut v: IndexVec = [1, 2, 3].into_iter().collect(); - assert_eq!(v.len(), 3); - - v.clear(); - assert_eq!(v.len(), 0); - assert_eq!(v.as_slice(), &[]); - assert_eq!(v, IndexVec::::new()); - } -} diff --git a/crates/oxc_index/src/macros.rs b/crates/oxc_index/src/macros.rs deleted file mode 100644 index 391397a98312f..0000000000000 --- a/crates/oxc_index/src/macros.rs +++ /dev/null @@ -1,620 +0,0 @@ -/// Generate the boilerplate for a newtyped index struct, for use with -/// `IndexVec`. -/// -/// In the future, if the compile-time overhead of doing so is reduced, this may -/// be replaced with a proc macro. -/// -/// ## Usage -/// -/// ### Standard -/// -/// The rough usage pattern of this macro is: -/// -/// ```rust,no_run -/// oxc_index::define_index_type! { -/// // Note that isn't actually a type alias, `MyIndex` is -/// // actually defined as a struct. XXX is this too confusing? -/// pub struct MyIndex = u32; -/// // optional extra configuration here of the form: -/// // `OPTION_NAME = stuff;` -/// // See below for details. -/// } -/// ``` -/// -/// Note that you can use other index types than `u32`, and you can set it to be -/// `MyIndex(pub u32)` as well. Currently, the wrapped item be a tuple struct, -/// however (patches welcome). -/// -/// ### Customization -/// -/// After the struct declaration, there are a number of configuration options -/// the macro uses to customize how the type it generates behaves. For example: -/// -/// ```rust,no_run -/// oxc_index::define_index_type! { -/// pub struct Span = u32; -/// -/// // Don't allow any spans with values higher this. -/// MAX_INDEX = 0x7fff_ff00; -/// -/// // But I also am not too worried about it, so only -/// // perform the asserts in debug builds. -/// DISABLE_MAX_INDEX_CHECK = cfg!(not(debug_assertions)); -/// } -/// ``` -/// -/// ## Configuration options -/// -/// This macro has a few ways you can customize it's output behavior. There's -/// not really any great syntax I can think of for them, but, well. -/// -/// #### `MAX_INDEX = ` -/// -/// Assert if anything tries to construct an index above that value. -/// -/// By default, this is `$raw_type::max_value() as usize`, e.g. we check that -/// our cast from `usize` to our wrapper is lossless, but we assume any all -/// instance of `$raw_type` is valid in this index domain. -/// -/// Note that these tests can be disabled entirely, or conditionally, with -/// `DISABLE_MAX_INDEX_CHECK`. Additionally, the generated type has -/// `from_usize_unchecked` and `from_raw_unchecked` functions which can be used -/// to ignore these checks. -/// -/// #### `DISABLE_MAX_INDEX_CHECK = ;` -/// -/// Set to true to disable the assertions mentioned above. False by default. -/// -/// To be clear, if this is set to false, we blindly assume all casts between -/// `usize` and `$raw_type` succeed. -/// -/// A common use is setting `DISABLE_MAX_INDEX_CHECK = !cfg!(debug_assertions)` -/// to avoid the tests at compile time -/// -/// For the sake of clarity, disabling this cannot lead to memory unsafety -- we -/// still go through bounds checks when accessing slices, and no unsafe code -/// should rely on on these checks (unless you write some, and don't! only use -/// this for correctness!). -/// -/// #### `DEFAULT = ;` -/// If provided, we'll implement `Default` for the index type using this -/// expression. -/// -/// Example: -/// -/// ```rust,no_run -/// oxc_index::define_index_type! { -/// pub struct MyIdx = u16; -/// MAX_INDEX = (u16::max_value() - 1) as usize; -/// // Set the default index to be an invalid index, as -/// // a hacky way of having this type behave somewhat -/// // like it were an Option without consuming -/// // extra space. -/// DEFAULT = (MyIdx::from_raw_unchecked(u16::max_value())); -/// } -/// ``` -/// -/// #### `DEBUG_FORMAT = ;` -/// -/// By default we write the underlying integer out in a Debug implementation -/// with `{:?}`. Sometimes you'd like more info though. For example, the type of -/// the index. This can be done via `DEBUG_FORMAT`: -/// -/// ```rust -/// oxc_index::define_index_type! { -/// struct FooIdx = usize; -/// DEBUG_FORMAT = "Foo({})"; -/// } -/// // Then ... -/// # fn main() { -/// let v = FooIdx::new(10); -/// assert_eq!("Foo(10)", format!("{:?}", v)); -/// # } -/// ``` -/// -/// #### `DISPLAY_FORMAT = ;` -/// -/// Similarly to `DEBUG_FORMAT`, we can implement Display for you. Unlike -/// `DEBUG_FORMAT`, if you do not set this, we will not implement `Display` for -/// the index type. -/// -/// ```rust -/// oxc_index::define_index_type! { -/// struct FooIdx = usize; -/// DISPLAY_FORMAT = "{}"; -/// // Note that you can use both DEBUG_FORMAT and DISPLAY_FORMAT. -/// DEBUG_FORMAT = "#"; -/// } -/// // Then ... -/// # fn main() { -/// let v = FooIdx::new(10); -/// assert_eq!("10", format!("{}", v)); -/// assert_eq!("#", format!("{:?}", v)); -/// # } -/// ``` -/// -/// #### `IMPL_RAW_CONVERSIONS = true;` -/// -/// We always automatically implement `From for YourIndex` and -/// `From for usize`. We don't do this for the "raw" type (e.g. `u32` -/// if your type is declared as `struct FooIdx = u32;`), unless you request it -/// via this option. It's an error to use this if your raw type is usize. -/// -/// ```rust -/// oxc_index::define_index_type! { -/// struct FooIdx = u32; -/// IMPL_RAW_CONVERSIONS = true; -/// } -/// -/// # fn main() { -/// let as_index = FooIdx::from(5u32); -/// let as_u32 = u32::from(as_index); -/// assert_eq!(as_u32, 5); -/// # } -/// ``` -#[macro_export] -macro_rules! define_index_type { - // public api - ( - $(#[$attrs:meta])* - $v:vis struct $type:ident = $raw:ident; - $($CONFIG_NAME:ident = $value:expr;)* $(;)? - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]] - @decl [$v struct $type ($raw)] - @debug_fmt ["{}"] - @max [(<$raw>::max_value() as usize)] - @no_check_max [false] - } - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! unknown_define_index_type_option { - () => {}; -} - -#[cfg(feature = "serialize")] -#[macro_export] -#[doc(hidden)] -macro_rules! __internal_maybe_index_impl_serde { - ($type:ident) => { - impl serde::ser::Serialize for $type { - fn serialize( - &self, - serializer: S, - ) -> Result { - self.index().serialize(serializer) - } - } - - impl<'de> serde::de::Deserialize<'de> for $type { - fn deserialize>( - deserializer: D, - ) -> Result { - usize::deserialize(deserializer).map(Self::from_usize) - } - } - }; -} - -#[cfg(not(feature = "serialize"))] -#[macro_export] -#[doc(hidden)] -macro_rules! __internal_maybe_index_impl_serde { - ($type:ident) => {}; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! __define_index_type_inner { - // DISABLE_MAX_INDEX_CHECK - ( - @configs [(DISABLE_MAX_INDEX_CHECK; $no_check_max:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$_old_no_check_max:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$max] - @no_check_max [$no_check_max] - } - }; - - // MAX_INDEX - ( - @configs [(MAX_INDEX; $new_max:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$cm:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$new_max] - @no_check_max [$cm] - } - }; - - // DEFAULT - ( - @configs [(DEFAULT; $default_expr:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$max] - @no_check_max [$no_check_max] - } - impl Default for $type { - #[inline] - fn default() -> Self { - $default_expr - } - } - }; - - // DEBUG_FORMAT - ( - @configs [(DEBUG_FORMAT; $dbg:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$old_dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$max] - @no_check_max [$no_check_max] - } - }; - - // DISPLAY_FORMAT - ( - @configs [(DISPLAY_FORMAT; $format:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$max] - @no_check_max [$no_check_max] - } - - impl core::fmt::Display for $type { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, $format, self.index()) - } - } - }; - - // IMPL_RAW_CONVERSIONS - ( - @configs [(IMPL_RAW_CONVERSIONS; $val:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - $crate::__define_index_type_inner!{ - @configs [$(($CONFIG_NAME; $value))*] - @attrs [$(#[$attrs])*] - @derives [$(#[$derive])*] - @decl [$v struct $type ($raw)] - @debug_fmt [$dbg] - @max [$max] - @no_check_max [$no_check_max] - } - // Ensure they passed in true. This is... cludgey. - const _: [(); 1] = [(); $val as usize]; - - impl From<$type> for $raw { - #[inline] - fn from(v: $type) -> $raw { - v.raw() - } - } - - impl From<$raw> for $type { - #[inline] - fn from(value: $raw) -> Self { - Self::from_raw(value) - } - } - }; - // Try to make rust emit a decent error message... - ( - @configs [($other:ident; $format:expr) $(($CONFIG_NAME:ident; $value:expr))*] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - $crate::unknown_define_index_type_option!($other); - }; - // finish - ( - @configs [] - @attrs [$(#[$attrs:meta])*] - @derives [$(#[$derive:meta])*] - @decl [$v:vis struct $type:ident ($raw:ident)] - @debug_fmt [$dbg:expr] - @max [$max:expr] - @no_check_max [$no_check_max:expr] - ) => { - - $(#[$derive])* - $(#[$attrs])* - #[repr(transparent)] - $v struct $type { _raw: $raw } - - impl $type { - /// If `Self::CHECKS_MAX_INDEX` is true, we'll assert if trying to - /// produce a value larger than this in any of the ctors that don't - /// have `unchecked` in their name. - $v const MAX_INDEX: usize = $max; - - /// Does this index type assert if asked to construct an index - /// larger than MAX_INDEX? - $v const CHECKS_MAX_INDEX: bool = !$no_check_max; - - /// Construct this index type from a usize. Alias for `from_usize`. - #[inline(always)] - $v fn new(value: usize) -> Self { - Self::from_usize(value) - } - - /// Construct this index type from the wrapped integer type. - #[inline(always)] - $v fn from_raw(value: $raw) -> Self { - Self::from_usize(value as usize) - } - - /// Construct this index type from one in a different domain - #[inline(always)] - $v fn from_foreign(value: F) -> Self { - Self::from_usize(value.index()) - } - - /// Construct from a usize without any checks. - #[allow(clippy::cast_possible_truncation)] - #[inline(always)] - $v const fn from_usize_unchecked(value: usize) -> Self { - Self { _raw: value as $raw } - } - - /// Construct from the underlying type without any checks. - #[inline(always)] - $v const fn from_raw_unchecked(raw: $raw) -> Self { - Self { _raw: raw } - } - - /// Construct this index type from a usize. - #[allow(clippy::cast_possible_truncation)] - #[inline] - $v fn from_usize(value: usize) -> Self { - Self::check_index(value as usize); - Self { _raw: value as $raw } - } - - /// Get the wrapped index as a usize. - #[inline(always)] - $v const fn index(self) -> usize { - self._raw as usize - } - - /// Get the wrapped index. - #[inline(always)] - $v const fn raw(self) -> $raw { - self._raw - } - - /// Asserts `v <= Self::MAX_INDEX` unless Self::CHECKS_MAX_INDEX is false. - #[inline] - $v fn check_index(v: usize) { - if Self::CHECKS_MAX_INDEX && (v > Self::MAX_INDEX) { - $crate::__max_check_fail(v, Self::MAX_INDEX); - } - } - - const _ENSURE_RAW_IS_UNSIGNED: [(); 0] = [(); <$raw>::MIN as usize]; - } - - impl core::fmt::Debug for $type { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, $dbg, self.index()) - } - } - - impl core::cmp::PartialOrd for $type { - #[inline] - fn partial_cmp(&self, other: &usize) -> Option { - self.index().partial_cmp(other) - } - } - - impl core::cmp::PartialOrd<$type> for usize { - #[inline] - fn partial_cmp(&self, other: &$type) -> Option { - self.partial_cmp(&other.index()) - } - } - - impl PartialEq for $type { - #[inline] - fn eq(&self, other: &usize) -> bool { - self.index() == *other - } - } - - impl PartialEq<$type> for usize { - #[inline] - fn eq(&self, other: &$type) -> bool { - *self == other.index() - } - } - - impl core::ops::Add for $type { - type Output = Self; - #[inline] - fn add(self, other: usize) -> Self { - // use wrapping add so that it's up to the index type whether or - // not to check -- e.g. if checks are disabled, they're disabled - // on both debug and release. - Self::new(self.index().wrapping_add(other)) - } - } - - impl core::ops::Sub for $type { - type Output = Self; - #[inline] - fn sub(self, other: usize) -> Self { - // use wrapping sub so that it's up to the index type whether or - // not to check -- e.g. if checks are disabled, they're disabled - // on both debug and release. - Self::new(self.index().wrapping_sub(other)) - } - } - - impl core::ops::AddAssign for $type { - #[inline] - fn add_assign(&mut self, other: usize) { - *self = *self + other - } - } - - impl core::ops::SubAssign for $type { - #[inline] - fn sub_assign(&mut self, other: usize) { - *self = *self - other; - } - } - - impl core::ops::Rem for $type { - type Output = Self; - #[inline] - fn rem(self, other: usize) -> Self { - Self::new(self.index() % other) - } - } - - impl core::ops::Add<$type> for usize { - type Output = $type; - #[inline] - fn add(self, other: $type) -> $type { - other + self - } - } - - impl core::ops::Sub<$type> for usize { - type Output = $type; - #[inline] - fn sub(self, other: $type) -> $type { - $type::new(self.wrapping_sub(other.index())) - } - } - - impl core::ops::Add for $type { - type Output = $type; - #[inline] - fn add(self, other: $type) -> $type { - $type::new(other.index() + self.index()) - } - } - - impl core::ops::Sub for $type { - type Output = $type; - #[inline] - fn sub(self, other: $type) -> $type { - $type::new(self.index().wrapping_sub(other.index())) - } - } - - impl core::ops::AddAssign for $type { - #[inline] - fn add_assign(&mut self, other: $type) { - *self = *self + other - } - } - - impl core::ops::SubAssign for $type { - #[inline] - fn sub_assign(&mut self, other: $type) { - *self = *self - other; - } - } - - impl $crate::Idx for $type { - #[inline] - fn from_usize(value: usize) -> Self { - Self::from(value) - } - - #[inline] - fn index(self) -> usize { - usize::from(self) - } - } - - impl From<$type> for usize { - #[inline] - fn from(v: $type) -> usize { - v.index() - } - } - - impl From for $type { - #[inline] - fn from(value: usize) -> Self { - $type::from_usize(value) - } - } - - $crate::__internal_maybe_index_impl_serde!($type); - }; -} diff --git a/crates/oxc_index/src/rayon_impl.rs b/crates/oxc_index/src/rayon_impl.rs deleted file mode 100644 index fcd18c756674b..0000000000000 --- a/crates/oxc_index/src/rayon_impl.rs +++ /dev/null @@ -1,307 +0,0 @@ -//! Parallel iterator types for (`IndexVec`) -#![allow(clippy::undocumented_unsafe_blocks)] -#![allow(clippy::manual_assert)] -/// Disabled lint since we copy code from https://github.com/rayon-rs/rayon/blob/97c1133c2366a301a2d4ab35cf686bca7f74830f/src/vec.rs#L1-L284 -use alloc::vec::Vec; -use core::{ - iter, mem, - ops::{Range, RangeBounds}, - ptr, slice, -}; - -use rayon::{ - iter::{ - plumbing::{bridge, Consumer, Producer, ProducerCallback, UnindexedConsumer}, - IndexedParallelIterator, IntoParallelIterator, ParallelDrainRange, ParallelIterator, - }, - slice::{Iter, IterMut}, -}; - -use crate::{Idx, IndexVec}; - -impl<'data, I: Idx, T: Sync + 'data> IntoParallelIterator for &'data IndexVec { - type Item = &'data T; - type Iter = Iter<'data, T>; - - fn into_par_iter(self) -> Self::Iter { - <&[T]>::into_par_iter(&self.raw) - } -} - -impl<'data, I: Idx, T: Send + 'data> IntoParallelIterator for &'data mut IndexVec { - type Item = &'data mut T; - type Iter = IterMut<'data, T>; - - fn into_par_iter(self) -> Self::Iter { - <&mut [T]>::into_par_iter(&mut self.raw) - } -} - -/// Parallel iterator that moves out of a vector. -#[derive(Debug, Clone)] -pub struct IntoIter { - vec: Vec, -} - -impl IntoParallelIterator for IndexVec { - type Item = T; - type Iter = IntoIter; - - fn into_par_iter(self) -> Self::Iter { - IntoIter { vec: self.raw } - } -} - -impl ParallelIterator for IntoIter { - type Item = T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - bridge(self, consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl IndexedParallelIterator for IntoIter { - fn drive(self, consumer: C) -> C::Result - where - C: Consumer, - { - bridge(self, consumer) - } - - fn len(&self) -> usize { - self.vec.len() - } - - fn with_producer(mut self, callback: CB) -> CB::Output - where - CB: ProducerCallback, - { - // Drain every item, and then the vector only needs to free its buffer. - self.vec.par_drain(..).with_producer(callback) - } -} - -impl<'data, I: Idx, T: Send> ParallelDrainRange for &'data mut IndexVec { - type Item = T; - type Iter = Drain<'data, T>; - - fn par_drain>(self, range: R) -> Self::Iter { - Drain { orig_len: self.len(), range: simplify_range(range, self.len()), vec: &mut self.raw } - } -} - -/// Draining parallel iterator that moves a range out of a vector, but keeps the total capacity. -#[derive(Debug)] -pub struct Drain<'data, T: Send> { - vec: &'data mut Vec, - range: Range, - orig_len: usize, -} - -impl<'data, T: Send> ParallelIterator for Drain<'data, T> { - type Item = T; - - fn drive_unindexed(self, consumer: C) -> C::Result - where - C: UnindexedConsumer, - { - bridge(self, consumer) - } - - fn opt_len(&self) -> Option { - Some(self.len()) - } -} - -impl<'data, T: Send> IndexedParallelIterator for Drain<'data, T> { - fn drive(self, consumer: C) -> C::Result - where - C: Consumer, - { - bridge(self, consumer) - } - - fn len(&self) -> usize { - self.range.len() - } - - fn with_producer(self, callback: CB) -> CB::Output - where - CB: ProducerCallback, - { - unsafe { - // Make the vector forget about the drained items, and temporarily the tail too. - self.vec.set_len(self.range.start); - - // Create the producer as the exclusive "owner" of the slice. - let producer = DrainProducer::from_vec(self.vec, self.range.len()); - - // The producer will move or drop each item from the drained range. - callback.callback(producer) - } - } -} - -impl<'data, T: Send> Drop for Drain<'data, T> { - fn drop(&mut self) { - let Range { start, end } = self.range; - if self.vec.len() == self.orig_len { - // We must not have produced, so just call a normal drain to remove the items. - self.vec.drain(start..end); - } else if start == end { - // Empty range, so just restore the length to its original state - unsafe { - self.vec.set_len(self.orig_len); - } - } else if end < self.orig_len { - // The producer was responsible for consuming the drained items. - // Move the tail items to their new place, then set the length to include them. - unsafe { - let ptr = self.vec.as_mut_ptr().add(start); - let tail_ptr = self.vec.as_ptr().add(end); - let tail_len = self.orig_len - end; - ptr::copy(tail_ptr, ptr, tail_len); - self.vec.set_len(start + tail_len); - } - } - } -} - -/// //////////////////////////////////////////////////////////////////////// - -pub(crate) struct DrainProducer<'data, T: Send> { - slice: &'data mut [T], -} - -impl DrainProducer<'_, T> { - /// Creates a draining producer, which *moves* items from the slice. - /// - /// Unsafe because `!Copy` data must not be read after the borrow is released. - pub(crate) unsafe fn new(slice: &mut [T]) -> DrainProducer<'_, T> { - DrainProducer { slice } - } - - /// Creates a draining producer, which *moves* items from the tail of the vector. - /// - /// Unsafe because we're moving from beyond `vec.len()`, so the caller must ensure - /// that data is initialized and not read after the borrow is released. - unsafe fn from_vec(vec: &mut Vec, len: usize) -> DrainProducer<'_, T> { - let start = vec.len(); - assert!(vec.capacity() - start >= len); - - // The pointer is derived from `Vec` directly, not through a `Deref`, - // so it has provenance over the whole allocation. - let ptr = vec.as_mut_ptr().add(start); - DrainProducer::new(slice::from_raw_parts_mut(ptr, len)) - } -} - -impl<'data, T: 'data + Send> Producer for DrainProducer<'data, T> { - type IntoIter = SliceDrain<'data, T>; - type Item = T; - - fn into_iter(mut self) -> Self::IntoIter { - // replace the slice so we don't drop it twice - let slice = mem::take(&mut self.slice); - SliceDrain { iter: slice.iter_mut() } - } - - fn split_at(mut self, index: usize) -> (Self, Self) { - // replace the slice so we don't drop it twice - let slice = mem::take(&mut self.slice); - let (left, right) = slice.split_at_mut(index); - unsafe { (DrainProducer::new(left), DrainProducer::new(right)) } - } -} - -impl<'data, T: 'data + Send> Drop for DrainProducer<'data, T> { - fn drop(&mut self) { - // extract the slice so we can use `Drop for [T]` - let slice_ptr: *mut [T] = mem::take::<&'data mut [T]>(&mut self.slice); - unsafe { ptr::drop_in_place::<[T]>(slice_ptr) }; - } -} - -/// //////////////////////////////////////////////////////////////////////// - -// like std::vec::Drain, without updating a source Vec -pub(crate) struct SliceDrain<'data, T> { - iter: slice::IterMut<'data, T>, -} - -impl<'data, T: 'data> Iterator for SliceDrain<'data, T> { - type Item = T; - - fn next(&mut self) -> Option { - // Coerce the pointer early, so we don't keep the - // reference that's about to be invalidated. - let ptr: *const T = self.iter.next()?; - Some(unsafe { ptr::read(ptr) }) - } - - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } - - fn count(self) -> usize { - self.iter.len() - } -} - -impl<'data, T: 'data> DoubleEndedIterator for SliceDrain<'data, T> { - fn next_back(&mut self) -> Option { - // Coerce the pointer early, so we don't keep the - // reference that's about to be invalidated. - let ptr: *const T = self.iter.next_back()?; - Some(unsafe { ptr::read(ptr) }) - } -} - -impl<'data, T: 'data> ExactSizeIterator for SliceDrain<'data, T> { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl<'data, T: 'data> iter::FusedIterator for SliceDrain<'data, T> {} - -impl<'data, T: 'data> Drop for SliceDrain<'data, T> { - fn drop(&mut self) { - // extract the iterator so we can use `Drop for [T]` - let slice_ptr: *mut [T] = mem::replace(&mut self.iter, [].iter_mut()).into_slice(); - unsafe { ptr::drop_in_place::<[T]>(slice_ptr) }; - } -} - -use core::ops::Bound; - -/// Normalize arbitrary `RangeBounds` to a `Range` -pub(super) fn simplify_range(range: impl RangeBounds, len: usize) -> Range { - let start = match range.start_bound() { - Bound::Unbounded => 0, - Bound::Included(&i) if i <= len => i, - Bound::Excluded(&i) if i < len => i + 1, - bound => panic!("range start {:?} should be <= length {}", bound, len), - }; - let end = match range.end_bound() { - Bound::Unbounded => len, - Bound::Excluded(&i) if i <= len => i, - Bound::Included(&i) if i < len => i + 1, - bound => panic!("range end {:?} should be <= length {}", bound, len), - }; - if start > end { - panic!( - "range start {:?} should be <= range end {:?}", - range.start_bound(), - range.end_bound() - ); - } - start..end -} diff --git a/crates/oxc_index/tests/test.rs b/crates/oxc_index/tests/test.rs deleted file mode 100644 index 926ab0835c99c..0000000000000 --- a/crates/oxc_index/tests/test.rs +++ /dev/null @@ -1,551 +0,0 @@ -#![allow( - clippy::assertions_on_constants, - clippy::eq_op, - clippy::uninlined_format_args, - clippy::should_panic_without_expect, - clippy::cast_possible_truncation -)] - -use oxc_index::{index_vec, IndexSlice, IndexVec}; - -oxc_index::define_index_type! { - pub struct USize16 = usize; - MAX_INDEX = u16::MAX as usize; - DEFAULT = USize16::from_raw_unchecked(usize::MAX); -} - -oxc_index::define_index_type! { - pub struct ZeroMaxIgnore = u16; - MAX_INDEX = 0; - DISABLE_MAX_INDEX_CHECK = true; -} - -oxc_index::define_index_type! { - pub struct ZeroMax = u16; - MAX_INDEX = 0; -} - -oxc_index::define_index_type! { - pub struct IdxSz = usize; -} - -oxc_index::define_index_type! { - pub struct Idx32 = u32; - DEBUG_FORMAT = "Test({:?})"; - DISPLAY_FORMAT = "foo {}"; - IMPL_RAW_CONVERSIONS = true; -} - -oxc_index::define_index_type! { - pub struct Idx16 = u16; -} - -oxc_index::define_index_type! { - pub struct Idx8 = u8; -} - -oxc_index::define_index_type! { - pub struct SmallCheckedEarly = u8; - MAX_INDEX = 0x7f; -} - -oxc_index::define_index_type! { - pub struct SmallChecked = u8; -} - -oxc_index::define_index_type! { - pub struct SmallUnchecked = u8; - DISABLE_MAX_INDEX_CHECK = true; -} - -oxc_index::define_index_type! { - pub struct SmallUncheckedEarly = u8; - DISABLE_MAX_INDEX_CHECK = true; - MAX_INDEX = 0x7f; -} - -#[test] -fn test_idx_default_max() { - assert_eq!(Idx32::MAX_INDEX, u32::MAX as usize); - assert_eq!(IdxSz::MAX_INDEX, usize::MAX); - assert_eq!(Idx16::MAX_INDEX, u16::MAX as usize); - assert_eq!(Idx8::MAX_INDEX, u8::MAX as usize); - - assert!(Idx32::CHECKS_MAX_INDEX); - assert!(IdxSz::CHECKS_MAX_INDEX); - assert!(Idx16::CHECKS_MAX_INDEX); - assert!(Idx8::CHECKS_MAX_INDEX); - - assert!(!ZeroMaxIgnore::CHECKS_MAX_INDEX); - assert_eq!(ZeroMaxIgnore::MAX_INDEX, 0); -} - -#[test] -fn test_idx_arith() { - assert_eq!(Idx32::new(0), 0usize); - assert_eq!(Idx32::new(0) + 1, 1usize); - assert_eq!(1 + Idx32::new(0), 1usize); - - assert_eq!(Idx32::new(1) - 1, 0usize); - assert_eq!(Idx32::new(5) % 4, 1usize); - - let mut m = Idx32::new(5); - m += 1; - assert_eq!(m, 6); - - assert!(Idx32::new(5) < Idx32::new(6)); - assert!(Idx32::new(5) < 6usize); - - assert!(Idx32::new(5) < Idx32::new(6)); - assert!(Idx32::new(5) < 6usize); - assert!(5usize < Idx32::new(6)); -} - -#[test] -fn test_idx_checks1() { - let v: u32 = Idx32::new(4).raw(); - assert_eq!(v, 4); - - let u: usize = Idx32::new(4).index(); - assert_eq!(u, 4); - - assert_eq!(SmallCheckedEarly::from_raw_unchecked(0xff).raw(), 0xff); - - assert!(SmallChecked::CHECKS_MAX_INDEX); - assert!(SmallCheckedEarly::CHECKS_MAX_INDEX); - - assert_eq!(SmallChecked::MAX_INDEX, 255); - assert_eq!(SmallCheckedEarly::MAX_INDEX, 0x7f); - - assert!(!SmallUnchecked::CHECKS_MAX_INDEX); - assert!(!SmallUncheckedEarly::CHECKS_MAX_INDEX); - - assert_eq!(SmallUnchecked::MAX_INDEX, 255); - assert_eq!(SmallUncheckedEarly::MAX_INDEX, 0x7f); -} - -#[test] -fn test_idx_checks2() { - // all shouldn't panic - - let v = SmallChecked::from_raw(150); - assert_eq!(v, 150); - let v = SmallChecked::from_usize(150); - assert_eq!(v, 150); - let v = SmallChecked::from_usize(255); - assert_eq!(v, 255); - let v = SmallChecked::from_usize(0); - assert_eq!(v, 0); - - let v = SmallCheckedEarly::from_usize(0x7f); - assert_eq!(v, 0x7f); - let v = SmallCheckedEarly::from_usize(0); - assert_eq!(v, 0); - - let v = SmallUncheckedEarly::from_raw(0xff); - assert_eq!(v, 0xff); - let v = SmallUncheckedEarly::from_usize(150); - assert_eq!(v, 150); - let v = SmallUncheckedEarly::from_usize(300); - assert_eq!(v.raw(), 300usize as u8); - let v = SmallUnchecked::from_usize(150); - assert_eq!(v, 150); - let v = SmallUnchecked::from_usize(300); - assert_eq!(v.raw(), 300usize as u8); - - let v = SmallCheckedEarly::from_raw_unchecked(0xff); - assert_eq!(v, 0xff); - let v = SmallCheckedEarly::from_usize_unchecked(150); - assert_eq!(v, 150); - let v = SmallCheckedEarly::from_usize_unchecked(300); - assert_eq!(v.raw(), 300usize as u8); - let v = SmallChecked::from_usize_unchecked(300); - assert_eq!(v.raw(), 300usize as u8); - - assert_eq!(::default().index(), usize::MAX); - - let v = ZeroMaxIgnore::new((u16::MAX as usize) + 1); - assert_eq!(v, 0); - let v = ZeroMaxIgnore::new(0) + 1; - assert_eq!(v, 1); - // let _ = ZeroMaxIgnore::new(0) - 1; - let v = ZeroMaxIgnore::new(2); - assert_eq!(v, 2); - let v = ZeroMaxIgnore::new((u16::MAX as usize) + 1); - assert_eq!(v, 0); -} - -#[test] -#[should_panic] -fn test_idx_sc_cf_raw() { - let _ = SmallCheckedEarly::from_raw(0xff); -} -#[test] -#[should_panic] -fn test_idx_sc_cf_idx0() { - let _ = SmallCheckedEarly::from_usize(150); -} -#[test] -#[should_panic] -fn test_idx_sc_cf_idx1() { - let _ = SmallCheckedEarly::from_usize(300); -} -#[test] -#[should_panic] -fn test_idx_sc_cf_idx2() { - let _ = SmallChecked::from_usize(300); -} -#[test] -#[should_panic] -fn test_idx_sc_of_add() { - let _ = SmallChecked::from_usize(255) + 1; -} -#[test] -#[should_panic] -fn test_idx_sc_of_addassign() { - let mut e2 = SmallChecked::from_usize(255); - e2 += 1; -} -#[test] -#[should_panic] -fn test_idx_sc_of_sub() { - let _ = SmallChecked::from_usize(0) - 1; -} -#[test] -#[should_panic] -fn test_idx_sc_of_subassign() { - let mut z2 = SmallChecked::from_usize(0); - z2 -= 1; -} - -#[test] -#[should_panic] -fn test_idx_zm_cf_idx() { - let _ = ZeroMax::new(2); -} -#[test] -#[should_panic] -fn test_idx_zm_cf_raw() { - let _ = ZeroMax::from_raw(2); -} - -#[test] -#[should_panic] -fn test_idx_zm_of_add0() { - let _ = ZeroMax::new(0) + 1; -} -#[test] -#[should_panic] -fn test_idx_zm_of_sub0() { - let _ = ZeroMax::new(0) - 1; -} -#[test] -#[should_panic] -fn test_idx_zm_of_nowrap() { - let _ = ZeroMax::new((u16::MAX as usize) + 1); -} - -#[test] -#[should_panic] -fn test_idx_sce_adde() { - let _ = SmallCheckedEarly::from_usize(0x7f) + 1; -} -#[test] -#[should_panic] -fn test_idx_sce_addassign() { - let mut e3 = SmallCheckedEarly::from_usize(0x7f); - e3 += 1; -} -#[test] -#[should_panic] -fn test_idx_sce_sub() { - let _ = SmallCheckedEarly::from_usize(0) - 1; -} -#[test] -#[should_panic] -fn test_idx_sce_subassign() { - let mut z3 = SmallCheckedEarly::from_usize(0); - z3 -= 1; -} - -#[test] -fn test_vec() { - let mut strs: IndexVec = index_vec!["strs", "bar", "baz"]; - - let l = strs.last_idx(); - assert_eq!(strs[l], "baz"); - - let new_i = strs.push("quux"); - assert_eq!(strs[new_i], "quux"); -} - -#[test] -fn test_idx() { - let mut e = Idx32::new(0); - let one = Idx32::new(1); - e += 1; - assert_eq!(e, 1); - e -= 1; - assert_eq!(e, 0); - e += one; - assert_eq!(e, 1); - e -= one; - assert_eq!(e, 0); - let e2 = e + one; - assert_eq!(e2, 1); - let e2 = e2 - one; - assert_eq!(e2, 0); - - let e2 = e + 1; - assert_eq!(e2, 1); - let e2 = e2 - 1; - assert_eq!(0, e2); - - assert_eq!(40usize - Idx32::new(10), 30); - - assert_eq!(u32::from(Idx32::new(500)), 500); - assert_eq!(Idx32::from(500u32), 500); -} - -#[test] -fn test_fmt() { - let i = format!("{:?}", Idx32::new(30)); - assert_eq!(i, "Test(30)"); - let i = format!("{}", Idx32::new(30)); - assert_eq!(i, "foo 30"); - - let v: IndexVec = index_vec![3, 4, 5]; - assert_eq!(format!("{:?}", v), format!("{:?}", vec![3, 4, 5])); - assert_eq!(format!("{:#?}", v), format!("{:#?}", vec![3, 4, 5])); - assert_eq!(format!("{:?}", &v[..]), format!("{:?}", &[3, 4, 5])); -} - -#[test] -fn test_partial_eq() { - let i0: IndexVec = index_vec![0]; - let i1: IndexVec = index_vec![1]; - let i123: IndexVec = index_vec![1, 2, 3]; - - assert_eq!(i0, i0); - assert_ne!(i0, i1); - assert_eq!(i123, vec![1, 2, 3]); - assert_eq!(i123, &[1, 2, 3]); - assert_eq!(i123, [1, 2, 3]); - assert_eq!(i123[..], [1, 2, 3]); - assert_eq!(i123[..Idx32::new(1)], [1usize]); - assert_eq!(i123[..Idx32::new(1)], i1.as_slice()); - assert_eq!(i123[..Idx32::new(1)], i1.as_raw_slice()); -} - -#[test] -fn test_drain() { - let mut vec: IndexVec = index_vec![1, 2, 3]; - let mut vec2: IndexVec = index_vec![]; - for i in vec.drain(..) { - vec2.push(i); - } - assert!(vec.is_empty()); - assert_eq!(vec2, [1, 2, 3]); - - let mut vec: IndexVec = index_vec![1, 2, 3]; - let mut vec2: IndexVec = index_vec![]; - for i in vec.drain(Idx32::from_raw(1)..) { - vec2.push(i); - } - assert_eq!(vec, [1]); - assert_eq!(vec2, [2, 3]); - - let mut vec: IndexVec = index_vec![(), (), ()]; - let mut vec2: IndexVec = index_vec![]; - for _i in vec.drain(..) { - vec2.push(()); - } - assert_eq!(vec, []); - assert_eq!(vec2, [(), (), ()]); -} - -#[test] -fn test_drain_enumerated() { - let mut vec: IndexVec = index_vec![1, 2, 3]; - let mut vec2: IndexVec = index_vec![]; - for (i, j) in vec.drain_enumerated(..) { - assert_eq!(i.index() + 1, j); - vec2.push(j); - } - assert!(vec.is_empty()); - assert_eq!(vec2, [1, 2, 3]); -} - -#[test] -fn test_position() { - let b: &IndexSlice = IndexSlice::new(&[1, 2, 3, 5, 5]); - assert_eq!(b.position(|&v| v == 9), None); - assert_eq!(b.position(|&v| v == 5), Some(IdxSz::from_raw(3))); - assert_eq!(b.position(|&v| v == 3), Some(IdxSz::from_raw(2))); - assert_eq!(b.position(|&v| v == 0), None); -} - -#[test] -fn test_rposition() { - let b: &IndexSlice = IndexSlice::new(&[1, 2, 3, 5, 5]); - assert_eq!(b.rposition(|&v| v == 9), None); - assert_eq!(b.rposition(|&v| v == 5), Some(IdxSz::from_raw(4))); - assert_eq!(b.rposition(|&v| v == 3), Some(IdxSz::from_raw(2))); - assert_eq!(b.rposition(|&v| v == 0), None); -} - -#[test] -fn test_binary_search() { - let b: &IndexSlice = IndexSlice::new(&[]); - assert_eq!(b.binary_search(&5), Err(IdxSz::new(0))); - - let b: &IndexSlice = IndexSlice::new(&[4]); - assert_eq!(b.binary_search(&3), Err(IdxSz::new(0))); - assert_eq!(b.binary_search(&4), Ok(IdxSz::new(0))); - assert_eq!(b.binary_search(&5), Err(IdxSz::new(1))); -} - -#[test] -fn test_chunk_iters() { - let mut v: IndexVec = index_vec![0, 1, 2, 3, 4]; - assert_eq!( - v.chunks(3).collect::>(), - &[IndexSlice::new(&[0, 1, 2]), IndexSlice::new(&[3, 4])] - ); - assert_eq!( - v.chunks_mut(3).collect::>(), - &[IndexSlice::new_mut(&mut [0, 1, 2]), IndexSlice::new_mut(&mut [3, 4])] - ); - - assert_eq!(v.chunks_exact(3).collect::>(), &[IndexSlice::new(&[0, 1, 2])]); - assert_eq!(v.chunks_exact_mut(3).collect::>(), &[IndexSlice::new_mut(&mut [0, 1, 2])]); - - assert_eq!( - v.rchunks(3).collect::>(), - &[IndexSlice::new(&[2, 3, 4]), IndexSlice::new(&[0, 1])] - ); - assert_eq!( - v.rchunks_mut(3).collect::>(), - &[IndexSlice::new_mut(&mut [2, 3, 4]), IndexSlice::new_mut(&mut [0, 1])] - ); - - assert_eq!(v.rchunks_exact(3).collect::>(), &[IndexSlice::new(&[2, 3, 4])]); - assert_eq!(v.rchunks_exact_mut(3).collect::>(), &[IndexSlice::new_mut(&mut [2, 3, 4])]); - assert_eq!( - v.windows(2).collect::>(), - &[ - IndexSlice::new(&[0, 1]), - IndexSlice::new(&[1, 2]), - IndexSlice::new(&[2, 3]), - IndexSlice::new(&[3, 4]) - ] - ); -} - -#[test] -fn test_indexing() { - let v: IndexVec = index_vec![0, 1, 2, 3, 4]; - assert_eq!(v[..], &[0, 1, 2, 3, 4]); - assert_eq!(v[IdxSz::new(1)..], &[1, 2, 3, 4]); - assert_eq!(v[IdxSz::new(1)..IdxSz::new(3)], &[1, 2]); - assert_eq!(v[IdxSz::new(1)..=IdxSz::new(3)], &[1, 2, 3]); - assert_eq!(v[..=IdxSz::new(3)], &[0, 1, 2, 3]); - - assert_eq!(v[IdxSz::new(3)], 3); - - // Make sure the types are as expected - let s: &IndexSlice = &v[..]; - assert_eq!(s, &[0, 1, 2, 3, 4]); - let s: &IndexSlice = &v[IdxSz::new(1)..]; - assert_eq!(s, &[1, 2, 3, 4]); - let s: &IndexSlice = &v[IdxSz::new(1)..IdxSz::new(3)]; - assert_eq!(s, &[1, 2]); - let s: &IndexSlice = &v[IdxSz::new(1)..=IdxSz::new(3)]; - assert_eq!(s, &[1, 2, 3]); - let s: &IndexSlice = &v[..=IdxSz::new(3)]; - assert_eq!(s, &[0, 1, 2, 3]); - - let mut v: IndexVec = index_vec![0, 1, 2, 3, 4]; - // check `IndexMut` - { - let s: &mut IndexSlice = &mut v[..]; - assert_eq!(s, &[0, 1, 2, 3, 4]); - } - { - let s: &mut IndexSlice = &mut v[IdxSz::new(1)..]; - assert_eq!(s, &[1, 2, 3, 4]); - } - { - let s: &mut IndexSlice = &mut v[IdxSz::new(1)..IdxSz::new(3)]; - assert_eq!(s, &[1, 2]); - } - { - let s: &mut IndexSlice = &mut v[IdxSz::new(1)..=IdxSz::new(3)]; - assert_eq!(s, &[1, 2, 3]); - } - { - let s: &mut IndexSlice = &mut v[..=IdxSz::new(3)]; - assert_eq!(s, &[0, 1, 2, 3]); - } - assert_eq!(&mut v[IdxSz::new(3)], &mut 3); -} - -#[test] -fn test_get() { - let v: IndexVec = index_vec![0, 1, 2, 3, 4]; - - let s: Option<&IndexSlice> = v.get(..); - assert_eq!(s.unwrap(), &[0, 1, 2, 3, 4]); - let s: Option<&IndexSlice> = v.get(IdxSz::new(1)..); - assert_eq!(s.unwrap(), &[1, 2, 3, 4]); - let s: Option<&IndexSlice> = v.get(IdxSz::new(1)..IdxSz::new(3)); - assert_eq!(s.unwrap(), &[1, 2]); - let s: Option<&IndexSlice> = v.get(IdxSz::new(1)..=IdxSz::new(3)); - assert_eq!(s.unwrap(), &[1, 2, 3]); - let s: Option<&IndexSlice> = v.get(..=IdxSz::new(3)); - assert_eq!(s.unwrap(), &[0, 1, 2, 3]); - - assert_eq!(v.get(IdxSz::new(3)), Some(&3)); -} - -#[test] -fn test_get_mut() { - let mut v: IndexVec = index_vec![0, 1, 2, 3, 4]; - let s: Option<&mut IndexSlice> = v.get_mut(..); - assert_eq!(s.unwrap(), &[0, 1, 2, 3, 4]); - let s: Option<&mut IndexSlice> = v.get_mut(IdxSz::new(1)..); - assert_eq!(s.unwrap(), &[1, 2, 3, 4]); - let s: Option<&mut IndexSlice> = v.get_mut(IdxSz::new(1)..IdxSz::new(3)); - assert_eq!(s.unwrap(), &[1, 2]); - let s: Option<&mut IndexSlice> = v.get_mut(IdxSz::new(1)..=IdxSz::new(3)); - assert_eq!(s.unwrap(), &[1, 2, 3]); - let s: Option<&mut IndexSlice> = v.get_mut(..=IdxSz::new(3)); - assert_eq!(s.unwrap(), &[0, 1, 2, 3]); - assert_eq!(v.get_mut(IdxSz::new(3)), Some(&mut 3)); -} - -#[test] -fn test_splits() { - let v: IndexVec = index_vec![0, 1, 2, 3, 4]; - let (a, b): (&i32, &IndexSlice) = v.split_first().unwrap(); - assert_eq!(a, &0); - assert_eq!(b, &[1, 2, 3, 4]); - - let (a, b): (&i32, &IndexSlice) = v.split_last().unwrap(); - assert_eq!(a, &4); - assert_eq!(b, &[0, 1, 2, 3]); - let mut v: IndexVec = index_vec![0, 1, 2, 3, 4]; - let (a, b): (&mut i32, &mut IndexSlice) = v.split_first_mut().unwrap(); - assert_eq!(a, &0); - assert_eq!(b, &[1, 2, 3, 4]); - - let (a, b): (&mut i32, &mut IndexSlice) = v.split_last_mut().unwrap(); - assert_eq!(a, &4); - assert_eq!(b, &[0, 1, 2, 3]); - - let mut v: IndexVec = index_vec![]; - assert!(v.split_first().is_none()); - assert!(v.split_last().is_none()); - assert!(v.split_first_mut().is_none()); - assert!(v.split_last_mut().is_none()); -}