mirror of
https://github.com/danbulant/oxc
synced 2026-05-20 04:38:54 +00:00
refactor(data_structures): add len method to StackCommon trait (#6215)
`len` method is in common between all stack types. Move it into `StackCommon` trait.
This commit is contained in:
parent
f7d113625e
commit
dbfa0bc01f
3 changed files with 31 additions and 19 deletions
|
|
@ -11,7 +11,7 @@ use assert_unchecked::assert_unchecked;
|
||||||
use super::{NonNull, StackCapacity};
|
use super::{NonNull, StackCapacity};
|
||||||
|
|
||||||
pub trait StackCommon<T>: StackCapacity<T> {
|
pub trait StackCommon<T>: StackCapacity<T> {
|
||||||
// Getter setter methods defined by implementer
|
// Getter + setter methods defined by implementer
|
||||||
fn start(&self) -> NonNull<T>;
|
fn start(&self) -> NonNull<T>;
|
||||||
fn end(&self) -> NonNull<T>;
|
fn end(&self) -> NonNull<T>;
|
||||||
fn cursor(&self) -> NonNull<T>;
|
fn cursor(&self) -> NonNull<T>;
|
||||||
|
|
@ -19,6 +19,9 @@ pub trait StackCommon<T>: StackCapacity<T> {
|
||||||
fn set_end(&mut self, end: NonNull<T>);
|
fn set_end(&mut self, end: NonNull<T>);
|
||||||
fn set_cursor(&mut self, cursor: NonNull<T>);
|
fn set_cursor(&mut self, cursor: NonNull<T>);
|
||||||
|
|
||||||
|
// Defined by implementer
|
||||||
|
fn len(&self) -> usize;
|
||||||
|
|
||||||
/// Make allocation of `capacity_bytes` bytes, aligned for `T`.
|
/// Make allocation of `capacity_bytes` bytes, aligned for `T`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
|
|
@ -98,12 +101,12 @@ pub trait StackCommon<T>: StackCapacity<T> {
|
||||||
///
|
///
|
||||||
/// # SAFETY
|
/// # SAFETY
|
||||||
/// * Stack must be allocated.
|
/// * Stack must be allocated.
|
||||||
/// * Stack must contain `len` initialized entries, starting at `self.start()`.
|
/// * Stack must contain `self.len()` initialized entries, starting at `self.start()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn drop_contents(&self, len: usize) {
|
unsafe fn drop_contents(&self) {
|
||||||
// Drop contents. Next line copied from `std`'s `Vec`.
|
// Drop contents. Next line copied from `std`'s `Vec`.
|
||||||
// SAFETY: Caller guarantees stack contains `len` initialized entries, starting at `start`.
|
// SAFETY: Caller guarantees stack contains `len` initialized entries, starting at `start`.
|
||||||
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.start().as_ptr(), len));
|
ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.start().as_ptr(), self.len()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get layout for allocation of `capacity_bytes` bytes.
|
/// Get layout for allocation of `capacity_bytes` bytes.
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,19 @@ impl<T> StackCommon<T> for NonEmptyStack<T> {
|
||||||
fn set_cursor(&mut self, cursor: NonNull<T>) {
|
fn set_cursor(&mut self, cursor: NonNull<T>) {
|
||||||
self.cursor = cursor;
|
self.cursor = cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
// SAFETY: `self.start` and `self.cursor` are both derived from same pointer.
|
||||||
|
// `self.cursor` is always >= `self.start`.
|
||||||
|
// Distance between pointers is always a multiple of `size_of::<T>()`.
|
||||||
|
let offset = unsafe { self.cursor_offset() };
|
||||||
|
|
||||||
|
// When stack has 1 entry, `start - cursor == 0`, so add 1 to get number of entries.
|
||||||
|
// SAFETY: Capacity cannot exceed `Self::MAX_CAPACITY`, which is `<= isize::MAX`,
|
||||||
|
// and offset can't exceed capacity, so `+ 1` cannot wrap around.
|
||||||
|
offset + 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> NonEmptyStack<T> {
|
impl<T> NonEmptyStack<T> {
|
||||||
|
|
@ -275,15 +288,7 @@ impl<T> NonEmptyStack<T> {
|
||||||
/// Number of entries is always at least 1. Stack is never empty.
|
/// Number of entries is always at least 1. Stack is never empty.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
// SAFETY: `self.start` and `self.cursor` are both derived from same pointer.
|
<Self as StackCommon<T>>::len(self)
|
||||||
// `self.cursor` is always >= `self.start`.
|
|
||||||
// Distance between pointers is always a multiple of `size_of::<T>()`.
|
|
||||||
let offset = unsafe { self.cursor_offset() };
|
|
||||||
|
|
||||||
// When stack has 1 entry, `start - cursor == 0`, so add 1 to get number of entries.
|
|
||||||
// SAFETY: Capacity cannot exceed `Self::MAX_CAPACITY`, which is `<= isize::MAX`,
|
|
||||||
// and offset can't exceed capacity, so `+ 1` cannot wrap around.
|
|
||||||
offset + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -303,7 +308,7 @@ impl<T> Drop for NonEmptyStack<T> {
|
||||||
// Drop contents.
|
// Drop contents.
|
||||||
// SAFETY: Stack is always allocated, and contains `self.len()` initialized entries,
|
// SAFETY: Stack is always allocated, and contains `self.len()` initialized entries,
|
||||||
// starting at `self.start`.
|
// starting at `self.start`.
|
||||||
unsafe { self.drop_contents(self.len()) };
|
unsafe { self.drop_contents() };
|
||||||
|
|
||||||
// Drop the memory
|
// Drop the memory
|
||||||
// SAFETY: Stack is always allocated.
|
// SAFETY: Stack is always allocated.
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,13 @@ impl<T> StackCommon<T> for Stack<T> {
|
||||||
fn set_cursor(&mut self, cursor: NonNull<T>) {
|
fn set_cursor(&mut self, cursor: NonNull<T>) {
|
||||||
self.cursor = cursor;
|
self.cursor = cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
// SAFETY: `self.start` and `self.cursor` are both derived from same pointer.
|
||||||
|
// `self.cursor` is always >= `self.start`.
|
||||||
|
// Distance between pointers is always a multiple of `size_of::<T>()`.
|
||||||
|
unsafe { self.cursor_offset() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Stack<T> {
|
impl<T> Stack<T> {
|
||||||
|
|
@ -303,10 +310,7 @@ impl<T> Stack<T> {
|
||||||
/// Get number of entries on stack.
|
/// Get number of entries on stack.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
// SAFETY: `self.start` and `self.cursor` are both derived from same pointer.
|
<Self as StackCommon<T>>::len(self)
|
||||||
// `self.cursor` is always >= `self.start`.
|
|
||||||
// Distance between pointers is always a multiple of `size_of::<T>()`.
|
|
||||||
unsafe { self.cursor_offset() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get if stack is empty.
|
/// Get if stack is empty.
|
||||||
|
|
@ -332,7 +336,7 @@ impl<T> Drop for Stack<T> {
|
||||||
if !self.is_empty() {
|
if !self.is_empty() {
|
||||||
// SAFETY: Checked above that stack is allocated.
|
// SAFETY: Checked above that stack is allocated.
|
||||||
// Stack contains `self.len()` initialized entries, starting at `self.start`
|
// Stack contains `self.len()` initialized entries, starting at `self.start`
|
||||||
unsafe { self.drop_contents(self.len()) };
|
unsafe { self.drop_contents() };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop the memory
|
// Drop the memory
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue