diff --git a/crates/oxc_data_structures/src/stack/common.rs b/crates/oxc_data_structures/src/stack/common.rs index 0fdfb98a09bad..e63c27e0d7cfc 100644 --- a/crates/oxc_data_structures/src/stack/common.rs +++ b/crates/oxc_data_structures/src/stack/common.rs @@ -3,7 +3,7 @@ use std::{ alloc::{self, Layout}, mem::{align_of, size_of}, - ptr, + ptr, slice, }; use assert_unchecked::assert_unchecked; @@ -186,6 +186,20 @@ pub trait StackCommon: StackCapacity { self.end().byte_offset_from(self.start()) as usize } } + + /// Get contents of stack as a slice `&[T]`. + #[inline] + fn as_slice(&self) -> &[T] { + // SAFETY: Stack always contains `self.len()` entries, starting at `self.start()` + unsafe { slice::from_raw_parts(self.start().as_ptr(), self.len()) } + } + + /// Get contents of stack as a mutable slice `&mut [T]`. + #[inline] + fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: Stack always contains `self.len()` entries, starting at `self.start()` + unsafe { slice::from_raw_parts_mut(self.start().as_ptr(), self.len()) } + } } /// Make allocation of with provided layout. diff --git a/crates/oxc_data_structures/src/stack/non_empty.rs b/crates/oxc_data_structures/src/stack/non_empty.rs index e248cd9c4ce0a..170a8820a5727 100644 --- a/crates/oxc_data_structures/src/stack/non_empty.rs +++ b/crates/oxc_data_structures/src/stack/non_empty.rs @@ -1,6 +1,9 @@ #![expect(clippy::unnecessary_safety_comment)] -use std::mem::size_of; +use std::{ + mem::size_of, + ops::{Deref, DerefMut}, +}; use super::{NonNull, StackCapacity, StackCommon}; @@ -301,6 +304,18 @@ impl NonEmptyStack { pub fn capacity(&self) -> usize { >::capacity(self) } + + /// Get contents of stack as a slice `&[T]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + >::as_slice(self) + } + + /// Get contents of stack as a mutable slice `&mut [T]`. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + >::as_mut_slice(self) + } } impl Drop for NonEmptyStack { @@ -316,6 +331,22 @@ impl Drop for NonEmptyStack { } } +impl Deref for NonEmptyStack { + type Target = [T]; + + #[inline] + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +impl DerefMut for NonEmptyStack { + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/oxc_data_structures/src/stack/standard.rs b/crates/oxc_data_structures/src/stack/standard.rs index dddd17dc50c5f..5c8bc67ef306d 100644 --- a/crates/oxc_data_structures/src/stack/standard.rs +++ b/crates/oxc_data_structures/src/stack/standard.rs @@ -1,6 +1,9 @@ #![expect(clippy::unnecessary_safety_comment)] -use std::mem::size_of; +use std::{ + mem::size_of, + ops::{Deref, DerefMut}, +}; use super::{NonNull, StackCapacity, StackCommon}; @@ -324,6 +327,18 @@ impl Stack { pub fn capacity(&self) -> usize { >::capacity(self) } + + /// Get contents of stack as a slice `&[T]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + >::as_slice(self) + } + + /// Get contents of stack as a mutable slice `&mut [T]`. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + >::as_mut_slice(self) + } } impl Drop for Stack { @@ -345,6 +360,22 @@ impl Drop for Stack { } } +impl Deref for Stack { + type Target = [T]; + + #[inline] + fn deref(&self) -> &[T] { + self.as_slice() + } +} + +impl DerefMut for Stack { + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + #[cfg(test)] mod tests { use super::*;