hooks 2.0.0-alpha

Compile-time, async hooks
Documentation
use super::{EffectCleanup, EffectFor, EffectForNoneDependency};

pub struct Cleanup<C: EffectCleanup>(pub Option<C>);

impl<C: EffectCleanup> Drop for Cleanup<C> {
    fn drop(&mut self) {
        if let Some(cleanup) = self.0.take() {
            cleanup.cleanup()
        }
    }
}

pub struct EffectInner<E, C: EffectCleanup> {
    pub cleanup: Cleanup<C>,
    pub effect: Option<E>,
}

impl<E, C: EffectCleanup> std::fmt::Debug for EffectInner<E, C> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        const PLACEHOLDER: Option<&str> = Some("..");
        f.debug_struct("EffectInner")
            .field("cleanup", &self.cleanup.0.as_ref().and(PLACEHOLDER))
            .field("effect", &self.effect.as_ref().and(PLACEHOLDER))
            .finish()
    }
}

impl<E, C: EffectCleanup> EffectInner<E, C> {
    #[inline]
    pub fn new_registered(effect: E) -> Self {
        Self {
            cleanup: Cleanup(None),
            effect: Some(effect),
        }
    }
    pub fn unmount(&mut self) {
        drop(std::mem::take(self).cleanup)
    }
}

impl<E, C: EffectCleanup> Default for EffectInner<E, C> {
    #[inline]
    fn default() -> Self {
        Self {
            cleanup: Cleanup(None),
            effect: None,
        }
    }
}

impl<E, C: EffectCleanup> EffectInner<E, C> {
    pub fn cleanup_and_effect_with(&mut self, run_effect: impl FnOnce(E) -> C) {
        let this = std::mem::take(self);
        drop(this.cleanup);
        if let Some(effect) = this.effect {
            *self = Self {
                cleanup: Cleanup(Some(run_effect(effect))),
                effect: None,
            };
        }
    }
}

impl<E, C: EffectCleanup> EffectInner<E, C> {
    #[inline]
    pub fn register_effect(&mut self, new_effect: E) {
        self.effect = Some(new_effect);
    }
}

impl<E: EffectForNoneDependency> EffectInner<E, E::Cleanup> {
    #[inline]
    pub fn cleanup_and_effect(&mut self) {
        self.cleanup_and_effect_with(EffectForNoneDependency::effect_for_none_dep)
    }
}

impl<E, C: EffectCleanup> EffectInner<E, C> {
    #[inline]
    pub fn cleanup_and_effect_for<Dep>(&mut self, dep: &Dep)
    where
        E: EffectFor<Dep, Cleanup = C>,
    {
        self.cleanup_and_effect_with(|effect| effect.effect_for(dep))
    }
}