use std::mem::MaybeUninit;
use num_traits::Zero;
pub trait IntoRawParts<T> {
fn into_raw_parts(self) -> (*mut T, usize, usize);
fn raw_parts(&self) -> (*mut T, usize, usize);
}
impl<T> IntoRawParts<T> for Vec<T> {
fn into_raw_parts(self) -> (*mut T, usize, usize) {
let mut me = std::mem::ManuallyDrop::new(self);
(me.as_mut_ptr(), me.len(), me.capacity())
}
fn raw_parts(&self) -> (*mut T, usize, usize) {
(self.as_ptr() as *mut T, self.len(), self.capacity())
}
}
pub trait ResizeFaster<T: Copy> {
fn fill_or_alloc(&mut self, new_len: usize, value: T);
}
impl<T: Copy + Zero + PartialEq> ResizeFaster<T> for Vec<T> {
fn fill_or_alloc(&mut self, new_len: usize, value: T) {
if self.capacity() == 0 {
*self = vec![value; new_len]
} else {
self.clear();
self.reserve(new_len);
let spare = &mut self.spare_capacity_mut()[..new_len];
let init_value = MaybeUninit::new(value);
spare.fill(init_value);
unsafe { self.set_len(new_len) }
}
}
}
pub trait PushUnchecked<T> {
unsafe fn push_unchecked(&mut self, value: T);
}
impl<T> PushUnchecked<T> for Vec<T> {
#[inline]
unsafe fn push_unchecked(&mut self, value: T) {
debug_assert!(self.capacity() > self.len());
let end = self.as_mut_ptr().add(self.len());
std::ptr::write(end, value);
self.set_len(self.len() + 1);
}
}
pub trait CapacityByFactor {
fn with_capacity_by_factor(original_len: usize, factor: f64) -> Self;
}
impl<T> CapacityByFactor for Vec<T> {
fn with_capacity_by_factor(original_len: usize, factor: f64) -> Self {
let cap = (original_len as f64 * factor) as usize;
Vec::with_capacity(cap)
}
}
pub trait ConvertVec<Out> {
type ItemIn;
fn convert_owned<F: FnMut(Self::ItemIn) -> Out>(self, f: F) -> Vec<Out>;
fn convert<F: FnMut(&Self::ItemIn) -> Out>(&self, f: F) -> Vec<Out>;
}
impl<T, Out> ConvertVec<Out> for Vec<T> {
type ItemIn = T;
fn convert_owned<F: FnMut(Self::ItemIn) -> Out>(self, f: F) -> Vec<Out> {
self.into_iter().map(f).collect()
}
fn convert<F: FnMut(&Self::ItemIn) -> Out>(&self, f: F) -> Vec<Out> {
self.iter().map(f).collect()
}
}
pub fn inplace_zip_filtermap<T, U>(
x: &mut Vec<T>,
y: &mut Vec<U>,
mut f: impl FnMut(T, U) -> Option<(T, U)>,
) {
assert_eq!(x.len(), y.len());
let length = x.len();
struct OwnedBuffer<T> {
end: *mut T,
length: usize,
}
impl<T> Drop for OwnedBuffer<T> {
fn drop(&mut self) {
for i in 0..self.length {
unsafe { self.end.wrapping_sub(i + 1).read() };
}
}
}
let x_ptr = x.as_mut_ptr();
let y_ptr = y.as_mut_ptr();
let mut x_buf = OwnedBuffer {
end: x_ptr.wrapping_add(length),
length,
};
let mut y_buf = OwnedBuffer {
end: y_ptr.wrapping_add(length),
length,
};
unsafe {
x.set_len(0);
y.set_len(0);
}
for i in 0..length {
let xi = unsafe { x_ptr.wrapping_add(i).read() };
let yi = unsafe { y_ptr.wrapping_add(i).read() };
x_buf.length -= 1;
y_buf.length -= 1;
let result = f(xi, yi);
if let Some((xi, yi)) = result {
x.push(xi);
y.push(yi);
}
}
debug_assert_eq!(x_buf.length, 0);
debug_assert_eq!(y_buf.length, 0);
std::mem::forget(x_buf);
std::mem::forget(y_buf);
}