use {
crate::SmallVec,
core::{
mem::take,
ptr::{
self,
drop_in_place
},
slice
},
rayon::{
iter::plumbing::{
Producer,
UnindexedConsumer,
bridge_producer_consumer
},
prelude::ParallelIterator
}
};
struct SliceDrain<'a, T>(slice::IterMut<'a, T>);
impl<T> Iterator for SliceDrain<'_, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.0.next().map(|val| unsafe { ptr::read(val) })
}
}
impl<T> DoubleEndedIterator for SliceDrain<'_, T> {
fn next_back(&mut self) -> Option<T> {
self.0.next_back().map(|val| unsafe { ptr::read(val) })
}
}
impl<T> ExactSizeIterator for SliceDrain<'_, T> {
fn len(&self) -> usize {
self.0.len()
}
}
impl<T> Drop for SliceDrain<'_, T> {
fn drop(&mut self) {
unsafe { drop_in_place(take(&mut self.0).into_slice()) };
}
}
struct DrainProducer<'a, T>(&'a mut [T]);
impl<'a, T: Send> Producer for DrainProducer<'a, T> {
type IntoIter = SliceDrain<'a, T>;
type Item = T;
fn into_iter(mut self) -> SliceDrain<'a, T> {
SliceDrain(take(&mut self.0).iter_mut())
}
fn split_at(mut self, index: usize) -> (Self, Self) {
let (left, right) = take(&mut self.0).split_at_mut(index);
(DrainProducer(left), DrainProducer(right))
}
}
impl<T> Drop for DrainProducer<'_, T> {
fn drop(&mut self) {
unsafe { drop_in_place(self.0) };
}
}
impl<T: Send, const N: usize> ParallelIterator for SmallVec<T, N> {
type Item = T;
fn drive_unindexed<C: UnindexedConsumer<T>>(mut self, consumer: C) -> C::Result {
let len = self.len();
bridge_producer_consumer(
len,
DrainProducer(unsafe {
self.set_len(0);
slice::from_raw_parts_mut(self.as_mut_ptr(), len)
}),
consumer
)
}
}