polariton_server 0.6.0

Server functionality for the Photon packet system
Documentation
use polariton::operation::{OperationResponse, ParameterTable};
use super::{Operation, OperationCode};

pub struct SimpleOpError {
    code: i16,
    message: Option<String>,
}

impl SimpleOpError {
    pub fn with_code(code: i16) -> Self {
        SimpleOpError { code, message: None }
    }

    pub fn with_message(code: i16, message: String) -> Self {
        SimpleOpError { code, message: Some(message) }
    }

    pub fn error_code(&self) -> i16 {
        self.code
    }

    pub fn error_msg(&self) -> Option<&'_ String> {
        self.message.as_ref()
    }
}

impl std::convert::From<i16> for SimpleOpError {
    fn from(value: i16) -> Self {
        Self::with_code(value)
    }
}

impl std::convert::From<SimpleOpError> for i16 {
    fn from(value: SimpleOpError) -> Self {
        value.code
    }
}

#[async_trait::async_trait]
pub trait SimpleOperation<C: Send + 'static = ()>: Send + Sync {
    type User: Sync;
    const CODE: u8;

    async fn handle(&self, params: ParameterTable<C>, user: &Self::User) -> Result<ParameterTable<C>, SimpleOpError>;
}

pub struct SimpleOpImpl<C: Send + 'static, U: Sync, O: SimpleOperation<C, User=U>> {
    inner: O,
    _c: std::marker::PhantomData<fn() -> C>,
    _u: std::marker::PhantomData<fn() -> U>,
}

impl<C: Send + 'static, U: Sync, O: SimpleOperation<C, User=U>> SimpleOpImpl<C, U, O> {
    pub fn new(op: O) -> Self {
        Self {
            inner: op,
            _c: Default::default(),
            _u: Default::default(),
        }
    }
}

#[async_trait::async_trait]
impl <C: Send + 'static, U: Sync, X: SimpleOperation<C, User=U>> Operation<C> for SimpleOpImpl<C, U, X> {
    type User = U;
    async fn handle_async(&self, params: ParameterTable<C>, user: &Self::User) -> OperationResponse<C> {
        let result = self.inner.handle(params, user).await;
        match result {
            Ok(p_out) => {
                OperationResponse {
                    code: X::CODE,
                    return_code: 0,
                    message: polariton::operation::Typed::Null,
                    params: p_out,
                }
            },
            Err(e) => {
                OperationResponse {
                    code: X::CODE,
                    return_code: e.code,
                    message: e.message.map(|s| polariton::operation::Typed::Str(s.into()))
                        .unwrap_or(polariton::operation::Typed::Null),
                    params: std::collections::HashMap::new().into(),
                }
            }
        }
    }
}

impl <C: Send + 'static, U: Sync, X: SimpleOperation<C, User=U>> OperationCode for SimpleOpImpl<C, U, X> {
    fn op_code() -> u8 {
        X::CODE
    }
}