use osom_lib_alloc::traits::Allocator;
use osom_lib_primitives::length::Length;
use osom_lib_reprc::macros::reprc;
use crate::immutable::{ImmutableString, ImmutableStringError, internal_string::InternalString};
#[reprc]
#[repr(transparent)]
#[must_use]
pub struct ImmutableStringBuilder<TAllocator: Allocator> {
internal: InternalString<TAllocator>,
}
impl<TAllocator: Allocator> ImmutableStringBuilder<TAllocator> {
#[inline(always)]
pub fn new() -> Result<Self, ImmutableStringError> {
Self::with_capacity_and_allocator(Length::ZERO, TAllocator::default())
}
#[inline(always)]
pub fn with_capacity(capacity: Length) -> Result<Self, ImmutableStringError> {
Self::with_capacity_and_allocator(capacity, TAllocator::default())
}
#[inline(always)]
pub fn with_allocator(allocator: TAllocator) -> Result<Self, ImmutableStringError> {
Self::with_capacity_and_allocator(Length::ZERO, allocator)
}
#[inline]
pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, ImmutableStringError> {
let internal = InternalString::with_allocator_and_capacity(capacity + 1, allocator)?;
Ok(Self { internal })
}
#[inline]
pub fn try_push(&mut self, text: &str) -> Result<(), ImmutableStringError> {
self.internal.try_push_slice(text.as_bytes())
}
pub fn shrink_to_fit(&mut self) -> Result<(), ImmutableStringError> {
self.internal.shrink_to_fit()
}
pub fn build(self) -> Result<ImmutableString<TAllocator>, ImmutableStringError> {
let mut internal = unsafe { (&raw const self.internal).read() };
core::mem::forget(self);
internal.try_push_slice(b"\0")?;
internal.shrink_to_fit()?;
let result = ImmutableString::from_internal(internal);
Ok(result)
}
}
impl<TAllocator: Allocator> Drop for ImmutableStringBuilder<TAllocator> {
fn drop(&mut self) {
let internal = unsafe { (&raw mut self.internal).read() };
internal.deallocate();
}
}