mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add module, config module data
This commit is contained in:
parent
3b10e3c101
commit
f2f1bd3461
@ -13,7 +13,7 @@ futures-channel = "0.3.15"
|
||||
futures = "0.3.15"
|
||||
futures-util = "0.3.15"
|
||||
bytes = "0.5"
|
||||
|
||||
tokio = { version = "1", features = ["sync"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
@ -1,8 +1,6 @@
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
mem,
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
@ -23,6 +21,22 @@ impl DataContainer {
|
||||
.insert(TypeId::of::<T>(), Box::new(val))
|
||||
.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) }
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod container;
|
||||
pub mod payload;
|
||||
|
@ -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)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
38
rust-lib/flowy-sys/src/error/error.rs
Normal file
38
rust-lib/flowy-sys/src/error/error.rs
Normal 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() }
|
||||
}
|
3
rust-lib/flowy-sys/src/error/mod.rs
Normal file
3
rust-lib/flowy-sys/src/error/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod error;
|
||||
|
||||
pub use error::*;
|
@ -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
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
mod data;
|
||||
mod error;
|
||||
mod handler;
|
||||
mod payload;
|
||||
mod module;
|
||||
mod request;
|
||||
mod response;
|
||||
mod service;
|
||||
|
36
rust-lib/flowy-sys/src/module/data.rs
Normal file
36
rust-lib/flowy-sys/src/module/data.rs
Normal 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!() }
|
||||
}
|
5
rust-lib/flowy-sys/src/module/mod.rs
Normal file
5
rust-lib/flowy-sys/src/module/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
mod data;
|
||||
mod module;
|
||||
|
||||
pub use data::*;
|
||||
pub use module::*;
|
115
rust-lib/flowy-sys/src/module/module.rs
Normal file
115
rust-lib/flowy-sys/src/module/module.rs
Normal 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!() }
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
mod request;
|
||||
|
||||
pub use request::*;
|
||||
|
||||
pub mod payload;
|
||||
mod request;
|
||||
|
@ -1,18 +1,26 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
payload::Payload,
|
||||
util::ready::{ready, Ready},
|
||||
};
|
||||
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 {
|
||||
fn default() -> Self { Self {} }
|
||||
fn default() -> Self { Self { id: "".to_string() } }
|
||||
}
|
||||
|
||||
pub trait FromRequest: Sized {
|
||||
type Error: Into<Error>;
|
||||
type Error: Into<SystemError>;
|
||||
type Future: Future<Output = Result<Self, Self::Error>>;
|
||||
|
||||
fn from_request(req: &FlowyRequest, payload: &mut Payload) -> Self::Future;
|
||||
@ -20,16 +28,16 @@ pub trait FromRequest: Sized {
|
||||
|
||||
#[doc(hidden)]
|
||||
impl FromRequest for () {
|
||||
type Error = Error;
|
||||
type Future = Ready<Result<(), Error>>;
|
||||
type Error = SystemError;
|
||||
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)]
|
||||
impl FromRequest for String {
|
||||
type Error = Error;
|
||||
type Future = Ready<Result<String, Error>>;
|
||||
type Error = SystemError;
|
||||
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())) }
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
use crate::error::Error;
|
||||
use crate::response::{FlowyResponse, ResponseData, StatusCode};
|
||||
use crate::{
|
||||
error::SystemError,
|
||||
response::{data::ResponseData, FlowyResponse, StatusCode},
|
||||
};
|
||||
|
||||
macro_rules! static_response {
|
||||
($name:ident, $status:expr) => {
|
||||
#[allow(non_snake_case, missing_docs)]
|
||||
pub fn $name() -> FlowyResponseBuilder {
|
||||
FlowyResponseBuilder::new($status)
|
||||
}
|
||||
pub fn $name() -> FlowyResponseBuilder { FlowyResponseBuilder::new($status) }
|
||||
};
|
||||
}
|
||||
|
||||
pub struct FlowyResponseBuilder<T = ResponseData> {
|
||||
pub data: T,
|
||||
pub status: StatusCode,
|
||||
pub error: Option<Error>,
|
||||
pub error: Option<SystemError>,
|
||||
}
|
||||
|
||||
impl FlowyResponseBuilder {
|
||||
@ -30,7 +30,7 @@ impl FlowyResponseBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn error(mut self, error: Option<Error>) -> Self {
|
||||
pub fn error(mut self, error: Option<SystemError>) -> Self {
|
||||
self.error = error;
|
||||
self
|
||||
}
|
||||
|
12
rust-lib/flowy-sys/src/response/data.rs
Normal file
12
rust-lib/flowy-sys/src/response/data.rs
Normal 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() }
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
mod builder;
|
||||
mod responder;
|
||||
mod response;
|
||||
|
||||
pub use builder::*;
|
||||
pub use responder::*;
|
||||
pub use response::*;
|
||||
|
||||
mod builder;
|
||||
pub mod data;
|
||||
mod responder;
|
||||
mod response;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
error::SystemError,
|
||||
request::FlowyRequest,
|
||||
response::{FlowyResponseBuilder, Responder},
|
||||
response::{data::ResponseData, Responder},
|
||||
};
|
||||
use std::future::Future;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum StatusCode {
|
||||
@ -11,15 +10,10 @@ pub enum StatusCode {
|
||||
Error,
|
||||
}
|
||||
|
||||
pub enum ResponseData {
|
||||
Bytes(Vec<u8>),
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct FlowyResponse<T = ResponseData> {
|
||||
pub data: T,
|
||||
pub status: StatusCode,
|
||||
pub error: Option<Error>,
|
||||
pub error: Option<SystemError>,
|
||||
}
|
||||
|
||||
impl FlowyResponse {
|
||||
@ -30,32 +24,9 @@ impl FlowyResponse {
|
||||
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 {
|
||||
#[inline]
|
||||
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() }
|
||||
}
|
||||
|
@ -1,24 +1,11 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
payload::Payload,
|
||||
request::FlowyRequest,
|
||||
response::{FlowyResponse, Responder},
|
||||
service::{Service, ServiceFactory, ServiceRequest, ServiceResponse},
|
||||
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;
|
||||
|
||||
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
|
||||
SF: ServiceFactory<Req> + 'static,
|
||||
Req: 'static,
|
||||
@ -26,38 +13,34 @@ where
|
||||
SF::Service: 'static,
|
||||
SF::Future: 'static,
|
||||
SF::Error: 'static,
|
||||
SF::InitError: 'static,
|
||||
{
|
||||
BoxServiceFactory(Box::new(FactoryWrapper(factory)))
|
||||
}
|
||||
|
||||
pub struct BoxServiceFactory<Cfg, Req, Res, Err, InitErr>(Inner<Cfg, Req, Res, Err, InitErr>);
|
||||
impl<C, Req, Res, Err, InitErr> ServiceFactory<Req> for BoxServiceFactory<C, Req, Res, Err, InitErr>
|
||||
pub struct BoxServiceFactory<Cfg, Req, Res, Err>(Inner<Cfg, Req, Res, Err>);
|
||||
impl<Cfg, Req, Res, Err> ServiceFactory<Req> for BoxServiceFactory<Cfg, Req, Res, Err>
|
||||
where
|
||||
Req: 'static,
|
||||
Res: 'static,
|
||||
Err: 'static,
|
||||
InitErr: 'static,
|
||||
{
|
||||
type Response = Res;
|
||||
type Error = Err;
|
||||
type Service = BoxService<Req, Res, Err>;
|
||||
type InitError = InitErr;
|
||||
type Config = C;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, InitErr>>;
|
||||
type Config = Cfg;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::Error>>;
|
||||
|
||||
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<
|
||||
Req,
|
||||
Config = C,
|
||||
Config = Cfg,
|
||||
Response = Res,
|
||||
Error = Err,
|
||||
InitError = InitErr,
|
||||
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);
|
||||
|
||||
impl<SF, Req, Cfg, Res, Err, InitErr> ServiceFactory<Req> for FactoryWrapper<SF>
|
||||
impl<SF, Req, Cfg, Res, Err> ServiceFactory<Req> for FactoryWrapper<SF>
|
||||
where
|
||||
Req: 'static,
|
||||
Res: 'static,
|
||||
Err: 'static,
|
||||
InitErr: 'static,
|
||||
SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err, InitError = InitErr>,
|
||||
SF: ServiceFactory<Req, Config = Cfg, Response = Res, Error = Err>,
|
||||
SF::Future: 'static,
|
||||
SF::Service: 'static,
|
||||
<SF::Service as Service<Req>>::Future: 'static,
|
||||
@ -120,12 +102,11 @@ where
|
||||
type Response = Res;
|
||||
type Error = Err;
|
||||
type Service = BoxService<Req, Res, Err>;
|
||||
type InitError = InitErr;
|
||||
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 {
|
||||
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) })
|
||||
}
|
||||
}
|
@ -1,16 +1,20 @@
|
||||
use crate::error::Error;
|
||||
use crate::payload::Payload;
|
||||
use crate::request::{FlowyRequest, FromRequest};
|
||||
use crate::response::{FlowyResponse, Responder};
|
||||
use crate::service::{Service, ServiceFactory, ServiceRequest, ServiceResponse};
|
||||
use crate::util::ready::*;
|
||||
use std::{
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use futures_core::ready;
|
||||
use paste::paste;
|
||||
use pin_project::pin_project;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use crate::{
|
||||
error::SystemError,
|
||||
request::{payload::Payload, FlowyRequest, FromRequest},
|
||||
response::{FlowyResponse, Responder},
|
||||
service::{Service, ServiceFactory, ServiceRequest, ServiceResponse},
|
||||
util::ready::*,
|
||||
};
|
||||
|
||||
pub trait Handler<T, R>: Clone + 'static
|
||||
where
|
||||
@ -69,15 +73,12 @@ where
|
||||
R::Output: Responder,
|
||||
{
|
||||
type Response = ServiceResponse;
|
||||
type Error = Error;
|
||||
type Error = SystemError;
|
||||
type Service = Self;
|
||||
type InitError = ();
|
||||
type Config = ();
|
||||
type Future = Ready<Result<Self::Service, ()>>;
|
||||
type Future = Ready<Result<Self::Service, Self::Error>>;
|
||||
|
||||
fn new_service(&self, _: ()) -> Self::Future {
|
||||
ready(Ok(self.clone()))
|
||||
}
|
||||
fn new_service(&self, _: ()) -> Self::Future { ready(Ok(self.clone())) }
|
||||
}
|
||||
|
||||
impl<H, T, R> Service<ServiceRequest> for HandlerService<H, T, R>
|
||||
@ -88,7 +89,7 @@ where
|
||||
R::Output: Responder,
|
||||
{
|
||||
type Response = ServiceResponse;
|
||||
type Error = Error;
|
||||
type Error = SystemError;
|
||||
type Future = HandlerServiceFuture<H, T, R>;
|
||||
|
||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
@ -117,9 +118,7 @@ where
|
||||
R: Future,
|
||||
R::Output: Responder,
|
||||
{
|
||||
// Error type in this future is a placeholder type.
|
||||
// all instances of error must be converted to ServiceResponse and return in Ok.
|
||||
type Output = Result<ServiceResponse, Error>;
|
||||
type Output = Result<ServiceResponse, SystemError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
loop {
|
||||
@ -130,20 +129,21 @@ where
|
||||
let fut = handle.call(item);
|
||||
let state = HandlerServiceFuture::Handle(fut, req.take());
|
||||
self.as_mut().set(state);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
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)));
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
HandlerServiceProj::Handle(fut, req) => {
|
||||
let res = ready!(fut.poll(cx));
|
||||
let req = req.take().unwrap();
|
||||
let res = res.respond_to(&req);
|
||||
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)]
|
||||
impl<$($T: FromRequest + 'static),+> FromRequest for ($($T,)+)
|
||||
{
|
||||
type Error = Error;
|
||||
type Error = SystemError;
|
||||
type Future = $tuple_type<$($T),+>;
|
||||
|
||||
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),+>
|
||||
{
|
||||
type Output = Result<($($T,)+), Error>;
|
||||
type Output = Result<($($T,)+), SystemError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.project();
|
||||
@ -233,11 +233,10 @@ factory_tuple! { A B C D E }
|
||||
#[rustfmt::skip]
|
||||
mod m {
|
||||
use super::*;
|
||||
|
||||
tuple_from_req!(TupleFromRequest1, (0, A));
|
||||
tuple_from_req!(TupleFromRequest2, (0, A), (1, B));
|
||||
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!(TupleFromRequest5, (0, A), (1, B), (2, C), (3, D), (4, E));
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
mod boxed;
|
||||
mod dispatch;
|
||||
mod handler;
|
||||
mod service;
|
||||
|
||||
pub use boxed::*;
|
||||
pub use dispatch::*;
|
||||
pub use handler::*;
|
||||
pub use service::*;
|
@ -1,8 +1,10 @@
|
||||
use crate::payload::Payload;
|
||||
use crate::request::FlowyRequest;
|
||||
use crate::response::{FlowyResponse, Responder, ResponseData};
|
||||
use std::future::Future;
|
||||
|
||||
use crate::{
|
||||
request::{payload::Payload, FlowyRequest},
|
||||
response::{data::ResponseData, FlowyResponse},
|
||||
};
|
||||
|
||||
pub trait Service<Request> {
|
||||
type Response;
|
||||
type Error;
|
||||
@ -11,13 +13,12 @@ pub trait Service<Request> {
|
||||
fn call(&self, req: Request) -> Self::Future;
|
||||
}
|
||||
|
||||
pub trait ServiceFactory<Req> {
|
||||
pub trait ServiceFactory<Request> {
|
||||
type Response;
|
||||
type Error;
|
||||
type Service: Service<Req, Response = Self::Response, Error = Self::Error>;
|
||||
type InitError;
|
||||
type Service: Service<Request, Response = Self::Response, Error = Self::Error>;
|
||||
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;
|
||||
}
|
||||
@ -28,17 +29,10 @@ pub struct 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]
|
||||
pub fn into_parts(self) -> (FlowyRequest, Payload) {
|
||||
(self.req, self.payload)
|
||||
}
|
||||
pub fn into_parts(self) -> (FlowyRequest, Payload) { (self.req, self.payload) }
|
||||
}
|
||||
|
||||
pub struct ServiceResponse<T = ResponseData> {
|
||||
@ -47,7 +41,5 @@ pub struct ServiceResponse<T = ResponseData> {
|
||||
}
|
||||
|
||||
impl<T> ServiceResponse<T> {
|
||||
pub fn new(request: FlowyRequest, response: FlowyResponse<T>) -> Self {
|
||||
ServiceResponse { request, response }
|
||||
}
|
||||
pub fn new(request: FlowyRequest, response: FlowyResponse<T>) -> Self { ServiceResponse { request, response } }
|
||||
}
|
Loading…
Reference in New Issue
Block a user