From 06388333af8d9364dbbe78c815e7d0743cd7a4d5 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sat, 13 May 2017 18:16:43 -0700 Subject: [PATCH] Implement ToTokens for Api, Request, and Response. --- src/api.rs | 78 ++++++++++--------------------------------------- src/lib.rs | 8 ++++- src/request.rs | 30 ++++++++++++++++++- src/response.rs | 28 +++++++++++++++++- 4 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/api.rs b/src/api.rs index c812f941..8af8229d 100644 --- a/src/api.rs +++ b/src/api.rs @@ -2,8 +2,8 @@ use quote::{ToTokens, Tokens}; use metadata::Metadata; use parse::Entry; -use request::{Request, RequestField}; -use response::{Response, ResponseField}; +use request::Request; +use response::Response; #[derive(Debug)] pub struct Api { @@ -12,8 +12,8 @@ pub struct Api { response: Response, } -impl Api { - pub fn output(&self) -> Tokens { +impl ToTokens for Api { + fn to_tokens(&self, tokens: &mut Tokens) { let description = &self.metadata.description; let method = &self.metadata.method; let name = &self.metadata.name; @@ -21,10 +21,18 @@ impl Api { let rate_limited = &self.metadata.rate_limited; let requires_authentication = &self.metadata.requires_authentication; - let request_types = self.generate_request_types(); - let response_types = self.generate_response_types(); + let request_types = { + let mut tokens = Tokens::new(); + self.request.to_tokens(&mut tokens); + tokens + }; + let response_types = { + let mut tokens = Tokens::new(); + self.response.to_tokens(&mut tokens); + tokens + }; - quote! { + tokens.append(quote! { use std::convert::TryFrom; /// The API endpoint. @@ -69,59 +77,7 @@ impl Api { requires_authentication: #requires_authentication, }; } - } - } - - fn generate_request_types(&self) -> Tokens { - let mut tokens = quote! { - /// Data for a request to this API endpoint. - #[derive(Debug)] - pub struct Request - }; - - if self.request.fields.len() == 0 { - tokens.append(";"); - } else { - tokens.append("{"); - - for request_field in self.request.fields.iter() { - match *request_field { - RequestField::Body(ref field) => field.to_tokens(&mut tokens), - RequestField::Header(_, ref field) => field.to_tokens(&mut tokens), - RequestField::Path(_, ref field) => field.to_tokens(&mut tokens), - RequestField::Query(ref field) => field.to_tokens(&mut tokens), - } - } - - tokens.append("}"); - } - - tokens - } - - fn generate_response_types(&self) -> Tokens { - let mut tokens = quote! { - /// Data in the response from this API endpoint. - #[derive(Debug)] - pub struct Response - }; - - if self.response.fields.len() == 0 { - tokens.append(";"); - } else { - tokens.append("{"); - - for response in self.response.fields.iter() { - match *response { - ResponseField::Body(ref field) => field.to_tokens(&mut tokens), - ResponseField::Header(_, ref field) => field.to_tokens(&mut tokens), - } - } - - tokens.append("}"); - } - - tokens + }); } } @@ -150,5 +106,3 @@ impl From> for Api { } } } - - diff --git a/src/lib.rs b/src/lib.rs index 0041bae1..80e3805f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,8 @@ extern crate syn; use proc_macro::TokenStream; +use quote::{ToTokens, Tokens}; + use api::Api; use parse::parse_entries; @@ -28,5 +30,9 @@ pub fn ruma_api(input: TokenStream) -> TokenStream { let api = Api::from(entries); - api.output().parse().expect("ruma_api! failed to parse output as a TokenStream") + let mut tokens = Tokens::new(); + + api.to_tokens(&mut tokens); + + tokens.parse().expect("ruma_api! failed to parse output tokens as a TokenStream") } diff --git a/src/request.rs b/src/request.rs index bfd0f6ee..214498e5 100644 --- a/src/request.rs +++ b/src/request.rs @@ -1,8 +1,9 @@ +use quote::{ToTokens, Tokens}; use syn::{Field, Lit, MetaItem}; #[derive(Debug)] pub struct Request { - pub fields: Vec, + fields: Vec, } impl From> for Request { @@ -43,6 +44,33 @@ impl From> for Request { } } +impl ToTokens for Request { + fn to_tokens(&self, mut tokens: &mut Tokens) { + tokens.append(quote! { + /// Data for a request to this API endpoint. + #[derive(Debug)] + pub struct Request + }); + + if self.fields.len() == 0 { + tokens.append(";"); + } else { + tokens.append("{"); + + for request_field in self.fields.iter() { + match *request_field { + RequestField::Body(ref field) => field.to_tokens(&mut tokens), + RequestField::Header(_, ref field) => field.to_tokens(&mut tokens), + RequestField::Path(_, ref field) => field.to_tokens(&mut tokens), + RequestField::Query(ref field) => field.to_tokens(&mut tokens), + } + } + + tokens.append("}"); + } + } +} + #[derive(Debug)] pub enum RequestField { Body(Field), diff --git a/src/response.rs b/src/response.rs index 16a45e0d..35bfcc06 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,8 +1,9 @@ +use quote::{ToTokens, Tokens}; use syn::{Field, Lit, MetaItem}; #[derive(Debug)] pub struct Response { - pub fields: Vec, + fields: Vec, } impl From> for Response { @@ -32,6 +33,31 @@ impl From> for Response { } } +impl ToTokens for Response { + fn to_tokens(&self, mut tokens: &mut Tokens) { + tokens.append(quote! { + /// Data in the response from this API endpoint. + #[derive(Debug)] + pub struct Response + }); + + if self.fields.len() == 0 { + tokens.append(";"); + } else { + tokens.append("{"); + + for response in self.fields.iter() { + match *response { + ResponseField::Body(ref field) => field.to_tokens(&mut tokens), + ResponseField::Header(_, ref field) => field.to_tokens(&mut tokens), + } + } + + tokens.append("}"); + } + } +} + #[derive(Debug)] pub enum ResponseField { Body(Field),