nitinol-projection 0.1.2

A library for Nitinol to project Events to Entity using nitinol-protocol
Documentation
use std::ops::Deref;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use crate::projector::EventProjector;


static mut GLOBAL_PROJECTOR: GlobalEventProjector = GlobalEventProjector(None);

static EXISTS: AtomicBool = AtomicBool::new(false);
static GLOBAL_INIT: AtomicUsize = AtomicUsize::new(UNINITIALIZED);

const UNINITIALIZED: usize = 0;
const INITIALIZING: usize = 1;
const INITIALIZED: usize = 2;

pub fn set_global_projector(install: EventProjector) {
    if GLOBAL_INIT
        .compare_exchange(
            UNINITIALIZED,
            INITIALIZING,
            Ordering::SeqCst,
            Ordering::SeqCst,
        )
        .is_ok()
    {
        unsafe {
            GLOBAL_PROJECTOR = GlobalEventProjector(Some(install));
        }
        GLOBAL_INIT.store(INITIALIZED, Ordering::SeqCst);
        EXISTS.store(true, Ordering::Release);
    } else {
        panic!("`EventProjector` already initialized");
    }
}

#[allow(unused)]
pub fn get_global_projector() -> &'static EventProjector {
    if EXISTS.load(Ordering::Acquire) {
        unsafe {
            &*std::ptr::addr_of!(GLOBAL_PROJECTOR)
        }
    } else {
        panic!("`EventProjector` not initialized");
    }
}


pub(crate) struct GlobalEventProjector(Option<EventProjector>);

impl Deref for GlobalEventProjector {
    type Target = EventProjector;

    fn deref(&self) -> &Self::Target {
        self.0.as_ref().expect("`EventProjector` not initialized")
    }
}