pub use self::iter::{RawIter, RawIterMut};
pub(crate) mod iter;
use crate::alloc::{Allocator, Global};
use crate::borrow::TryToOwned;
use crate::clone::TryClone;
use crate::error::Error;
use crate::{Box, Vec};
cfg_if! {
if #[cfg(rune_nightly)] {
pub(crate) use core::slice::range;
} else {
use core::ops;
#[must_use]
pub(crate) fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
where
R: ops::RangeBounds<usize>,
{
let len = bounds.end;
let start: ops::Bound<&usize> = range.start_bound();
let start = match start {
ops::Bound::Included(&start) => start,
ops::Bound::Excluded(start) => start
.checked_add(1)
.unwrap_or_else(|| slice_start_index_overflow_fail()),
ops::Bound::Unbounded => 0,
};
let end: ops::Bound<&usize> = range.end_bound();
let end = match end {
ops::Bound::Included(end) => end
.checked_add(1)
.unwrap_or_else(|| slice_end_index_overflow_fail()),
ops::Bound::Excluded(&end) => end,
ops::Bound::Unbounded => len,
};
if start > end {
slice_index_order_fail(start, end);
}
if end > len {
slice_end_index_len_fail(end, len);
}
ops::Range { start, end }
}
const fn slice_start_index_overflow_fail() -> ! {
panic!("attempted to index slice from after maximum usize");
}
const fn slice_end_index_overflow_fail() -> ! {
panic!("attempted to index slice up to maximum usize");
}
fn slice_index_order_fail(index: usize, end: usize) -> ! {
panic!("slice index starts at {index} but ends at {end}");
}
fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
panic!("range end index {index} out of range for slice of length {len}");
}
}
}
#[inline]
#[doc(hidden)]
pub fn into_vec<T, A: Allocator>(this: Box<[T], A>) -> Vec<T, A> {
hack::into_vec(this)
}
#[inline]
pub(crate) fn to_vec<T, A: Allocator>(s: &[T], alloc: A) -> Result<Vec<T, A>, Error>
where
T: TryClone,
{
hack::to_vec(s, alloc)
}
impl<T> TryToOwned for [T]
where
T: TryClone,
{
type Owned = Vec<T, Global>;
#[inline]
fn try_to_owned(&self) -> Result<Self::Owned, Error> {
hack::to_vec(self, Global)
}
}
pub(crate) mod hack {
use crate::alloc::Allocator;
use crate::clone::TryClone;
use crate::error::Error;
use crate::{Box, Vec};
pub(crate) fn into_vec<T, A: Allocator>(b: Box<[T], A>) -> Vec<T, A> {
unsafe {
let len = b.len();
let (b, alloc) = Box::into_raw_with_allocator(b);
Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
}
}
#[inline]
pub(crate) fn to_vec<T: ConvertVec, A: Allocator>(
s: &[T],
alloc: A,
) -> Result<Vec<T, A>, Error> {
T::to_vec(s, alloc)
}
pub(crate) trait ConvertVec {
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Result<Vec<Self, A>, Error>
where
Self: Sized;
}
impl<T> ConvertVec for T
where
T: TryClone,
{
default_fn! {
#[inline]
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Result<Vec<Self, A>, Error> {
struct DropGuard<'a, T, A: Allocator> {
vec: &'a mut Vec<T, A>,
num_init: usize,
}
impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
#[inline]
fn drop(&mut self) {
unsafe {
self.vec.set_len(self.num_init);
}
}
}
let mut vec = Vec::try_with_capacity_in(s.len(), alloc)?;
let mut guard = DropGuard {
vec: &mut vec,
num_init: 0,
};
let slots = guard.vec.spare_capacity_mut();
for (i, b) in s.iter().enumerate().take(slots.len()) {
guard.num_init = i;
slots[i].write(b.try_clone()?);
}
core::mem::forget(guard);
unsafe {
vec.set_len(s.len());
}
Ok(vec)
}
}
}
#[cfg(rune_nightly)]
impl<T: crate::clone::TryCopy> ConvertVec for T {
#[inline]
fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Result<Vec<Self, A>, Error> {
let mut v = Vec::try_with_capacity_in(s.len(), alloc)?;
unsafe {
s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
v.set_len(s.len());
}
Ok(v)
}
}
}