hexga_core 0.0.11-beta.56

Basic set of functionalities common to all hexga crate
Documentation
use super::*;

/// Multi threaded read only singleton, where the value is initialized at compile time.
pub type SingletonOnce<T> = SingletonOf<OnceLock<T>>;
/// Multi threaded read only singleton, where the value is initialized from a static fn / lambda at runtime.
pub type SingletonOnceLazy<T> = SingletonOf<LazyLock<T>>;

// Wasm is single threaded right now, so this is ok.
#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
mod single_thread
{
    use super::*;

    unsafe impl<T> Sync for SingletonOnce<T> {}
    unsafe impl<T> Send for SingletonOnce<T> {}

    unsafe impl<T> Sync for SingletonOnceLazy<T> {}
    unsafe impl<T> Send for SingletonOnceLazy<T> {}
}

impl<T> SingletonOnce<T>
{
    pub const fn uninit() -> Self { Self::from_guard(OnceLock::new()) }

    pub const fn new() -> Self { Self::uninit() }
}

impl<T> Debug for SingletonOnce<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult
    {
        match self.try_get()
        {
            Ok(guard) => write!(f, "{:?}", guard),
            Err(e) => write!(f, "SingletonOnce<{}> can't be read: {:?}", std::any::type_name::<T>(), e),
        }
    }
}

impl<T> Guarded<T> for SingletonOnce<T>
{
    type Guard<'a>
        = &'a T
    where
        Self: 'a;

    #[inline]
    #[track_caller]
    fn get<'a>(&'a self) -> Self::Guard<'a>
    {
        match self.guarded.get()
        {
            Some(guard) => guard,
            None =>
            {
                panic!("SingletonOnce<{}> not initialized", std::any::type_name::<T>())
            }
        }
    }
    type Error<'a>
        = ()
    where
        Self: 'a;

    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>> { self.guarded.get().ok_or(()) }
}

impl<T> SingletonOnceable<T> for SingletonOnce<T>
{
    fn init_from_fn<'a, F>(&'a self, init: F) -> Result<Self::Guard<'a>, F>
    where
        F: FnOnce() -> T,
    {
        Ok(self.guarded.get_or_init(init))
    }
}

impl_singleton_methods_get!(SingletonOnce);

impl<T> SingletonOnceLazy<T>
{
    pub const fn new(f: fn() -> T) -> Self { Self::from_guard(LazyLock::new(f)) }

    pub const fn uninit() -> Self { Self::from_guard(LazyLock::new(|| panic!("SingletonOnceLazy<{}> not initialized", std::any::type_name::<T>()))) }
}

impl<T> Debug for SingletonOnceLazy<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult
    {
        match self.try_get()
        {
            Ok(guard) => write!(f, "{:?}", guard),
            Err(e) => write!(f, "SingletonOnceLazy<{}> can't be read: {:?}", std::any::type_name::<T>(), e),
        }
    }
}

impl<T> Guarded<T> for SingletonOnceLazy<T>
{
    type Guard<'a>
        = &'a T
    where
        Self: 'a;

    #[track_caller]
    fn get<'a>(&'a self) -> Self::Guard<'a> { &self.guarded }

    type Error<'a>
        = std::convert::Infallible
    where
        Self: 'a;

    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>> { Ok(&self.guarded) }
}
impl_singleton_methods_get!(SingletonOnceLazy);