use std::future::Future; use crate::{ error::{InternalError, SystemError}, module::Event, request::payload::Payload, util::ready::{ready, Ready}, }; use futures_core::ready; use std::{ fmt::{Debug, Display}, hash::Hash, pin::Pin, task::{Context, Poll}, }; #[derive(Clone, Debug)] pub struct EventRequest { id: String, event: Event, data: Option>, } impl EventRequest { pub fn new(event: E) -> EventRequest where E: Eq + Hash + Debug + Clone + Display, { Self { id: uuid::Uuid::new_v4().to_string(), event: event.into(), data: None, } } pub fn data(mut self, data: Vec) -> Self { self.data = Some(data); self } pub fn get_event(&self) -> &Event { &self.event } pub fn get_id(&self) -> &str { &self.id } pub fn from_data(_data: Vec) -> Self { unimplemented!() } } 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 = SystemError; type Future = Ready>; fn from_request(_req: &EventRequest, _payload: &mut Payload) -> Self::Future { ready(Ok(())) } } #[doc(hidden)] impl FromRequest for String { type Error = SystemError; type Future = Ready>; fn from_request(req: &EventRequest, _payload: &mut Payload) -> Self::Future { match &req.data { None => ready(Err(InternalError::new("Expected string but request had data").into())), Some(buf) => ready(Ok(String::from_utf8_lossy(buf).into_owned())), } } } #[doc(hidden)] impl FromRequest for Result where T: FromRequest, { type Error = SystemError; 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, SystemError>; 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)) } }