use core::ptr::NonNull;
use allocator_api2::alloc::{AllocError, Allocator};
use super::{Arena, ExpectAlloc};
use crate::{Arc, Box};
impl<A: Allocator + Clone> Arena<A> {
#[allow(clippy::mut_from_ref, reason = "Simple references: see Self::try_alloc_with")]
#[must_use]
#[inline]
pub fn alloc_str(&self, s: impl AsRef<str>) -> &mut str {
(self.impl_alloc_str(s.as_ref())).expect_alloc()
}
#[must_use]
#[inline]
pub fn alloc_str_arc(&self, s: impl AsRef<str>) -> Arc<str, A>
where
A: Send + Sync,
{
self.try_alloc_str_arc(s).expect_alloc()
}
#[must_use]
#[inline]
pub fn alloc_str_box(&self, s: impl AsRef<str>) -> Box<str, A> {
self.try_alloc_str_box(s).expect_alloc()
}
#[allow(clippy::mut_from_ref, reason = "Simple references: see Self::try_alloc_with")]
#[inline]
pub fn try_alloc_str(&self, s: impl AsRef<str>) -> Result<&mut str, AllocError> {
self.impl_alloc_str(s.as_ref())
}
#[inline]
pub fn try_alloc_str_arc(&self, s: impl AsRef<str>) -> Result<Arc<str, A>, AllocError>
where
A: Send + Sync,
{
self.impl_alloc_prefixed_shared_arc::<u8>(s.as_ref().as_bytes()).map(|ptr|
unsafe { Arc::from_raw(ptr) })
}
#[inline]
pub fn try_alloc_str_box(&self, s: impl AsRef<str>) -> Result<Box<str, A>, AllocError> {
self.impl_alloc_prefixed_shared::<u8>(s.as_ref().as_bytes()).map(|ptr|
unsafe { Box::from_raw(ptr) })
}
#[allow(clippy::mut_from_ref, reason = "Simple references: see Self::try_alloc_with")]
#[inline(always)]
fn impl_alloc_str(&self, s: &str) -> Result<&mut str, AllocError> {
let len = s.len();
loop {
if let Some(u) = self.try_reserve_local_bytes(len) {
return Ok(u.init_copy_from_str(s));
}
if self.is_oversized(len) {
let ptr = self.alloc_oversized_local_with(len, |mutator| {
let ticket = mutator.try_alloc_bytes(len).expect("dedicated oversized chunk sized to fit string");
let r: &mut str = ticket.init_copy_from_str(s);
NonNull::from(r)
})?;
return Ok(unsafe { &mut *ptr.as_ptr() });
}
self.refill_local(len)?;
}
}
}