use osom_lib_alloc::traits::Allocator;
use osom_lib_arc::carc_array::CWeakArray;
use osom_lib_reprc::macros::reprc;
use osom_lib_try_clone::TryClone;
use super::{MaxReferencesExceededError, SharedString};
#[reprc]
#[repr(u8)]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
#[must_use]
pub enum WeakUpgradeError {
MaxReferencesExceeded = 0,
NoStrongReferencesAlive = 1,
}
impl From<osom_lib_arc::errors::WeakUpgradeError> for WeakUpgradeError {
fn from(err: osom_lib_arc::errors::WeakUpgradeError) -> Self {
match err {
osom_lib_arc::errors::WeakUpgradeError::MaxReferencesExceeded => Self::MaxReferencesExceeded,
osom_lib_arc::errors::WeakUpgradeError::NoStrongReferencesAlive => Self::NoStrongReferencesAlive,
}
}
}
#[reprc]
#[repr(transparent)]
#[derive(Debug)]
#[must_use]
pub struct WeakSharedString<TAllocator: Allocator> {
internal: CWeakArray<u8, TAllocator>,
}
impl<TAllocator: Allocator> WeakSharedString<TAllocator> {
#[inline(always)]
pub(crate) fn from_internal(internal: CWeakArray<u8, TAllocator>) -> Self {
Self { internal }
}
#[inline(always)]
#[must_use]
pub fn strong_count(&self) -> u32 {
CWeakArray::strong_count(&self.internal)
}
#[inline(always)]
#[must_use]
pub fn weak_count(&self) -> u32 {
CWeakArray::weak_count(&self.internal)
}
#[inline]
#[must_use]
pub fn as_str(&self) -> &str {
unsafe {
let slice = self.internal.data();
core::str::from_utf8_unchecked(&slice[..slice.len() - 1])
}
}
#[inline]
#[must_use]
pub fn as_c_str(&self) -> &str {
unsafe {
let slice = self.internal.data();
core::str::from_utf8_unchecked(slice)
}
}
pub fn upgrade(&self) -> Result<SharedString<TAllocator>, WeakUpgradeError> {
let strong = CWeakArray::upgrade(&self.internal)?;
Ok(SharedString::from_internal(strong))
}
#[inline(always)]
#[must_use]
pub fn abandon(self) -> bool {
CWeakArray::<u8, TAllocator>::abandon(self.internal)
}
}
impl<TAllocator: Allocator> TryClone for WeakSharedString<TAllocator> {
type Error = MaxReferencesExceededError;
fn try_clone(&self) -> Result<Self, Self::Error> {
let internal = self.internal.try_clone()?;
Ok(Self { internal })
}
}
impl<TAllocator: Allocator> Clone for WeakSharedString<TAllocator> {
fn clone(&self) -> Self {
self.try_clone()
.expect("WeakSharedString weak reference count is too high.")
}
}