use core::{alloc::Layout, mem, ptr::NonNull};
#[cfg(feature = "std")]
use std::alloc;
#[cfg(not(feature = "std"))]
extern crate alloc as no_std_alloc;
#[cfg(not(feature = "std"))]
use no_std_alloc::alloc;
use try_reserve::error::{TryReserveError, TryReserveErrorKind};
use super::{Cap, Ptr};
pub unsafe trait Shrink<T>: Cap + Ptr<T> {
fn __shrink_manually_unchecked(&mut self, len_to_sub: usize) {
assert!(mem::size_of::<T>() != 0, "Capacity overflow");
assert!(len_to_sub <= self.__cap(), "Capacity underflow");
Self::__try_shrink_manually(self, len_to_sub).unwrap();
}
fn __try_shrink_manually(&mut self, len_to_sub: usize) -> Result<(), TryReserveError> {
if mem::size_of::<T>() == 0 || len_to_sub > self.__cap() {
return Err(TryReserveError::from(TryReserveErrorKind::CapacityOverflow));
}
let new_cap = self.__cap() - len_to_sub;
let new_layout = Layout::array::<T>(new_cap)?;
let new_ptr = if new_layout.size() > 0 {
let old_layout = Layout::array::<T>(self.__cap())?;
let old_ptr = self.__ptr().as_ptr() as *mut u8;
let new_u8_ptr = unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) };
match NonNull::new(new_u8_ptr as *mut T) {
Some(ptr) => ptr,
None => {
return Err(TryReserveError::from(TryReserveErrorKind::AllocError {
layout: new_layout,
non_exhaustive: (),
}))
}
}
} else {
if self.__cap() > 0 {
let old_layout = Layout::array::<T>(self.__cap())?;
unsafe {
alloc::dealloc(self.__ptr().as_ptr() as *mut u8, old_layout);
}
}
NonNull::dangling()
};
self.__ptr_set(new_ptr);
self.__cap_set(new_cap);
Ok(())
}
unsafe fn __shrink(&mut self, old_len: usize, new_len: usize);
}