use std::future::Future; use crate::{ errors::{DispatchError, InternalError}, module::{Event, ModuleDataMap}, request::payload::Payload, util::ready::{ready, Ready}, }; use derivative::*; use futures_core::ready; use std::{ fmt::Debug, pin::Pin, sync::Arc, task::{Context, Poll}, }; #[derive(Clone, Debug, Derivative)] pub struct EventRequest { pub(crate) id: String, pub(crate) event: Event, #[derivative(Debug = "ignore")] pub(crate) module_data: Arc, } impl EventRequest { pub fn new(id: String, event: E, module_data: Arc) -> EventRequest where E: Into, { Self { id, event: event.into(), module_data, } } pub fn module_data(&self) -> Option<&T> where T: Send + Sync, { if let Some(data) = self.module_data.get::() { return Some(data); } None } } pub trait FromRequest: Sized { type Error: Into; type Future: Future>; fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future; } #[doc(hidden)] impl FromRequest for () { type Error = DispatchError; type Future = Ready>; fn from_request(_req: &EventRequest, _payload: &mut Payload) -> Self::Future { ready(Ok(())) } } #[doc(hidden)] impl FromRequest for String { type Error = DispatchError; type Future = Ready>; fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { match &payload { Payload::None => ready(Err(unexpected_none_payload(req))), Payload::Bytes(buf) => ready(Ok(String::from_utf8_lossy(buf).into_owned())), } } } pub fn unexpected_none_payload(request: &EventRequest) -> DispatchError { log::warn!("{:?} expected payload", &request.event); InternalError::new("Expected payload").into() } #[doc(hidden)] impl FromRequest for Result where T: FromRequest, { type Error = DispatchError; type Future = FromRequestFuture; fn from_request(req: &EventRequest, payload: &mut Payload) -> Self::Future { FromRequestFuture { fut: T::from_request(req, payload), } } } #[pin_project::pin_project] pub struct FromRequestFuture { #[pin] fut: Fut, } impl Future for FromRequestFuture where Fut: Future>, { type Output = Result, DispatchError>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let res = ready!(this.fut.poll(cx)); Poll::Ready(Ok(res)) } }