actix_default_responder/
lib.rs

1extern crate proc_macro;
2extern crate quote;
3
4use proc_macro::TokenStream;
5use quote::quote;
6
7enum ResponderType {
8    Json,
9    Xml,
10    Bincode,
11}
12
13#[proc_macro_derive(JsonResponder)]
14pub fn json_responder_derive(input: TokenStream) -> TokenStream {
15    let ast = syn::parse(input).unwrap();
16    impl_responder(&ast, ResponderType::Json)
17}
18
19#[proc_macro_derive(XMLResponder)]
20pub fn xml_responder_derive(input: TokenStream) -> TokenStream {
21    let ast = syn::parse(input).unwrap();
22    impl_responder(&ast, ResponderType::Xml)
23}
24
25#[proc_macro_derive(BincodeResponder)]
26pub fn bincode_responder_derive(input: TokenStream) -> TokenStream {
27    let ast = syn::parse(input).unwrap();
28    impl_responder(&ast, ResponderType::Bincode)
29}
30
31fn impl_responder(ast: &syn::DeriveInput, responder: ResponderType) -> TokenStream {
32    let name = &ast.ident;
33
34    let body = match responder {
35        ResponderType::Json => quote! {
36            match serde_json::to_string(&self) {
37                Ok(_body) => actix_web::HttpResponse::Ok().content_type("application/json").body(_body),
38                Err(_err) => actix_web::HttpResponse::build(
39                    actix_web::http::StatusCode::INTERNAL_SERVER_ERROR
40                ).body(_err.to_string()),
41            }
42        },
43        ResponderType::Xml => quote! {
44            match serde_xml_rs::to_string(&self) {
45                Ok(_body) => actix_web::HttpResponse::Ok().content_type("application/xml").body(_body),
46                Err(_err) => actix_web::HttpResponse::build(
47                    actix_web::http::StatusCode::INTERNAL_SERVER_ERROR
48                ).body(_err.to_string()),
49            }
50        },
51        ResponderType::Bincode => quote! {
52            match bincode::serialize(&self) {
53                Ok(_body) => actix_web::HttpResponse::Ok().content_type("multipart/form-data").body(_body),
54                Err(_err) => actix_web::HttpResponse::build(
55                    actix_web::http::StatusCode::INTERNAL_SERVER_ERROR
56                ).body(_err.to_string()),
57            }
58        },
59    };
60
61    let gen = quote! {
62        impl actix_web::Responder for #name {
63            type Body = actix_web::body::BoxBody;
64
65            #[inline]
66            fn respond_to(mut self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse<Self::Body> {
67                #body
68            }
69
70        }
71    };
72
73    gen.into()
74}