From 744f56acf9c92bf6c996720bb643248dba70237f Mon Sep 17 00:00:00 2001 From: msrd0 Date: Mon, 6 Apr 2020 16:20:08 +0000 Subject: [PATCH] Less generic type arguments --- gotham_restful/src/lib.rs | 1 + gotham_restful/src/openapi/router.rs | 107 +++++-------- gotham_restful/src/resource.rs | 65 ++++---- gotham_restful/src/result.rs | 6 + gotham_restful/src/routing.rs | 211 +++++++------------------- gotham_restful_derive/src/method.rs | 79 ++++++++-- gotham_restful_derive/src/resource.rs | 3 +- 7 files changed, 200 insertions(+), 272 deletions(-) diff --git a/gotham_restful/src/lib.rs b/gotham_restful/src/lib.rs index 8b5e607..ed38ffa 100644 --- a/gotham_restful/src/lib.rs +++ b/gotham_restful/src/lib.rs @@ -158,6 +158,7 @@ pub use openapi::{ mod resource; pub use resource::{ Resource, + ResourceMethod, ResourceReadAll, ResourceRead, ResourceSearch, diff --git a/gotham_restful/src/openapi/router.rs b/gotham_restful/src/openapi/router.rs index a4aad3e..6bef17e 100644 --- a/gotham_restful/src/openapi/router.rs +++ b/gotham_restful/src/openapi/router.rs @@ -4,19 +4,16 @@ use crate::{ routing::*, OpenapiSchema, OpenapiType, - RequestBody, - ResourceType + RequestBody }; use futures::future::ok; use gotham::{ - extractor::QueryStringExtractor, handler::{Handler, HandlerFuture, NewHandler}, helpers::http::response::create_response, pipeline::chain::PipelineHandleChain, router::builder::*, state::State }; -use hyper::Body; use indexmap::IndexMap; use log::error; use mime::{Mime, APPLICATION_JSON, TEXT_PLAIN}; @@ -25,7 +22,6 @@ use openapiv3::{ ReferenceOr, ReferenceOr::Item, ReferenceOr::Reference, RequestBody as OARequestBody, Response, Responses, Schema, SchemaKind, SecurityScheme, Server, StatusCode, Type }; -use serde::de::DeserializeOwned; use std::panic::RefUnwindSafe; /** @@ -381,134 +377,103 @@ macro_rules! implOpenapiRouter { C : PipelineHandleChain

+ Copy + Send + Sync + 'static, P : RefUnwindSafe + Send + Sync + 'static { - fn read_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceReadAll + fn read_all(&mut self) { - let schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth())); + item.get = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::default(), None, None, Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).read_all::() + (&mut *(self.0).0, self.1).read_all::() } - fn read(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceRead + fn read(&mut self) { - let schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth())); + item.get = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).read::() + (&mut *(self.0).0, self.1).read::() } - fn search(&mut self) - where - Query : ResourceType + DeserializeOwned + QueryStringExtractor + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceSearch + fn search(&mut self) { - let schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); let path = format!("/{}/search", &self.1); let mut item = (self.0).1.remove_path(&self.1); - item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_query_params(Query::schema()), None, None, Res::requires_auth())); + item.get = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::from_query_params(Handler::Query::schema()), None, None, Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).search::() + (&mut *(self.0).0, self.1).search::() } - fn create(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceCreate + fn create(&mut self) { - let schema = (self.0).1.add_schema::(); - let body_schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); + let body_schema = (self.0).1.add_schema::(); let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.post = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth())); + item.post = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Handler::Body::supported_types(), Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).create::() + (&mut *(self.0).0, self.1).create::() } - fn update_all(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdateAll + fn update_all(&mut self) { - let schema = (self.0).1.add_schema::(); - let body_schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); + let body_schema = (self.0).1.add_schema::(); let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth())); + item.put = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Handler::Body::supported_types(), Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).update_all::() + (&mut *(self.0).0, self.1).update_all::() } - fn update(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdate + fn update(&mut self) { - let schema = (self.0).1.add_schema::(); - let body_schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); + let body_schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), Some(body_schema), Body::supported_types(), Res::requires_auth())); + item.put = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), Some(body_schema), Handler::Body::supported_types(), Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).update::() + (&mut *(self.0).0, self.1).update::() } - fn delete_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceDeleteAll + fn delete_all(&mut self) { - let schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth())); + item.delete = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::default(), None, None, Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).delete_all::() + (&mut *(self.0).0, self.1).delete_all::() } - fn delete(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceDelete + fn delete(&mut self) { - let schema = (self.0).1.add_schema::(); + let schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth())); + item.delete = Some(new_operation(Handler::Res::default_status(), Handler::Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Handler::Res::requires_auth())); (self.0).1.add_path(path, item); - (&mut *(self.0).0, self.1).delete::() + (&mut *(self.0).0, self.1).delete::() } } diff --git a/gotham_restful/src/resource.rs b/gotham_restful/src/resource.rs index 171f3f9..3e417f9 100644 --- a/gotham_restful/src/resource.rs +++ b/gotham_restful/src/resource.rs @@ -1,8 +1,9 @@ use crate::{DrawResourceRoutes, RequestBody, ResourceResult, ResourceType}; use gotham::{ - router::response::extender::StaticResponseExtender, - state::{State, StateData} + extractor::QueryStringExtractor, + state::State }; +use hyper::Body; use serde::de::DeserializeOwned; use std::panic::RefUnwindSafe; @@ -18,58 +19,68 @@ pub trait Resource fn setup(route : D); } -/// Handle a GET request on the Resource root. -pub trait ResourceReadAll +pub trait ResourceMethod { - fn read_all(state : &mut State) -> R; + type Res : ResourceResult; +} + +/// Handle a GET request on the Resource root. +pub trait ResourceReadAll : ResourceMethod +{ + fn read_all(state : &mut State) -> Self::Res; } /// Handle a GET request on the Resource with an id. -pub trait ResourceRead -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static +pub trait ResourceRead : ResourceMethod { - fn read(state : &mut State, id : ID) -> R; + type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; + + fn read(state : &mut State, id : Self::ID) -> Self::Res; } /// Handle a GET request on the Resource with additional search parameters. -pub trait ResourceSearch -where - Query : ResourceType + DeserializeOwned + StateData + StaticResponseExtender +pub trait ResourceSearch : ResourceMethod { - fn search(state : &mut State, query : Query) -> R; + type Query : ResourceType + QueryStringExtractor + Sync; + + fn search(state : &mut State, query : Self::Query) -> Self::Res; } /// Handle a POST request on the Resource root. -pub trait ResourceCreate +pub trait ResourceCreate : ResourceMethod { - fn create(state : &mut State, body : Body) -> R; + type Body : RequestBody; + + fn create(state : &mut State, body : Self::Body) -> Self::Res; } /// Handle a PUT request on the Resource root. -pub trait ResourceUpdateAll +pub trait ResourceUpdateAll : ResourceMethod { - fn update_all(state : &mut State, body : Body) -> R; + type Body : RequestBody; + + fn update_all(state : &mut State, body : Self::Body) -> Self::Res; } /// Handle a PUT request on the Resource with an id. -pub trait ResourceUpdate -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static +pub trait ResourceUpdate : ResourceMethod { - fn update(state : &mut State, id : ID, body : Body) -> R; + type Body : RequestBody; + type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; + + fn update(state : &mut State, id : Self::ID, body : Self::Body) -> Self::Res; } /// Handle a DELETE request on the Resource root. -pub trait ResourceDeleteAll +pub trait ResourceDeleteAll : ResourceMethod { - fn delete_all(state : &mut State) -> R; + fn delete_all(state : &mut State) -> Self::Res; } /// Handle a DELETE request on the Resource with an id. -pub trait ResourceDelete -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static +pub trait ResourceDelete : ResourceMethod { - fn delete(state : &mut State, id : ID) -> R; + type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; + + fn delete(state : &mut State, id : Self::ID) -> Self::Res; } diff --git a/gotham_restful/src/result.rs b/gotham_restful/src/result.rs index 00b4c62..8d93d6c 100644 --- a/gotham_restful/src/result.rs +++ b/gotham_restful/src/result.rs @@ -171,6 +171,7 @@ This can be returned from a resource when there is no cause of an error. For exa ``` # #[macro_use] extern crate gotham_restful_derive; +# mod doc_tests_are_broken { # use gotham::state::State; # use gotham_restful::*; # use serde::{Deserialize, Serialize}; @@ -189,6 +190,7 @@ fn read_all(_state: &mut State) -> Success { let res = MyResponse { message: "I'm always happy".to_string() }; res.into() } +# } ``` */ pub struct Success(T); @@ -242,6 +244,7 @@ look something like this (assuming the `auth` feature is enabled): ``` # #[macro_use] extern crate gotham_restful_derive; +# mod doc_tests_are_broken { # use gotham::state::State; # use gotham_restful::*; # use serde::Deserialize; @@ -261,6 +264,7 @@ fn read_all(auth : AuthStatus) -> AuthResult { // do something NoContent::default().into() } +# } ``` */ pub enum AuthResult @@ -359,6 +363,7 @@ the function attributes: ``` # #[macro_use] extern crate gotham_restful_derive; +# mod doc_tests_are_broken { # use gotham::state::State; # use gotham_restful::*; # @@ -369,6 +374,7 @@ the function attributes: fn read_all(_state: &mut State) { // do something } +# } ``` */ #[derive(Default)] diff --git a/gotham_restful/src/routing.rs b/gotham_restful/src/routing.rs index ac1628d..c5a866c 100644 --- a/gotham_restful/src/routing.rs +++ b/gotham_restful/src/routing.rs @@ -2,7 +2,6 @@ use crate::{ resource::*, result::{ResourceError, ResourceResult, Response}, RequestBody, - ResourceType, StatusCode }; #[cfg(feature = "openapi")] @@ -13,7 +12,6 @@ use futures::{ stream::Stream }; use gotham::{ - extractor::QueryStringExtractor, handler::{HandlerFuture, IntoHandlerError}, helpers::http::response::{create_empty_response, create_response}, pipeline::chain::PipelineHandleChain, @@ -35,7 +33,6 @@ use hyper::{ Method }; use mime::{Mime, APPLICATION_JSON}; -use serde::de::DeserializeOwned; use std::panic::RefUnwindSafe; /// Allow us to extract an id from a path. @@ -67,52 +64,14 @@ pub trait DrawResources /// `Resource::setup` method. pub trait DrawResourceRoutes { - fn read_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceReadAll; - - fn read(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceRead; - - fn search(&mut self) - where - Query : ResourceType + DeserializeOwned + QueryStringExtractor + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceSearch; - - fn create(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceCreate; - - fn update_all(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdateAll; - - fn update(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdate; - - fn delete_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceDeleteAll; - - fn delete(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceDelete; + fn read_all(&mut self); + fn read(&mut self); + fn search(&mut self); + fn create(&mut self); + fn update_all(&mut self); + fn update(&mut self); + fn delete_all(&mut self); + fn delete(&mut self); } fn response_from(res : Response, state : &State) -> hyper::Response @@ -195,85 +154,54 @@ where Box::new(f) } -fn read_all_handler(state : State) -> Box -where - Res : ResourceResult, - Handler : ResourceReadAll +fn read_all_handler(state : State) -> Box { to_handler_future(state, |state| Handler::read_all(state)) } -fn read_handler(state : State) -> Box -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceRead +fn read_handler(state : State) -> Box { let id = { - let path : &PathExtractor = PathExtractor::borrow_from(&state); + let path : &PathExtractor = PathExtractor::borrow_from(&state); path.id.clone() }; to_handler_future(state, |state| Handler::read(state, id)) } -fn search_handler(mut state : State) -> Box -where - Query : ResourceType + QueryStringExtractor + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceSearch +fn search_handler(mut state : State) -> Box { - let query = Query::take_from(&mut state); + let query = Handler::Query::take_from(&mut state); to_handler_future(state, |state| Handler::search(state, query)) } -fn create_handler(state : State) -> Box -where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceCreate +fn create_handler(state : State) -> Box { - handle_with_body::(state, |state, body| Handler::create(state, body)) + handle_with_body::(state, |state, body| Handler::create(state, body)) } -fn update_all_handler(state : State) -> Box -where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdateAll +fn update_all_handler(state : State) -> Box { - handle_with_body::(state, |state, body| Handler::update_all(state, body)) + handle_with_body::(state, |state, body| Handler::update_all(state, body)) } -fn update_handler(state : State) -> Box -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdate +fn update_handler(state : State) -> Box { let id = { - let path : &PathExtractor = PathExtractor::borrow_from(&state); + let path : &PathExtractor = PathExtractor::borrow_from(&state); path.id.clone() }; - handle_with_body::(state, |state, body| Handler::update(state, id, body)) + handle_with_body::(state, |state, body| Handler::update(state, id, body)) } -fn delete_all_handler(state : State) -> Box -where - Res : ResourceResult, - Handler : ResourceDeleteAll +fn delete_all_handler(state : State) -> Box { to_handler_future(state, |state| Handler::delete_all(state)) } -fn delete_handler(state : State) -> Box -where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceDelete +fn delete_handler(state : State) -> Box { let id = { - let path : &PathExtractor = PathExtractor::borrow_from(&state); + let path : &PathExtractor = PathExtractor::borrow_from(&state); path.id.clone() }; to_handler_future(state, |state| Handler::delete(state, id)) @@ -368,109 +296,78 @@ macro_rules! implDrawResourceRoutes { C : PipelineHandleChain

+ Copy + Send + Sync + 'static, P : RefUnwindSafe + Send + Sync + 'static { - fn read_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceReadAll + fn read_all(&mut self) { - let matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); + let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); self.0.get(&self.1) .extend_route_matcher(matcher) - .to(|state| read_all_handler::(state)); + .to(|state| read_all_handler::(state)); } - fn read(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceRead + fn read(&mut self) { - let matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); + let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); self.0.get(&format!("{}/:id", self.1)) .extend_route_matcher(matcher) - .with_path_extractor::>() - .to(|state| read_handler::(state)); + .with_path_extractor::>() + .to(|state| read_handler::(state)); } - fn search(&mut self) - where - Query : ResourceType + QueryStringExtractor + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceSearch + fn search(&mut self) { - let matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); + let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); self.0.get(&format!("{}/search", self.1)) .extend_route_matcher(matcher) - .with_query_string_extractor::() - .to(|state| search_handler::(state)); + .with_query_string_extractor::() + .to(|state| search_handler::(state)); } - fn create(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceCreate + fn create(&mut self) { - let accept_matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); - let content_matcher : MaybeMatchContentTypeHeader = Body::supported_types().into(); + let accept_matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); + let content_matcher : MaybeMatchContentTypeHeader = Handler::Body::supported_types().into(); self.0.post(&self.1) .extend_route_matcher(accept_matcher) .extend_route_matcher(content_matcher) - .to(|state| create_handler::(state)); + .to(|state| create_handler::(state)); } - fn update_all(&mut self) - where - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdateAll + fn update_all(&mut self) { - let accept_matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); - let content_matcher : MaybeMatchContentTypeHeader = Body::supported_types().into(); + let accept_matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); + let content_matcher : MaybeMatchContentTypeHeader = Handler::Body::supported_types().into(); self.0.put(&self.1) .extend_route_matcher(accept_matcher) .extend_route_matcher(content_matcher) - .to(|state| update_all_handler::(state)); + .to(|state| update_all_handler::(state)); } - fn update(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Body : RequestBody, - Res : ResourceResult, - Handler : ResourceUpdate + fn update(&mut self) { - let accept_matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); - let content_matcher : MaybeMatchContentTypeHeader = Body::supported_types().into(); + let accept_matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); + let content_matcher : MaybeMatchContentTypeHeader = Handler::Body::supported_types().into(); self.0.put(&format!("{}/:id", self.1)) .extend_route_matcher(accept_matcher) .extend_route_matcher(content_matcher) - .with_path_extractor::>() - .to(|state| update_handler::(state)); + .with_path_extractor::>() + .to(|state| update_handler::(state)); } - fn delete_all(&mut self) - where - Res : ResourceResult, - Handler : ResourceDeleteAll + fn delete_all(&mut self) { - let matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); + let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); self.0.delete(&self.1) .extend_route_matcher(matcher) - .to(|state| delete_all_handler::(state)); + .to(|state| delete_all_handler::(state)); } - fn delete(&mut self) - where - ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, - Res : ResourceResult, - Handler : ResourceDelete + fn delete(&mut self) { - let matcher : MaybeMatchAcceptHeader = Res::accepted_types().into(); + let matcher : MaybeMatchAcceptHeader = Handler::Res::accepted_types().into(); self.0.delete(&format!("{}/:id", self.1)) .extend_route_matcher(matcher) - .with_path_extractor::>() - .to(|state| delete_handler::(state)); + .with_path_extractor::>() + .to(|state| delete_handler::(state)); } } } diff --git a/gotham_restful_derive/src/method.rs b/gotham_restful_derive/src/method.rs index 27e4ae0..2fc1e60 100644 --- a/gotham_restful_derive/src/method.rs +++ b/gotham_restful_derive/src/method.rs @@ -1,4 +1,4 @@ -use heck::SnakeCase; +use heck::{CamelCase, SnakeCase}; use proc_macro::TokenStream; use proc_macro2::{Ident, TokenStream as TokenStream2}; use quote::{format_ident, quote}; @@ -46,6 +46,22 @@ impl FromStr for Method impl Method { + pub fn type_names(&self) -> Vec<&'static str> + { + use Method::*; + + match self { + ReadAll => vec![], + Read => vec!["ID"], + Search => vec!["Query"], + Create => vec!["Body"], + UpdateAll => vec!["Body"], + Update => vec!["ID", "Body"], + DeleteAll => vec![], + Delete => vec!["ID"] + } + } + pub fn trait_ident(&self) -> Ident { use Method::*; @@ -80,6 +96,16 @@ impl Method format_ident!("{}", name) } + pub fn mod_ident(&self, resource : String) -> Ident + { + format_ident!("_gotham_restful_resource_{}_method_{}", resource.to_snake_case(), self.fn_ident()) + } + + pub fn handler_struct_ident(&self, resource : String) -> Ident + { + format_ident!("{}{}Handler", resource.to_camel_case(), self.trait_ident()) + } + pub fn setup_ident(&self, resource : String) -> Ident { format_ident!("{}_{}_setup_impl", resource.to_snake_case(), self.fn_ident()) @@ -194,6 +220,8 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) - let trait_ident = method.trait_ident(); let method_ident = method.fn_ident(); + let mod_ident = method.mod_ident(resource_ident.to_string()); + let handler_ident = method.handler_struct_ident(resource_ident.to_string()); let setup_ident = method.setup_ident(resource_ident.to_string()); let (ret, is_no_content) = match &fun.sig.output { @@ -214,11 +242,15 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) - }).collect(); // extract the generic parameters to use - let mut generics : Vec = args.iter() + let generics : Vec = args.iter() .filter(|arg| (*arg).ty.is_method_arg()) .map(|arg| arg.ty.quote_ty().unwrap()) + .zip(method.type_names()) + .map(|(arg, name)| { + let ident = format_ident!("{}", name); + quote!(type #ident = #arg;) + }) .collect(); - generics.push(quote!(#ret)); // extract the definition of our method let mut args_def : Vec = args.iter() @@ -277,22 +309,37 @@ pub fn expand_method(method : Method, attrs : TokenStream, item : TokenStream) - let output = quote! { #fun - impl #krate::#trait_ident<#(#generics),*> for #resource_ident - where #where_clause + #fun_vis mod #mod_ident { - fn #method_ident(#(#args_def),*) -> #ret + use super::*; + + struct #handler_ident; + + impl #krate::ResourceMethod for #handler_ident { - #[allow(unused_imports)] - use #krate::export::{Future, FromState}; - - #block + type Res = #ret; } - } - - #[deny(dead_code)] - #fun_vis fn #setup_ident(route : &mut D) - { - route.#method_ident::<#resource_ident, #(#generics),*>(); + + impl #krate::#trait_ident for #handler_ident + where #where_clause + { + #(#generics)* + + fn #method_ident(#(#args_def),*) -> #ret + { + #[allow(unused_imports)] + use #krate::export::{Future, FromState}; + + #block + } + } + + #[deny(dead_code)] + pub fn #setup_ident(route : &mut D) + { + route.#method_ident::<#handler_ident>(); + } + } }; output.into() diff --git a/gotham_restful_derive/src/resource.rs b/gotham_restful_derive/src/resource.rs index 10d7e6c..a4d8eef 100644 --- a/gotham_restful_derive/src/resource.rs +++ b/gotham_restful_derive/src/resource.rs @@ -39,8 +39,9 @@ pub fn expand_resource(tokens : TokenStream) -> TokenStream m.0.into_iter() }).map(|method| { let method = Method::from_str(&method.to_string()).expect("unknown method"); + let mod_ident = method.mod_ident(ident.to_string()); let ident = method.setup_ident(ident.to_string()); - quote!(#ident(&mut route);) + quote!(#mod_ident::#ident(&mut route);) }).collect(); let output = quote! {