add module, config module data

This commit is contained in:
appflowy 2021-06-25 23:53:13 +08:00
parent 3b10e3c101
commit f2f1bd3461
22 changed files with 322 additions and 363 deletions

View File

@ -13,7 +13,7 @@ futures-channel = "0.3.15"
futures = "0.3.15" futures = "0.3.15"
futures-util = "0.3.15" futures-util = "0.3.15"
bytes = "0.5" bytes = "0.5"
tokio = { version = "1", features = ["sync"] }
[dev-dependencies] [dev-dependencies]
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }

View File

@ -1,8 +1,6 @@
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
collections::HashMap, collections::HashMap,
fmt,
mem,
}; };
#[derive(Default)] #[derive(Default)]
@ -23,6 +21,22 @@ impl DataContainer {
.insert(TypeId::of::<T>(), Box::new(val)) .insert(TypeId::of::<T>(), Box::new(val))
.and_then(downcast_owned) .and_then(downcast_owned)
} }
pub fn remove<T: 'static>(&mut self) -> Option<T> { self.map.remove(&TypeId::of::<T>()).and_then(downcast_owned) }
pub fn get<T: 'static>(&self) -> Option<&T> {
self.map.get(&TypeId::of::<T>()).and_then(|boxed| boxed.downcast_ref())
}
pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.map
.get_mut(&TypeId::of::<T>())
.and_then(|boxed| boxed.downcast_mut())
}
pub fn contains<T: 'static>(&self) -> bool { self.map.contains_key(&TypeId::of::<T>()) }
pub fn extend(&mut self, other: DataContainer) { self.map.extend(other.map); }
} }
fn downcast_owned<T: 'static>(boxed: Box<dyn Any>) -> Option<T> { boxed.downcast().ok().map(|boxed| *boxed) } fn downcast_owned<T: 'static>(boxed: Box<dyn Any>) -> Option<T> { boxed.downcast().ok().map(|boxed| *boxed) }

View File

@ -1,2 +1 @@
pub mod container; pub mod container;
pub mod payload;

View File

@ -1,150 +0,0 @@
use crate::response::{FlowyResponse, StatusCode};
use std::cell::RefCell;
use std::fmt;
pub struct Error {
inner: Box<dyn HandlerError>,
}
impl Error {
pub fn as_handler_error(&self) -> &dyn HandlerError {
self.inner.as_ref()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", &self.inner)
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
fn cause(&self) -> Option<&dyn std::error::Error> {
None
}
}
impl From<Error> for FlowyResponse {
fn from(err: Error) -> Self {
FlowyResponse::from_error(err)
}
}
impl From<FlowyResponse> for Error {
fn from(res: FlowyResponse) -> Error {
InternalError::from_response("", res).into()
}
}
/// `Error` for any error that implements `ResponseError`
impl<T: HandlerError + 'static> From<T> for Error {
fn from(err: T) -> Error {
Error {
inner: Box::new(err),
}
}
}
pub trait HandlerError: fmt::Debug + fmt::Display {
fn status_code(&self) -> StatusCode;
fn as_response(&self) -> FlowyResponse {
let resp = FlowyResponse::new(self.status_code());
resp
}
}
pub struct InternalError<T> {
inner: T,
status: InternalErrorType,
}
enum InternalErrorType {
Status(StatusCode),
Response(RefCell<Option<FlowyResponse>>),
}
impl<T> InternalError<T> {
pub fn new(inner: T, status: StatusCode) -> Self {
InternalError {
inner,
status: InternalErrorType::Status(status),
}
}
pub fn from_response(inner: T, response: FlowyResponse) -> Self {
InternalError {
inner,
status: InternalErrorType::Response(RefCell::new(Some(response))),
}
}
}
impl<T> fmt::Debug for InternalError<T>
where
T: fmt::Debug + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
impl<T> fmt::Display for InternalError<T>
where
T: fmt::Display + 'static,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
impl<T> HandlerError for InternalError<T>
where
T: fmt::Debug + fmt::Display + 'static,
{
fn status_code(&self) -> StatusCode {
match self.status {
InternalErrorType::Status(st) => st,
InternalErrorType::Response(ref resp) => {
if let Some(resp) = resp.borrow().as_ref() {
resp.status.clone()
} else {
StatusCode::Error
}
}
}
}
fn as_response(&self) -> FlowyResponse {
panic!()
// match self.status {
// InternalErrorType::Status(st) => {
// let mut res = Response::new(st);
// let mut buf = BytesMut::new();
// let _ = write!(Writer(&mut buf), "{}", self);
// res.headers_mut().insert(
// header::CONTENT_TYPE,
// header::HeaderValue::from_static("text/plain; charset=utf-8"),
// );
// res.set_body(Body::from(buf))
// }
// InternalErrorType::Response(ref resp) => {
// if let Some(resp) = resp.borrow_mut().take() {
// resp
// } else {
// Response::new(StatusCode::INTERNAL_SERVER_ERROR)
// }
// }
// }
}
}

View File

@ -0,0 +1,38 @@
use crate::response::{FlowyResponse, StatusCode};
use std::{cell::RefCell, fmt};
pub trait Error: fmt::Debug + fmt::Display {
fn status_code(&self) -> StatusCode;
fn as_response(&self) -> FlowyResponse { FlowyResponse::new(self.status_code()) }
}
impl<T: Error + 'static> From<T> for SystemError {
fn from(err: T) -> SystemError { SystemError { inner: Box::new(err) } }
}
pub struct SystemError {
inner: Box<dyn Error>,
}
impl SystemError {
pub fn inner_error(&self) -> &dyn Error { self.inner.as_ref() }
}
impl fmt::Display for SystemError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.inner, f) }
}
impl fmt::Debug for SystemError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", &self.inner) }
}
impl std::error::Error for SystemError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
fn cause(&self) -> Option<&dyn std::error::Error> { None }
}
impl From<SystemError> for FlowyResponse {
fn from(err: SystemError) -> Self { err.inner_error().as_response() }
}

View File

@ -0,0 +1,3 @@
mod error;
pub use error::*;

View File

@ -1,65 +0,0 @@
use crate::{
error::Error,
handler::{boxed, BoxServiceFactory, Handler, HandlerService},
request::FromRequest,
response::Responder,
service::{ServiceRequest, ServiceResponse},
};
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
pub struct HandlerDispatch {
service: BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>,
}
impl HandlerDispatch {
pub fn new<H, T, R>(handler: H) -> Self
where
H: Handler<T, R>,
T: FromRequest + 'static,
R: Future + 'static,
R::Output: Responder + 'static,
{
HandlerDispatch {
service: boxed::factory(HandlerService::new(handler)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{payload::Payload, request::FlowyRequest, service::ServiceFactory};
pub async fn no_params() -> String {
println!("no params");
"hello".to_string()
}
#[tokio::test]
async fn extract_no_params() {
let dispatch = HandlerDispatch::new(no_params);
let resp = response_from_dispatch(dispatch).await;
}
pub async fn one_params(s: String) -> String {
println!("one params");
"hello".to_string()
}
#[tokio::test]
async fn extract_one_params() {
let dispatch = HandlerDispatch::new(one_params);
let resp = response_from_dispatch(dispatch).await;
}
async fn response_from_dispatch(dispatch: HandlerDispatch) -> ServiceResponse {
let service = dispatch.service.new_service(()).await.unwrap();
let service_request = ServiceRequest::new(FlowyRequest::default(), Payload::None);
let resp = service.call(service_request).await.unwrap();
resp
}
}

View File

@ -1,7 +1,6 @@
mod data; mod data;
mod error; mod error;
mod handler; mod module;
mod payload;
mod request; mod request;
mod response; mod response;
mod service; mod service;

View File

@ -0,0 +1,36 @@
use crate::{
error::SystemError,
request::{payload::Payload, FlowyRequest, FromRequest},
util::ready::Ready,
};
use std::{ops::Deref, sync::Arc};
pub struct ModuleData<T: ?Sized>(Arc<T>);
impl<T> ModuleData<T> {
pub fn new(data: T) -> Self { ModuleData(Arc::new(data)) }
pub fn get_ref(&self) -> &T { self.0.as_ref() }
}
impl<T: ?Sized> Deref for ModuleData<T> {
type Target = Arc<T>;
fn deref(&self) -> &Arc<T> { &self.0 }
}
impl<T: ?Sized> Clone for ModuleData<T> {
fn clone(&self) -> ModuleData<T> { ModuleData(self.0.clone()) }
}
impl<T: ?Sized> From<Arc<T>> for ModuleData<T> {
fn from(arc: Arc<T>) -> Self { ModuleData(arc) }
}
impl<T: ?Sized + 'static> FromRequest for ModuleData<T> {
type Error = SystemError;
type Future = Ready<Result<Self, SystemError>>;
#[inline]
fn from_request(req: &FlowyRequest, _: &mut Payload) -> Self::Future { unimplemented!() }
}

View File

@ -0,0 +1,5 @@
mod data;
mod module;
pub use data::*;
pub use module::*;

View File

@ -0,0 +1,115 @@
use crate::{
data::container::DataContainer,
error::SystemError,
module::ModuleData,
request::FromRequest,
response::Responder,
service::{BoxService, Handler, Service, ServiceFactory, ServiceRequest, ServiceResponse},
};
use futures_core::{future::LocalBoxFuture, ready};
use std::{
collections::HashMap,
future::Future,
hash::Hash,
marker::PhantomData,
pin::Pin,
rc::Rc,
task::{Context, Poll},
};
use tokio::sync::{mpsc, mpsc::UnboundedReceiver};
use crate::{
request::{payload::Payload, FlowyRequest},
service::{factory, BoxServiceFactory, HandlerService},
};
use pin_project::pin_project;
use std::fmt::Debug;
pub type Command = String;
pub type ModuleServiceFactory = BoxServiceFactory<(), ServiceRequest, ServiceResponse, SystemError>;
#[pin_project::pin_project]
pub struct Module {
name: String,
data: DataContainer,
fact_map: HashMap<Command, ModuleServiceFactory>,
cmd_rx: UnboundedReceiver<FlowyRequest>,
}
impl Module {
pub fn new(cmd_rx: UnboundedReceiver<FlowyRequest>) -> Self {
Self {
name: "".to_owned(),
data: DataContainer::new(),
fact_map: HashMap::new(),
cmd_rx,
}
}
pub fn name(mut self, s: &str) -> Self {
self.name = s.to_owned();
self
}
pub fn data<D: 'static>(mut self, data: D) -> Self {
let module_data = ModuleData::new(data);
self.data.insert(module_data);
self
}
pub fn event<H, T, R>(mut self, command: Command, handler: H) -> Self
where
H: Handler<T, R>,
T: FromRequest + 'static,
R: Future + 'static,
R::Output: Responder + 'static,
{
self.fact_map.insert(command, factory(HandlerService::new(handler)));
self
}
}
impl Future for Module {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop {
match ready!(Pin::new(&mut self.cmd_rx).poll_recv(cx)) {
None => return Poll::Ready(()),
Some(request) => match self.fact_map.get(request.get_id()) {
Some(factory) => {
let service_future = factory.new_service(());
tokio::task::spawn_local(ModuleServiceFuture {
request,
service_future,
});
},
None => {},
},
}
}
}
}
#[pin_project(project = HandlerServiceProj)]
pub struct ModuleServiceFuture<Service, Error> {
request: FlowyRequest,
#[pin]
service_future: LocalBoxFuture<'static, Result<Service, Error>>,
}
impl<Service, Error> Future for ModuleServiceFuture<Service, Error> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { unimplemented!() }
}
impl ServiceFactory<ServiceRequest> for Module {
type Response = ServiceResponse;
type Error = SystemError;
type Service = BoxService<ServiceRequest, ServiceResponse, SystemError>;
type Config = ();
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
fn new_service(&self, cfg: Self::Config) -> Self::Future { unimplemented!() }
}

View File

@ -1,3 +1,4 @@
mod request;
pub use request::*; pub use request::*;
pub mod payload;
mod request;

View File

@ -1,18 +1,26 @@
use crate::{
error::Error,
payload::Payload,
util::ready::{ready, Ready},
};
use std::future::Future; use std::future::Future;
pub struct FlowyRequest {} use crate::{
error::SystemError,
request::payload::Payload,
util::ready::{ready, Ready},
};
use std::hash::Hash;
pub struct FlowyRequest {
id: String,
}
impl FlowyRequest {
pub fn get_id(&self) -> &str { &self.id }
}
impl std::default::Default for FlowyRequest { impl std::default::Default for FlowyRequest {
fn default() -> Self { Self {} } fn default() -> Self { Self { id: "".to_string() } }
} }
pub trait FromRequest: Sized { pub trait FromRequest: Sized {
type Error: Into<Error>; type Error: Into<SystemError>;
type Future: Future<Output = Result<Self, Self::Error>>; type Future: Future<Output = Result<Self, Self::Error>>;
fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future; fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future;
@ -20,16 +28,16 @@ pub trait FromRequest: Sized {
#[doc(hidden)] #[doc(hidden)]
impl FromRequest for () { impl FromRequest for () {
type Error = Error; type Error = SystemError;
type Future = Ready<Result<(), Error>>; type Future = Ready<Result<(), SystemError>>;
fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future { ready(Ok(())) } fn from_request(_req: &FlowyRequest, _payload: &mut Payload) -> Self::Future { ready(Ok(())) }
} }
#[doc(hidden)] #[doc(hidden)]
impl FromRequest for String { impl FromRequest for String {
type Error = Error; type Error = SystemError;
type Future = Ready<Result<String, Error>>; type Future = Ready<Result<String, SystemError>>;
fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future { ready(Ok("".to_string())) } fn from_request(_req: &FlowyRequest, _payload: &mut Payload) -> Self::Future { ready(Ok("".to_string())) }
} }

View File

@ -1,19 +1,19 @@
use crate::error::Error; use crate::{
use crate::response::{FlowyResponse, ResponseData, StatusCode}; error::SystemError,
response::{data::ResponseData, FlowyResponse, StatusCode},
};
macro_rules! static_response { macro_rules! static_response {
($name:ident, $status:expr) => { ($name:ident, $status:expr) => {
#[allow(non_snake_case, missing_docs)] #[allow(non_snake_case, missing_docs)]
pub fn $name() -> FlowyResponseBuilder { pub fn $name() -> FlowyResponseBuilder { FlowyResponseBuilder::new($status) }
FlowyResponseBuilder::new($status)
}
}; };
} }
pub struct FlowyResponseBuilder<T = ResponseData> { pub struct FlowyResponseBuilder<T = ResponseData> {
pub data: T, pub data: T,
pub status: StatusCode, pub status: StatusCode,
pub error: Option<Error>, pub error: Option<SystemError>,
} }
impl FlowyResponseBuilder { impl FlowyResponseBuilder {
@ -30,7 +30,7 @@ impl FlowyResponseBuilder {
self self
} }
pub fn error(mut self, error: Option<Error>) -> Self { pub fn error(mut self, error: Option<SystemError>) -> Self {
self.error = error; self.error = error;
self self
} }

View File

@ -0,0 +1,12 @@
pub enum ResponseData {
Bytes(Vec<u8>),
None,
}
impl std::convert::Into<ResponseData> for String {
fn into(self) -> ResponseData { ResponseData::Bytes(self.into_bytes()) }
}
impl std::convert::Into<ResponseData> for &str {
fn into(self) -> ResponseData { self.to_string().into() }
}

View File

@ -1,7 +1,8 @@
mod builder;
mod responder;
mod response;
pub use builder::*; pub use builder::*;
pub use responder::*; pub use responder::*;
pub use response::*; pub use response::*;
mod builder;
pub mod data;
mod responder;
mod response;

View File

@ -1,9 +1,8 @@
use crate::{ use crate::{
error::Error, error::SystemError,
request::FlowyRequest, request::FlowyRequest,
response::{FlowyResponseBuilder, Responder}, response::{data::ResponseData, Responder},
}; };
use std::future::Future;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum StatusCode { pub enum StatusCode {
@ -11,15 +10,10 @@ pub enum StatusCode {
Error, Error,
} }
pub enum ResponseData {
Bytes(Vec<u8>),
None,
}
pub struct FlowyResponse<T = ResponseData> { pub struct FlowyResponse<T = ResponseData> {
pub data: T, pub data: T,
pub status: StatusCode, pub status: StatusCode,
pub error: Option<Error>, pub error: Option<SystemError>,
} }
impl FlowyResponse { impl FlowyResponse {
@ -30,32 +24,9 @@ impl FlowyResponse {
error: None, error: None,
} }
} }
pub fn success() -> Self {
FlowyResponse {
data: ResponseData::None,
status: StatusCode::Success,
error: None,
}
}
#[inline]
pub fn from_error(error: Error) -> FlowyResponse {
let mut resp = error.as_handler_error().as_response();
resp.error = Some(error);
resp
}
} }
impl Responder for FlowyResponse { impl Responder for FlowyResponse {
#[inline] #[inline]
fn respond_to(self, _: &FlowyRequest) -> FlowyResponse { self } fn respond_to(self, _: &FlowyRequest) -> FlowyResponse { self }
} }
impl std::convert::Into<ResponseData> for String {
fn into(self) -> ResponseData { ResponseData::Bytes(self.into_bytes()) }
}
impl std::convert::Into<ResponseData> for &str {
fn into(self) -> ResponseData { self.to_string().into() }
}

View File

@ -1,24 +1,11 @@
use crate::{ use crate::{
error::Error,
payload::Payload,
request::FlowyRequest,
response::{FlowyResponse, Responder},
service::{Service, ServiceFactory, ServiceRequest, ServiceResponse}, service::{Service, ServiceFactory, ServiceRequest, ServiceResponse},
util::ready::*, util::ready::*,
}; };
use futures_core::ready;
use paste::paste;
use pin_project::pin_project;
use std::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use futures_core::future::LocalBoxFuture; use futures_core::future::LocalBoxFuture;
pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error, SF::InitError> pub fn factory<SF, Req>(factory: SF) -> BoxServiceFactory<SF::Config, Req, SF::Response, SF::Error>
where where
SF: ServiceFactory<Req> + 'static, SF: ServiceFactory<Req> + 'static,
Req: 'static, Req: 'static,
@ -26,38 +13,34 @@ where
SF::Service: 'static, SF::Service: 'static,
SF::Future: 'static, SF::Future: 'static,
SF::Error: 'static, SF::Error: 'static,
SF::InitError: 'static,
{ {
BoxServiceFactory(Box::new(FactoryWrapper(factory))) BoxServiceFactory(Box::new(FactoryWrapper(factory)))
} }
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>); pub struct BoxServiceFactory<Cfg, Req, Res, Err>(Inner<Cfg, Req, Res, Err>);
impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr> impl<Cfg, Req, Res, Err> ServiceFactory<Req> for BoxServiceFactory<Cfg, Req, Res, Err>
where where
Req: 'static, Req: 'static,
Res: 'static, Res: 'static,
Err: 'static, Err: 'static,
InitErr: 'static,
{ {
type Response = Res; type Response = Res;
type Error = Err; type Error = Err;
type Service = BoxService<Req, Res, Err>; type Service = BoxService<Req, Res, Err>;
type InitError = InitErr; type Config = Cfg;
type Config = C; type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
type Future = LocalBoxFuture<'static, Result<Self::Service, InitErr>>;
fn new_service(&self, cfg: C) -> Self::Future { self.0.new_service(cfg) } fn new_service(&self, cfg: Cfg) -> Self::Future { self.0.new_service(cfg) }
} }
type Inner<C, Req, Res, Err, InitErr> = Box< type Inner<Cfg, Req, Res, Err> = Box<
dyn ServiceFactory< dyn ServiceFactory<
Req, Req,
Config = C, Config = Cfg,
Response = Res, Response = Res,
Error = Err, Error = Err,
InitError = InitErr,
Service = BoxService<Req, Res, Err>, Service = BoxService<Req, Res, Err>,
Future = LocalBoxFuture<'static, Result<BoxService<Req, Res, Err>, InitErr>>, Future = LocalBoxFuture<'static, Result<BoxService<Req, Res, Err>, Err>>,
>, >,
>; >;
@ -106,13 +89,12 @@ where
struct FactoryWrapper<SF>(SF); struct FactoryWrapper<SF>(SF);
impl<SF, Req, Cfg, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<SF> impl<SF, Req, Cfg, Res, Err> ServiceFactory<Req> for FactoryWrapper<SF>
where where
Req: 'static, Req: 'static,
Res: 'static, Res: 'static,
Err: 'static, Err: 'static,
InitErr: 'static, SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err>,
SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err, InitError = InitErr>,
SF::Future: 'static, SF::Future: 'static,
SF::Service: 'static, SF::Service: 'static,
<SF::Service as Service<Req>>::Future: 'static, <SF::Service as Service<Req>>::Future: 'static,
@ -120,12 +102,11 @@ where
type Response = Res; type Response = Res;
type Error = Err; type Error = Err;
type Service = BoxService<Req, Res, Err>; type Service = BoxService<Req, Res, Err>;
type InitError = InitErr;
type Config = Cfg; type Config = Cfg;
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>; type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
fn new_service(&self, cfg: Cfg) -> Self::Future { fn new_service(&self, cfg: Cfg) -> Self::Future {
let f = self.0.new_service(cfg); let f = self.0.new_service(cfg);
Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as _) }) Box::pin(async { f.await.map(|s| Box::new(ServiceWrapper::new(s)) as Self::Service) })
} }
} }

View File

@ -1,16 +1,20 @@
use crate::error::Error; use std::{
use crate::payload::Payload; future::Future,
use crate::request::{FlowyRequest, FromRequest}; marker::PhantomData,
use crate::response::{FlowyResponse, Responder}; pin::Pin,
use crate::service::{Service, ServiceFactory, ServiceRequest, ServiceResponse}; task::{Context, Poll},
use crate::util::ready::*; };
use futures_core::ready; use futures_core::ready;
use paste::paste;
use pin_project::pin_project; use pin_project::pin_project;
use std::future::Future;
use std::marker::PhantomData; use crate::{
use std::pin::Pin; error::SystemError,
use std::task::{Context, Poll}; request::{payload::Payload, FlowyRequest, FromRequest},
response::{FlowyResponse, Responder},
service::{Service, ServiceFactory, ServiceRequest, ServiceResponse},
util::ready::*,
};
pub trait Handler<T, R>: Clone + 'static pub trait Handler<T, R>: Clone + 'static
where where
@ -69,15 +73,12 @@ where
R::Output: Responder, R::Output: Responder,
{ {
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = SystemError;
type Service = Self; type Service = Self;
type InitError = ();
type Config = (); type Config = ();
type Future = Ready<Result<Self::Service, ()>>; type Future = Ready<Result<Self::Service, Self::Error>>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: ()) -> Self::Future { ready(Ok(self.clone())) }
ready(Ok(self.clone()))
}
} }
impl<H, T, R> Service<ServiceRequest> for HandlerService<H, T, R> impl<H, T, R> Service<ServiceRequest> for HandlerService<H, T, R>
@ -88,7 +89,7 @@ where
R::Output: Responder, R::Output: Responder,
{ {
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = SystemError;
type Future = HandlerServiceFuture<H, T, R>; type Future = HandlerServiceFuture<H, T, R>;
fn call(&self, req: ServiceRequest) -> Self::Future { fn call(&self, req: ServiceRequest) -> Self::Future {
@ -117,9 +118,7 @@ where
R: Future, R: Future,
R::Output: Responder, R::Output: Responder,
{ {
// Error type in this future is a placeholder type. type Output = Result<ServiceResponse, SystemError>;
// all instances of error must be converted to ServiceResponse and return in Ok.
type Output = Result<ServiceResponse, Error>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop { loop {
@ -130,20 +129,21 @@ where
let fut = handle.call(item); let fut = handle.call(item);
let state = HandlerServiceFuture::Handle(fut, req.take()); let state = HandlerServiceFuture::Handle(fut, req.take());
self.as_mut().set(state); self.as_mut().set(state);
} },
Err(err) => { Err(err) => {
let req = req.take().unwrap(); let req = req.take().unwrap();
let res = FlowyResponse::from_error(err.into()); let system_err: SystemError = err.into();
let res: FlowyResponse = system_err.into();
return Poll::Ready(Ok(ServiceResponse::new(req, res))); return Poll::Ready(Ok(ServiceResponse::new(req, res)));
} },
}; };
} },
HandlerServiceProj::Handle(fut, req) => { HandlerServiceProj::Handle(fut, req) => {
let res = ready!(fut.poll(cx)); let res = ready!(fut.poll(cx));
let req = req.take().unwrap(); let req = req.take().unwrap();
let res = res.respond_to(&req); let res = res.respond_to(&req);
return Poll::Ready(Ok(ServiceResponse::new(req, res))); return Poll::Ready(Ok(ServiceResponse::new(req, res)));
} },
} }
} }
} }
@ -175,7 +175,7 @@ macro_rules! tuple_from_req ({$tuple_type:ident, $(($n:tt, $T:ident)),+} => {
#[allow(unused_parens)] #[allow(unused_parens)]
impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+) impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+)
{ {
type Error = Error; type Error = SystemError;
type Future = $tuple_type<$($T),+>; type Future = $tuple_type<$($T),+>;
fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future { fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future {
@ -196,7 +196,7 @@ macro_rules! tuple_from_req ({$tuple_type:ident, $(($n:tt, $T:ident)),+} => {
impl<$($T: FromRequest),+> Future for $tuple_type<$($T),+> impl<$($T: FromRequest),+> Future for $tuple_type<$($T),+>
{ {
type Output = Result<($($T,)+), Error>; type Output = Result<($($T,)+), SystemError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project(); let mut this = self.project();
@ -233,11 +233,10 @@ factory_tuple! { A B C D E }
#[rustfmt::skip] #[rustfmt::skip]
mod m { mod m {
use super::*; use super::*;
tuple_from_req!(TupleFromRequest1, (0, A)); tuple_from_req!(TupleFromRequest1, (0, A));
tuple_from_req!(TupleFromRequest2, (0, A), (1, B)); tuple_from_req!(TupleFromRequest2, (0, A), (1, B));
tuple_from_req!(TupleFromRequest3, (0, A), (1, B), (2, C)); tuple_from_req!(TupleFromRequest3, (0, A), (1, B), (2, C));
tuple_from_req!(TupleFromRequest4, (0, A), (1, B), (2, C), (3, D)); tuple_from_req!(TupleFromRequest4, (0, A), (1, B), (2, C), (3, D));
tuple_from_req!(TupleFromRequest5, (0, A), (1, B), (2, C), (3, D), (4, E)); tuple_from_req!(TupleFromRequest5, (0, A), (1, B), (2, C), (3, D), (4, E));
} }

View File

@ -1,7 +1,7 @@
mod boxed; mod boxed;
mod dispatch;
mod handler; mod handler;
mod service;
pub use boxed::*; pub use boxed::*;
pub use dispatch::*;
pub use handler::*; pub use handler::*;
pub use service::*;

View File

@ -1,8 +1,10 @@
use crate::payload::Payload;
use crate::request::FlowyRequest;
use crate::response::{FlowyResponse, Responder, ResponseData};
use std::future::Future; use std::future::Future;
use crate::{
request::{payload::Payload, FlowyRequest},
response::{data::ResponseData, FlowyResponse},
};
pub trait Service<Request> { pub trait Service<Request> {
type Response; type Response;
type Error; type Error;
@ -11,13 +13,12 @@ pub trait Service<Request> {
fn call(&self, req: Request) -> Self::Future; fn call(&self, req: Request) -> Self::Future;
} }
pub trait ServiceFactory<Req> { pub trait ServiceFactory<Request> {
type Response; type Response;
type Error; type Error;
type Service: Service<Req, Response = Self::Response, Error = Self::Error>; type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
type InitError;
type Config; type Config;
type Future: Future<Output = Result<Self::Service, Self::InitError>>; type Future: Future<Output = Result<Self::Service, Self::Error>>;
fn new_service(&self, cfg: Self::Config) -> Self::Future; fn new_service(&self, cfg: Self::Config) -> Self::Future;
} }
@ -28,17 +29,10 @@ pub struct ServiceRequest {
} }
impl ServiceRequest { impl ServiceRequest {
pub fn new(req: FlowyRequest, payload: Payload) -> Self { Self { req, payload } }
pub fn new(req: FlowyRequest, payload: Payload) -> Self {
Self {
req, payload,
}
}
#[inline] #[inline]
pub fn into_parts(self) -> (FlowyRequest, Payload) { pub fn into_parts(self) -> (FlowyRequest, Payload) { (self.req, self.payload) }
(self.req, self.payload)
}
} }
pub struct ServiceResponse<T = ResponseData> { pub struct ServiceResponse<T = ResponseData> {
@ -47,7 +41,5 @@ pub struct ServiceResponse<T = ResponseData> {
} }
impl<T> ServiceResponse<T> { impl<T> ServiceResponse<T> {
pub fn new(request: FlowyRequest, response: FlowyResponse<T>) -> Self { pub fn new(request: FlowyRequest, response: FlowyResponse<T>) -> Self { ServiceResponse { request, response } }
ServiceResponse { request, response }
}
} }