Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions crates/oxc_data_structures/src/stack/non_empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ impl<T> NonEmptyStack<T> {
}

/// Get if stack is empty. Always returns `false`.
///
/// Probably you want [`is_exhausted`] instead.
///
/// [`is_exhausted`]: Self::is_exhausted
#[expect(clippy::unused_self)]
#[inline]
pub fn is_empty(&self) -> bool {
Expand All @@ -362,6 +366,22 @@ impl<T> NonEmptyStack<T> {
false
}

/// Get if stack is back in its initial state.
/// i.e. Every `push` has been followed by a corresponding `pop`.
///
/// [`NonEmptyStack`] is never empty, so this is the closest thing to `is_empty` that makes sense.
///
/// If this method returns `true`, the stack only contains the initial element,
/// and calling [`pop`] will panic.
///
/// Equivalent to `stack.len() == 1`.
///
/// [`pop`]: Self::pop
#[inline]
pub fn is_exhausted(&self) -> bool {
self.cursor == self.start
}

/// Get capacity.
#[inline]
pub fn capacity(&self) -> usize {
Expand Down Expand Up @@ -460,6 +480,22 @@ mod tests {
NonEmptyStack::with_capacity(0, 10u64);
}

#[test]
fn is_exhausted() {
let mut stack = NonEmptyStack::new(0u64);
assert!(stack.is_exhausted());

stack.push(10);
assert!(!stack.is_exhausted());
stack.push(20);
assert!(!stack.is_exhausted());

stack.pop();
assert!(!stack.is_exhausted());
stack.pop();
assert!(stack.is_exhausted());
}

#[test]
fn push_then_pop() {
let mut stack = NonEmptyStack::new(10u64);
Expand Down
45 changes: 45 additions & 0 deletions crates/oxc_data_structures/src/stack/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,22 @@ impl<T> SparseStack<T> {
self.has_values.len()
}

/// Get if stack is back in its initial state.
/// i.e. Every `push` has been followed by a corresponding `pop`.
///
/// [`SparseStack`] is never empty, so this is the closest thing to `is_empty` that makes sense.
///
/// If this method returns `true`, the stack only contains the initial element,
/// and calling [`pop`] will panic.
///
/// Equivalent to `stack.len() == 1`.
///
/// [`pop`]: Self::pop
#[inline]
pub fn is_exhausted(&self) -> bool {
self.has_values.is_exhausted()
}

/// Get number of filled entries on the stack.
#[inline]
pub fn filled_len(&self) -> usize {
Expand Down Expand Up @@ -285,3 +301,32 @@ impl<T> SparseStack<T> {
self.values.as_mut_slice()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn is_exhausted() {
let mut stack = SparseStack::<u64>::new();
assert!(stack.is_exhausted());

stack.push(None);
assert!(!stack.is_exhausted());
stack.push(None);
assert!(!stack.is_exhausted());
stack.pop();
assert!(!stack.is_exhausted());
stack.pop();
assert!(stack.is_exhausted());

stack.push(Some(10));
assert!(!stack.is_exhausted());
stack.push(Some(20));
assert!(!stack.is_exhausted());
stack.pop();
assert!(!stack.is_exhausted());
stack.pop();
assert!(stack.is_exhausted());
}
}
Loading