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
}
}