feat(data_structures): add as_slice + as_mut_slice methods to stacks (#6216)

Add `as_slice` and `as_mut_slice` methods to `Stack` and `NonEmptyStack`.
This commit is contained in:
overlookmotel 2024-10-01 12:26:36 +00:00
parent dbfa0bc01f
commit 7566c2d66f
3 changed files with 79 additions and 3 deletions

View file

@ -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<T>: StackCapacity<T> {
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.

View file

@ -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<T> NonEmptyStack<T> {
pub fn capacity(&self) -> usize {
<Self as StackCommon<T>>::capacity(self)
}
/// Get contents of stack as a slice `&[T]`.
#[inline]
pub fn as_slice(&self) -> &[T] {
<Self as StackCommon<T>>::as_slice(self)
}
/// Get contents of stack as a mutable slice `&mut [T]`.
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
<Self as StackCommon<T>>::as_mut_slice(self)
}
}
impl<T> Drop for NonEmptyStack<T> {
@ -316,6 +331,22 @@ impl<T> Drop for NonEmptyStack<T> {
}
}
impl<T> Deref for NonEmptyStack<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> DerefMut for NonEmptyStack<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -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<T> Stack<T> {
pub fn capacity(&self) -> usize {
<Self as StackCommon<T>>::capacity(self)
}
/// Get contents of stack as a slice `&[T]`.
#[inline]
pub fn as_slice(&self) -> &[T] {
<Self as StackCommon<T>>::as_slice(self)
}
/// Get contents of stack as a mutable slice `&mut [T]`.
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
<Self as StackCommon<T>>::as_mut_slice(self)
}
}
impl<T> Drop for Stack<T> {
@ -345,6 +360,22 @@ impl<T> Drop for Stack<T> {
}
}
impl<T> Deref for Stack<T> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> DerefMut for Stack<T> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
#[cfg(test)]
mod tests {
use super::*;