dabus 0.5.0

Dynamic Aplication Controll Bus - an asynchronous, event based module system for thoes who want to move fast and *not* break things
Documentation
use std::{any::TypeId, fmt::Debug};

use crate::util::GeneralRequirements;

/// value must be Debug, just to make things easy
pub struct DynVar {
    val: Box<dyn GeneralRequirements + Sync + Send + 'static>,
}

impl DynVar {
    #[must_use]
    pub fn new<T: GeneralRequirements + Sync + Send + 'static>(x: T) -> Self {
        Self { val: Box::new(x) }
    }

    #[must_use]
    pub fn to_raw(self) -> Box<dyn GeneralRequirements> {
        self.val
    }

    #[must_use]
    pub fn from_raw(val: Box<dyn GeneralRequirements + Sync + Send + 'static>) -> Self {
        Self { val }
    }

    #[must_use]
    pub fn type_name(&self) -> &'static str {
        (*self.val).type_name()
    }

    #[must_use]
    pub fn as_ref<T: GeneralRequirements>(&self) -> Option<&T> {
        (*self.val).as_any().downcast_ref()
    }

    #[must_use]
    pub fn as_mut<T: GeneralRequirements>(&mut self) -> Option<&mut T> {
        (*self.val).mut_any().downcast_mut()
    }

    pub fn try_to<T: GeneralRequirements>(self) -> Result<T, Self> {
        if (*self.val).as_any().type_id() == TypeId::of::<T>() {
            Ok(unsafe { *self.val.to_any().downcast().unwrap_unchecked() })
        } else {
            Err(self)
        }
    }

    /// # Safety
    ///
    /// the caller must make sure that the contained value has type T. calling with the incorrect type is *undefined behavior*
    #[must_use]
    pub unsafe fn as_ref_unchecked<T: GeneralRequirements>(&self) -> &T {
        (*self.val).as_any().downcast_ref_unchecked()
    }

    /// # Safety
    ///
    /// the caller must make sure that the contained value has type T. calling with the incorrect type is *undefined behavior*
    #[must_use]
    pub unsafe fn as_mut_unchecked<T: GeneralRequirements>(&mut self) -> &mut T {
        (*self.val).mut_any().downcast_mut_unchecked()
    }

    /// # Safety
    ///
    /// the caller must make sure that the contained value has type T. calling with the incorrect type is *undefined behavior*
    #[must_use]
    pub unsafe fn try_to_unchecked<T: GeneralRequirements>(self) -> T {
        *self.val.to_any().downcast_unchecked()
    }

    #[must_use]
    pub fn is<T: GeneralRequirements>(&self) -> bool {
        (*self.val).as_any().type_id() == TypeId::of::<T>()
    }

    #[must_use]
    pub fn clone_as<T: GeneralRequirements + Clone + Sync + Send + 'static>(&self) -> Option<Self> {
        Some(Self {
            val: Box::new(self.as_ref::<T>()?.clone()),
        })
    }

    /// # Safety
    ///
    /// the caller must make sure that the contained value has type T. calling with the incorrect type is *undefined behavior*
    #[must_use]
    pub unsafe fn clone_as_unchecked<T: GeneralRequirements + Clone + Sync + Send + 'static>(
        &self,
    ) -> Self {
        Self {
            val: Box::new(self.as_ref_unchecked::<T>().clone()),
        }
    }
}

impl Debug for DynVar {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("DynVar")
            .field("val", self.val.as_dbg())
            .finish()
    }
}