diff --git a/Cargo.toml b/Cargo.toml index 7b2e6c99a..f9e2266ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ members = [ ".", "actix-files", "actix-session", + "actix-web-codegen", ] [package.metadata.docs.rs] @@ -63,6 +64,7 @@ actix-codec = "0.1.0" #actix-service = "0.3.2" #actix-utils = "0.3.1" actix-rt = "0.2.0" +actix-web-codegen = { path="actix-web-codegen" } actix-service = { git = "https://github.com/actix/actix-net.git" } actix-utils = { git = "https://github.com/actix/actix-net.git" } diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index c6b52f049..c08cae9c2 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -318,9 +318,7 @@ where } } -impl
NewService
-{
+impl NewService {
type Response = ServiceResponse;
type Error = ();
type Service = FilesService ;
@@ -730,8 +728,7 @@ mod tests {
#[test]
fn test_named_file_content_range_headers() {
let mut srv = test::init_service(
- App::new()
- .service(Files::new("/test", ".").index_file("tests/test.binary")),
+ App::new().service(Files::new("/test", ".").index_file("tests/test.binary")),
);
// Valid range header
@@ -770,8 +767,7 @@ mod tests {
#[test]
fn test_named_file_content_length_headers() {
let mut srv = test::init_service(
- App::new()
- .service(Files::new("test", ".").index_file("tests/test.binary")),
+ App::new().service(Files::new("test", ".").index_file("tests/test.binary")),
);
// Valid range header
diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml
new file mode 100644
index 000000000..24ed36b77
--- /dev/null
+++ b/actix-web-codegen/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "actix-web-codegen"
+description = "Actix web codegen macros"
+version = "0.1.0"
+authors = ["Nikolay Kim for #name {
+ fn register(self, config: &mut actix_web::dev::AppConfig ) {
+ #ast
+ actix_web::dev::HttpServiceFactory::register(
+ actix_web::Resource::new(#path)
+ .route(actix_web::web::get().to(#name)), config);
+ }
+ }
+ })
+ .into()
+}
+
+/// #[post("path")] attribute
+#[proc_macro_attribute]
+pub fn post(args: TokenStream, input: TokenStream) -> TokenStream {
+ let args = parse_macro_input!(args as syn::AttributeArgs);
+ if args.is_empty() {
+ panic!("invalid server definition, expected: #[get(\"some path\")]");
+ }
+
+ // path
+ let path = match args[0] {
+ syn::NestedMeta::Literal(syn::Lit::Str(ref fname)) => {
+ let fname = quote!(#fname).to_string();
+ fname.as_str()[1..fname.len() - 1].to_owned()
+ }
+ _ => panic!("resource path"),
+ };
+
+ let ast: syn::ItemFn = syn::parse(input).unwrap();
+ let name = ast.ident.clone();
+
+ (quote! {
+ #[allow(non_camel_case_types)]
+ struct #name;
+
+ impl for #name {
+ fn register(self, config: &mut actix_web::dev::AppConfig ) {
+ #ast
+ actix_web::dev::HttpServiceFactory::register(
+ actix_web::Resource::new(#path)
+ .route(actix_web::web::post().to(#name)), config);
+ }
+ }
+ })
+ .into()
+}
+
+/// #[put("path")] attribute
+#[proc_macro_attribute]
+pub fn put(args: TokenStream, input: TokenStream) -> TokenStream {
+ let args = parse_macro_input!(args as syn::AttributeArgs);
+ if args.is_empty() {
+ panic!("invalid server definition, expected: #[get(\"some path\")]");
+ }
+
+ // path
+ let path = match args[0] {
+ syn::NestedMeta::Literal(syn::Lit::Str(ref fname)) => {
+ let fname = quote!(#fname).to_string();
+ fname.as_str()[1..fname.len() - 1].to_owned()
+ }
+ _ => panic!("resource path"),
+ };
+
+ let ast: syn::ItemFn = syn::parse(input).unwrap();
+ let name = ast.ident.clone();
+
+ (quote! {
+ #[allow(non_camel_case_types)]
+ struct #name;
+
+ impl for #name {
+ fn register(self, config: &mut actix_web::dev::AppConfig ) {
+ #ast
+ actix_web::dev::HttpServiceFactory::register(
+ actix_web::Resource::new(#path)
+ .route(actix_web::web::put().to(#name)), config);
+ }
+ }
+ })
+ .into()
+}
diff --git a/actix-web-codegen/src/server.rs b/actix-web-codegen/src/server.rs
new file mode 100644
index 000000000..43e663f3a
--- /dev/null
+++ b/actix-web-codegen/src/server.rs
@@ -0,0 +1,31 @@
+use std::collections::HashSet;
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::path::PathBuf;
+
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+use syn;
+
+/// Thrift mux server impl
+pub struct Server {}
+
+impl Server {
+ fn new() -> Server {
+ Server {}
+ }
+
+ /// generate servers
+ pub fn generate(input: TokenStream) {
+ let mut srv = Server::new();
+ let ast: syn::ItemFn = syn::parse2(input).unwrap();
+ println!("T: {:?}", ast.ident);
+
+ // quote! {
+ // #ast
+
+ // #(#servers)*
+ // }
+ }
+}
diff --git a/examples/basic.rs b/examples/basic.rs
index 5fd862d49..39633f523 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -1,9 +1,9 @@
use futures::IntoFuture;
-use actix_web::{
- http::Method, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer,
-};
+use actix_web::macros::get;
+use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
+#[get("/resource1/index.html")]
fn index(req: HttpRequest) -> &'static str {
println!("REQ: {:?}", req);
"Hello world!\r\n"
@@ -14,6 +14,7 @@ fn index_async(req: HttpRequest) -> impl IntoFuture {
let config_ref = Rc::new(RefCell::new(None));
Route {
service: Box::new(RouteNewService::new(
- Extract::new(config_ref.clone())
- .and_then(Handle::new(HttpResponse::NotFound).map_err(|_| panic!())),
+ Extract::new(config_ref.clone()).and_then(
+ Handler::new(HttpResponse::NotFound).map_err(|_| panic!()),
+ ),
)),
guards: Rc::new(Vec::new()),
config: ConfigStorage::default(),
@@ -272,7 +273,7 @@ impl {
T::Config::store_default(&mut self.config);
self.service = Box::new(RouteNewService::new(
Extract::new(self.config_ref.clone())
- .and_then(Handle::new(handler).map_err(|_| panic!())),
+ .and_then(Handler::new(handler).map_err(|_| panic!())),
));
self
}
@@ -314,7 +315,7 @@ impl {
{
self.service = Box::new(RouteNewService::new(
Extract::new(self.config_ref.clone())
- .and_then(AsyncHandle::new(handler).map_err(|_| panic!())),
+ .and_then(AsyncHandler::new(handler).map_err(|_| panic!())),
));
self
}