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 Grow<T>: Cap + Ptr<T> {
fn __grow_manually_unchecked(&mut self, len_to_add: usize) {
assert!(mem::size_of::<T>() != 0, "Capacity overflow");
Self::__try_grow_manually(self, len_to_add).unwrap();
}
fn __try_grow_manually(&mut self, len_to_add: usize) -> Result<(), TryReserveError> {
if mem::size_of::<T>() == 0 {
return Err(TryReserveError::from(TryReserveErrorKind::CapacityOverflow));
}
if len_to_add == 0 {
return Ok(());
}
let (new_cap, new_layout) = if self.__cap() == 0 {
(len_to_add, Layout::array::<T>(len_to_add)?)
} else {
let new_cap = self.__cap() + len_to_add;
let new_layout = Layout::array::<T>(new_cap)?;
(new_cap, new_layout)
};
if new_layout.size() > isize::MAX as usize {
return Err(TryReserveError::from(TryReserveErrorKind::AllocError {
layout: new_layout,
non_exhaustive: (),
}));
}
let new_ptr = if self.__cap() == 0 {
unsafe { alloc::alloc(new_layout) }
} else {
unsafe {
let old_ptr = self.__ptr().as_ptr() as *mut u8;
let old_layout = Layout::array::<T>(self.__cap())?;
alloc::realloc(old_ptr, old_layout, new_layout.size())
}
};
self.__ptr_set(match NonNull::new(new_ptr as *mut T) {
Some(ptr) => ptr,
None => {
return Err(TryReserveError::from(TryReserveErrorKind::AllocError {
layout: new_layout,
non_exhaustive: (),
}))
}
});
self.__cap_set(new_cap);
Ok(())
}
unsafe fn __grow(&mut self, old_len: usize, new_len: usize);
}