/// Allocate a runtime length uninitialised byte buffer on the stack, call `callback` with this buffer, and then deallocate the buffer.
@ -305,5 +305,79 @@ T: Default
stackalloc_with(size,T::default,callback)
}
/// Collect an iterator into a stack allocated buffer up to `size` elements, call `callback` with this buffer, and then drop and deallocate the buffer.
///
/// See `stackalloc()`.
///
/// # Size
/// We will only take up to `size` elements from the iterator, the rest of the iterator is dropped.
/// If the iterator yield less elements than `size`, then the slice passed to callback will be smaller than `size` and only contain the elements actually yielded.
#[inline]pubfnstackalloc_with_iter<I,T,U,F>(size: usize,iter: I,callback: F)-> U
whereF: FnOnce(&mut[T])-> U,
I: IntoIterator<Item=T>,
{
stackalloc_uninit(size,move|buf|{
letmutdone=0;
for(d,s)inbuf.iter_mut().zip(iter.into_iter())
{
*d=MaybeUninit::new(s);
done+=1;
}
// SAFETY: We just initialised `done` elements of `buf` above.
letbuf=unsafe{
slice_assume_init_mut(&mutbuf[..done])
};
letret=callback(buf);
ifmem::needs_drop::<T>()
{
// SAFETY: We have initialised the `buf` above
unsafe{
ptr::drop_in_place(bufas*mut_);
}
}
ret
})
}
/// Collect an exact size iterator into a stack allocated slice, call `callback` with this buffer, and then drop and deallocate the buffer.
///
/// See `stackalloc_with_iter()`.
///
/// # Size
/// If the implementation of `ExactSizeIterator` on `I` is incorrect and reports a longer length than the iterator actually produces, then the slice passed to `callback` is shortened to the number of elements actually produced.
#[inline]pubfnstackalloc_from_iter_exact<I,T,U,F>(iter: I,callback: F)-> U
whereF: FnOnce(&mut[T])-> U,
I: IntoIterator<Item=T>,
I::IntoIter: ExactSizeIterator,
{
letiter=iter.into_iter();
stackalloc_with_iter(iter.len(),iter,callback)
}
/// Collect an iterator into a stack allocated buffer, call `callback` with this buffer, and then drop and deallocate the buffer.
///
/// # Safety
/// While the slice passed to `callback` is guaranteed to be safe to use, regardless of if the iterator fills (or tries to overfill) it, this function is still marked as `unsafe` because it trusts the iterator `I` reports an accurate length with its `size_hint()`.
/// It is recommended to instead use `stackalloc_with_iter()` specifying a strict upper bound on the buffer's size, or `stackalloc_from_iter_exact()` for `ExactSizeIterator`s, as this function may allocate far more, or far less (even 0) memory needed to hold all the iterator's elements; therefore this function will very easily not work properly and/or cause stack overflow if used carelessly.
///
/// If the standard library's `std::iter::TrustedLen` trait becomes stablised, this function will be changed to require that as a bound on `I` and this function will no longer be `unsafe`.
///
/// # Size
/// The size allocated for the buffer will be the upper bound of the iterator's `size_hint()` if one exists. If not, then the size allocated will be the lower bound of `size_hint()`.
/// This can potentially result in only some of the iterator being present in the buffer, or the buffer allocated being much larger than the iterator itself.
/// If this iterator does not have a good `size_hint()` for this purpose, use `stackalloc_with_iter()`, or `stackalloc_from_iter_exact()` if the iterator has an exact size.
#[inline]pubunsafefnstackalloc_from_iter_trusted<I,T,U,F>(iter: I,callback: F)-> U