podo-core-driver 0.4.4

Podo Driver FFI
Documentation
use std::marker::PhantomData;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

use super::message::*;
use crate::error::RuntimeError;

pub enum State<S>
where
    S: From<usize> + Into<usize>,
{
    NotInitialized,
    Initializing,
    Ready,
    Running(S),
    Stopped,
}

const NOT_INITIALIZED: usize = usize::max_value();
const INITIALIZING: usize = usize::max_value() - 1;
const READY: usize = usize::max_value() - 2;
const STOPPED: usize = usize::max_value() - 3;

impl<S> From<State<S>> for usize
where
    S: From<usize> + Into<usize>,
{
    fn from(state: State<S>) -> Self {
        match state {
            State::NotInitialized => NOT_INITIALIZED,
            State::Initializing => INITIALIZING,
            State::Ready => READY,
            State::Stopped => STOPPED,
            State::Running(s) => s.into(),
        }
    }
}

impl<S> From<usize> for State<S>
where
    S: From<usize> + Into<usize>,
{
    fn from(state: usize) -> Self {
        match state {
            NOT_INITIALIZED => State::NotInitialized,
            INITIALIZING => State::Initializing,
            READY => State::Ready,
            STOPPED => State::Stopped,
            _ => State::Running(state.into()),
        }
    }
}

impl<S> Default for State<S>
where
    S: From<usize> + Into<usize>,
{
    fn default() -> Self {
        Self::NotInitialized
    }
}

#[derive(Clone, Default)]
pub struct StateFlag<S>
where
    S: From<usize> + Into<usize>,
{
    flag: Arc<AtomicUsize>,
    ty: PhantomData<S>,
}

impl<S> StateFlag<S>
where
    S: From<usize> + Into<usize>,
{
    #[inline]
    pub fn new_ready() -> Self {
        Self {
            flag: Arc::new(AtomicUsize::new(State::<S>::Ready.into())),
            ty: PhantomData::default(),
        }
    }

    #[inline]
    pub fn new_running(state: S) -> Self {
        Self {
            flag: Arc::new(AtomicUsize::new(State::Running(state).into())),
            ty: PhantomData::default(),
        }
    }

    #[inline]
    pub fn start_initialize(&self) -> Result<(), RuntimeError> {
        match self
            .flag
            .swap(State::<S>::Initializing.into(), Ordering::Relaxed)
        {
            NOT_INITIALIZED => Ok(()),
            _ => RuntimeError::expect(ERR_INIT),
        }
    }

    #[inline]
    pub fn stop_initialize(&self) -> Result<(), RuntimeError> {
        match self.flag.swap(State::<S>::Ready.into(), Ordering::Relaxed) {
            INITIALIZING => Ok(()),
            _ => RuntimeError::expect(ERR_INIT),
        }
    }

    #[inline]
    pub fn skip_initialize(&self) -> Result<(), RuntimeError> {
        match self.flag.swap(State::<S>::Ready.into(), Ordering::Relaxed) {
            NOT_INITIALIZED | INITIALIZING => Ok(()),
            _ => RuntimeError::expect(ERR_INIT),
        }
    }

    #[inline]
    pub fn start(&self, state: S) -> Result<(), RuntimeError> {
        match self.flag.swap(state.into(), Ordering::Relaxed) {
            NOT_INITIALIZED | INITIALIZING => RuntimeError::expect(ERR_NOT_INIT),
            READY | STOPPED => Ok(()),
            _ => RuntimeError::expect(ERR_STARTED),
        }
    }

    #[inline]
    pub fn status(&self) -> Result<S, RuntimeError> {
        match self.flag.load(Ordering::Relaxed) {
            NOT_INITIALIZED | INITIALIZING => RuntimeError::expect(ERR_NOT_INIT),
            READY => RuntimeError::expect(ERR_NOT_STARTED),
            STOPPED => RuntimeError::expect(ERR_STOPPED),
            _state => Ok(_state.into()),
        }
    }

    #[inline]
    pub fn stop(&self) -> Result<(), RuntimeError> {
        match self
            .flag
            .swap(State::<S>::Stopped.into(), Ordering::Relaxed)
        {
            NOT_INITIALIZED | INITIALIZING => RuntimeError::expect(ERR_NOT_INIT),
            READY => RuntimeError::expect(ERR_NOT_STARTED),
            STOPPED => RuntimeError::expect(ERR_STOPPED),
            _ => Ok(()),
        }
    }

    #[inline]
    pub fn is_initialized(&self) -> bool {
        match self.flag.load(Ordering::Relaxed) {
            NOT_INITIALIZED => false,
            _ => true,
        }
    }

    #[inline]
    pub fn is_running(&self) -> bool {
        match self.flag.load(Ordering::Relaxed) {
            NOT_INITIALIZED | INITIALIZING | READY | STOPPED => false,
            _ => true,
        }
    }

    #[inline]
    pub fn assert_running(&self) -> Result<(), RuntimeError> {
        match self.is_running() {
            true => Ok(()),
            false => RuntimeError::expect(ERR_NOT_STARTED),
        }
    }

    #[inline]
    pub fn assert_stopped(&self) -> Result<(), RuntimeError> {
        match self.is_running() {
            false => Ok(()),
            true => RuntimeError::expect(ERR_STARTED),
        }
    }
}

pub struct NoExtraState;

impl From<usize> for NoExtraState {
    #[inline]
    fn from(_: usize) -> Self {
        NoExtraState
    }
}

impl Into<usize> for NoExtraState {
    #[inline]
    fn into(self) -> usize {
        0
    }
}