asteroid-mq 0.1.0-alpha.3

An embeddable message queue system
Documentation
use std::{borrow::Cow, future::Future, sync::Arc};

use crate::prelude::NodeId;

use super::EdgeRequestEnum;
#[derive(Clone)]
pub struct EdgeAuthService {
    inner: Arc<dyn sealed::BoxedEdgeAuth>,
    source: Cow<'static, str>,
}

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

impl std::fmt::Display for EdgeAuthService {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "EdgeAuthService: {}", self.source)
    }
}

#[derive(Debug)]
pub struct EdgeAuthError {
    reason: Cow<'static, str>,
    source: Option<Box<dyn std::error::Error + Send + Sync>>,
}

impl EdgeAuthError {
    pub fn new<E: std::error::Error + Send + Sync + 'static>(
        reason: impl Into<Cow<'static, str>>,
        source: E,
    ) -> Self {
        Self {
            reason: reason.into(),
            source: Some(Box::new(source)),
        }
    }
    pub fn new_local(reason: impl Into<Cow<'static, str>>) -> Self {
        Self {
            reason: reason.into(),
            source: None,
        }
    }
}
impl std::fmt::Display for EdgeAuthError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "EdgeAuthError: {}", self.reason,)?;
        if let Some(source) = &self.source {
            write!(f, "with source: {}", source)?;
        }
        Ok(())
    }
}

impl EdgeAuthService {
    pub fn new<T>(inner: T) -> Self
    where
        T: EdgeAuth,
    {
        Self {
            inner: Arc::new(inner),
            source: std::any::type_name::<T>().into(),
        }
    }

    pub async fn check(
        &self,
        from: NodeId,
        request: &EdgeRequestEnum,
    ) -> Result<(), EdgeAuthError> {
        self.inner.check(from, request).await
    }
}

pub trait EdgeAuth: Send + Sync + 'static {
    fn check<'r>(
        &'r self,
        from: NodeId,
        request: &'r EdgeRequestEnum,
    ) -> impl Future<Output = Result<(), EdgeAuthError>> + Send + 'r;
}

mod sealed {
    use futures_util::future::BoxFuture;

    use super::{EdgeAuth, EdgeAuthError};
    use crate::protocol::node::edge::EdgeRequestEnum;
    use crate::protocol::node::NodeId;

    pub(super) trait BoxedEdgeAuth: Send + Sync {
        fn check<'r>(
            &'r self,
            from: NodeId,
            request: &'r EdgeRequestEnum,
        ) -> BoxFuture<'r, Result<(), EdgeAuthError>>;
    }

    impl<T> BoxedEdgeAuth for T
    where
        T: EdgeAuth,
    {
        fn check<'r>(
            &'r self,
            from: NodeId,
            request: &'r EdgeRequestEnum,
        ) -> BoxFuture<'r, Result<(), EdgeAuthError>> {
            Box::pin(async move { self.check(from, request).await })
        }
    }
}