cyfs-util 0.6.8

Rust cyfs-util package
Documentation
use cyfs_base::BuckyResult;
use async_std::prelude::*;
use async_trait::async_trait;

use std::sync::{Arc, Mutex};

#[async_trait]
pub trait EventListenerAsyncRoutine<P, R>: Send + Sync + 'static
where
    P: Send + Sync + 'static,
    R: 'static,
{
    async fn call(&self, param: &P) -> BuckyResult<R>;
}

#[async_trait]
impl<F, Fut, P, R> EventListenerAsyncRoutine<P, R> for F
where
    P: Send + Sync + 'static,
    R: 'static,
    F: Send + Sync + 'static + Fn(&P) -> Fut,
    Fut: Future<Output = BuckyResult<R>> + Send + 'static,
{
    async fn call(&self, param: &P) -> BuckyResult<R> {
        (self)(param).await
    }
}

#[async_trait]
pub trait EventListenerSyncRoutine<P, R>: Send + Sync + 'static
where
    P: Send + Sync + 'static,
    R: 'static,
{
    fn call(&self, param: &P) -> BuckyResult<R>;
}

#[async_trait]
impl<F, P, R> EventListenerSyncRoutine<P, R> for F
where
    P: Send + Sync + 'static,
    R: 'static,
    F: Send + Sync + 'static + Fn(&P) -> BuckyResult<R>,
{
    fn call(&self, param: &P) -> BuckyResult<R> {
        (self)(param)
    }
}

pub struct SyncEventManager<P, R>
where
    P: Send + Sync + 'static,
    R: 'static,
{
    next_cookie: u32,
    listeners: Vec<(u32, Box<dyn EventListenerSyncRoutine<P, R>>)>,
}

impl<P, R> SyncEventManager<P, R>
where
    P: Send + Sync + 'static,
    R: 'static,
{
    pub fn new() -> Self {
        Self {
            next_cookie: 1,
            listeners: Vec::new(),
        }
    }

    pub fn listener_count(&self) -> usize {
        self.listeners.len()
    }

    pub fn is_empty(&self) -> bool {
        self.listeners.is_empty()
    }

    pub fn on(&mut self, listener: Box<dyn EventListenerSyncRoutine<P, R>>) -> u32 {
        let cookie = self.next_cookie;
        self.next_cookie += 1;
        if self.next_cookie == u32::MAX {
            self.next_cookie = 1;
        }

        self.listeners.push((cookie, listener));

        cookie
    }

    pub fn off(&mut self, cookie: u32) -> bool {
        let ret = self.listeners.iter().enumerate().find(|v| v.1 .0 == cookie);

        match ret {
            Some((index, _)) => {
                self.listeners.remove(index);
                true
            }
            None => false,
        }
    }

    pub fn emit(&self, param: &P) -> BuckyResult<Option<R>> {
        let mut ret = None;
        for item in &self.listeners {
            ret = Some(item.1.call(param)?);
        }

        Ok(ret)
    }
}

#[derive(Clone)]
pub struct SyncEventManagerSync<P, R>(Arc<Mutex<SyncEventManager<P, R>>>)
where
    P: Send + Sync + 'static,
    R: 'static;

impl<P, R> SyncEventManagerSync<P, R>
where
    P: Send + Sync + 'static,
    R: 'static,
{
    pub fn new() -> Self {
        let inner = SyncEventManager::new();
        Self(Arc::new(Mutex::new(inner)))
    }

    pub fn listener_count(&self) -> usize {
        self.0.lock().unwrap().listeners.len()
    }

    pub fn is_empty(&self) -> bool {
        self.0.lock().unwrap().is_empty()
    }

    pub fn on(&self, listener: Box<dyn EventListenerSyncRoutine<P, R>>) -> u32 {
        self.0.lock().unwrap().on(listener)
    }

    pub fn off(&self, cookie: u32) -> bool {
        self.0.lock().unwrap().off(cookie)
    }

    pub fn emit(&self, param: &P) -> BuckyResult<Option<R>> {
        self.0.lock().unwrap().emit(param)
    }
}