mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(allocator): add Vec::into_boxed_slice (#6195)
Note that this PR does not implement the inverse operation (`Box::to_vec` for `[T]`).
This commit is contained in:
parent
7240ee23fc
commit
5ee1ef3d92
2 changed files with 70 additions and 2 deletions
|
|
@ -76,6 +76,25 @@ impl<'alloc, T> Box<'alloc, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'alloc, T: ?Sized> Box<'alloc, T> {
|
||||
/// Create a [`Box`] from a raw pointer to a value.
|
||||
///
|
||||
/// The [`Box`] takes ownership of the data pointed to by `ptr`.
|
||||
///
|
||||
/// # SAFETY
|
||||
/// Data pointed to by `ptr` must live as long as `'alloc`.
|
||||
/// This requirement is met if the pointer was obtained from other data in the arena.
|
||||
///
|
||||
/// Data pointed to by `ptr` must *only* be used for this `Box`. i.e. it must be unique,
|
||||
/// with no other aliases. You must not, for example, create 2 `Box`es from the same pointer.
|
||||
///
|
||||
/// `ptr` must have been created from a `*mut T` or `&mut T` (not a `*const T` / `&T`).
|
||||
#[inline]
|
||||
pub(crate) const unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
|
||||
Self(ptr, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'alloc, T: ?Sized> ops::Deref for Box<'alloc, T> {
|
||||
type Target = T;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
fmt::Debug,
|
||||
hash::{Hash, Hasher},
|
||||
ops,
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use allocator_api2::vec;
|
||||
|
|
@ -14,7 +15,7 @@ use bumpalo::Bump;
|
|||
#[cfg(any(feature = "serialize", test))]
|
||||
use serde::{ser::SerializeSeq, Serialize, Serializer};
|
||||
|
||||
use crate::Allocator;
|
||||
use crate::{Allocator, Box};
|
||||
|
||||
/// Bumpalo Vec
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
|
@ -101,6 +102,39 @@ impl<'alloc, T> Vec<'alloc, T> {
|
|||
vec.extend(iter);
|
||||
Self(vec)
|
||||
}
|
||||
|
||||
/// Converts the vector into [`Box<[T]>`][owned slice].
|
||||
///
|
||||
/// Any excess capacity the vector has will not be included in the slice.
|
||||
/// The excess memory will be leaked in the arena (i.e. not reused by another allocation).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use oxc_allocator::{Allocator, Vec};
|
||||
///
|
||||
/// let allocator = Allocator::default();
|
||||
/// let mut v = Vec::with_capacity_in(10, &allocator);
|
||||
/// v.extend([1, 2, 3]);
|
||||
/// let b = v.into_boxed_slice();
|
||||
///
|
||||
/// assert_eq!(&*b, &[1, 2, 3]);
|
||||
/// assert_eq!(b.len(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// [owned slice]: Box
|
||||
pub fn into_boxed_slice(self) -> Box<'alloc, [T]> {
|
||||
let slice = self.0.leak();
|
||||
let ptr = NonNull::from(slice);
|
||||
// SAFETY: `ptr` points to a valid slice `[T]`.
|
||||
// `allocator_api2::vec::Vec::leak` consumes the inner `Vec` without dropping it.
|
||||
// Lifetime of returned `Box<'alloc, [T]>` is same as lifetime of consumed `Vec<'alloc, T>`,
|
||||
// so data in the `Box` must be valid for its lifetime.
|
||||
// `Vec` uniquely owned the data, and we have consumed the `Vec`, so the new `Box` has
|
||||
// unique ownership of the data (no aliasing).
|
||||
// `ptr` was created from a `&mut [T]`.
|
||||
unsafe { Box::from_non_null(ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'alloc, T> ops::Deref for Vec<'alloc, T> {
|
||||
|
|
@ -178,7 +212,7 @@ impl<'alloc, T: Hash> Hash for Vec<'alloc, T> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Vec;
|
||||
use crate::Allocator;
|
||||
use crate::{Allocator, Box};
|
||||
|
||||
#[test]
|
||||
fn vec_with_capacity() {
|
||||
|
|
@ -211,4 +245,19 @@ mod test {
|
|||
program
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_to_boxed_slice() {
|
||||
let allocator = Allocator::default();
|
||||
let mut v = Vec::with_capacity_in(10, &allocator);
|
||||
v.extend([1, 2, 3]);
|
||||
|
||||
let b = v.into_boxed_slice();
|
||||
// Check return value is an `oxc_allocator::Box`, not an `allocator_api2::boxed::Box`
|
||||
let b: Box<[u8]> = b;
|
||||
|
||||
assert_eq!(&*b, &[1, 2, 3]);
|
||||
// Check length of slice is equal to what `v.len()` was, not `v.capacity()`
|
||||
assert_eq!(b.len(), 3);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue