Use three block form for the macro, fix some bugs, construct metadata tokens.
This commit is contained in:
parent
bf7189048a
commit
d0a35341a2
91
src/lib.rs
91
src/lib.rs
@ -8,7 +8,7 @@ extern crate syn;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
use quote::Tokens;
|
||||
use quote::{ToTokens, Tokens};
|
||||
use syn::{Expr, Field, Ident, Item};
|
||||
|
||||
use parse::{Entry, parse_entries};
|
||||
@ -38,17 +38,26 @@ impl Api {
|
||||
|
||||
impl From<Vec<Entry>> for Api {
|
||||
fn from(entries: Vec<Entry>) -> Api {
|
||||
if entries.len() != 3 {
|
||||
panic!("ruma_api! expects 3 blocks: metadata, request, and response");
|
||||
}
|
||||
|
||||
let mut metadata = None;
|
||||
let mut request = None;
|
||||
let mut response = None;
|
||||
|
||||
for entry in entries {
|
||||
match entry {
|
||||
Entry::Metadata(fields) => metadata = Some(Metadata::from(fields)),
|
||||
Entry::Request(fields) => request = Some(Request::from(fields)),
|
||||
Entry::Response(fields) => response = Some(Response::from(fields)),
|
||||
}
|
||||
}
|
||||
|
||||
Api {
|
||||
metadata: Metadata {
|
||||
description: Tokens::new(),
|
||||
method: Tokens::new(),
|
||||
name: Tokens::new(),
|
||||
path: Tokens::new(),
|
||||
rate_limited: Tokens::new(),
|
||||
requires_authentication: Tokens::new(),
|
||||
},
|
||||
request: Request,
|
||||
response: Response,
|
||||
metadata: metadata.expect("ruma_api! is missing metadata"),
|
||||
request: request.expect("ruma_api! is missing request"),
|
||||
response: response.expect("ruma_api! is missing response"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,20 +71,68 @@ struct Metadata {
|
||||
requires_authentication: Tokens,
|
||||
}
|
||||
|
||||
impl From<Vec<(Ident, Expr)>> for Metadata {
|
||||
fn from(fields: Vec<(Ident, Expr)>) -> Self {
|
||||
let mut description = None;
|
||||
let mut method = None;
|
||||
let mut name = None;
|
||||
let mut path = None;
|
||||
let mut rate_limited = None;
|
||||
let mut requires_authentication = None;
|
||||
|
||||
for field in fields {
|
||||
let (identifier, expression) = field;
|
||||
|
||||
if identifier == Ident::new("description") {
|
||||
description = Some(tokens_for(expression));
|
||||
} else if identifier == Ident::new("method") {
|
||||
method = Some(tokens_for(expression));
|
||||
} else if identifier == Ident::new("name") {
|
||||
name = Some(tokens_for(expression));
|
||||
} else if identifier == Ident::new("path") {
|
||||
path = Some(tokens_for(expression));
|
||||
} else if identifier == Ident::new("rate_limited") {
|
||||
rate_limited = Some(tokens_for(expression));
|
||||
} else if identifier == Ident::new("requires_authentication") {
|
||||
requires_authentication = Some(tokens_for(expression));
|
||||
} else {
|
||||
panic!("ruma_api! metadata included unexpected field: {}", identifier);
|
||||
}
|
||||
}
|
||||
|
||||
Metadata {
|
||||
description: description.expect("ruma_api! metadata is missing description"),
|
||||
method: method.expect("ruma_api! metadata is missing method"),
|
||||
name: name.expect("ruma_api! metadata is missing name"),
|
||||
path: path.expect("ruma_api! metadata is missing path"),
|
||||
rate_limited: rate_limited.expect("ruma_api! metadata is missing rate_limited"),
|
||||
requires_authentication: requires_authentication
|
||||
.expect("ruma_api! metadata is missing requires_authentication"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Request;
|
||||
|
||||
impl From<Item> for Request {
|
||||
fn from(item: Item) -> Self {
|
||||
impl From<Vec<Field>> for Request {
|
||||
fn from(fields: Vec<Field>) -> Self {
|
||||
Request
|
||||
// panic!("ruma_api! could not parse Request");
|
||||
}
|
||||
}
|
||||
|
||||
struct Response;
|
||||
|
||||
impl From<Item> for Response {
|
||||
fn from(item: Item) -> Self {
|
||||
impl From<Vec<Field>> for Response {
|
||||
fn from(fields: Vec<Field>) -> Self {
|
||||
Response
|
||||
// panic!("ruma_api! could not parse Response");
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method for turning a value into tokens.
|
||||
fn tokens_for<T>(value: T) -> Tokens where T: ToTokens {
|
||||
let mut tokens = Tokens::new();
|
||||
|
||||
value.to_tokens(&mut tokens);
|
||||
|
||||
tokens
|
||||
}
|
||||
|
27
src/parse.rs
27
src/parse.rs
@ -16,6 +16,7 @@ use syn::{
|
||||
use syn::parse::{expr, ident, lit, ty};
|
||||
use synom::space::{block_comment, whitespace};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Entry {
|
||||
Metadata(Vec<(Ident, Expr)>),
|
||||
Request(Vec<Field>),
|
||||
@ -30,25 +31,25 @@ named!(pub parse_entries -> Vec<Entry>, do_parse!(
|
||||
named!(entry -> Entry, alt!(
|
||||
do_parse!(
|
||||
keyword!("metadata") >>
|
||||
punct!(":") >>
|
||||
punct!("{") >>
|
||||
fields: many0!(struct_init_field) >>
|
||||
punct!("}") >>
|
||||
(Entry::Metadata(fields))
|
||||
)
|
||||
|
|
||||
do_parse!(
|
||||
keyword!("request") >>
|
||||
punct!(":") >>
|
||||
punct!("{") >>
|
||||
fields: many0!(struct_field) >>
|
||||
fields: terminated_list!(punct!(","), struct_field) >>
|
||||
punct!("}") >>
|
||||
(Entry::Request(fields))
|
||||
)
|
||||
|
|
||||
do_parse!(
|
||||
keyword!("response") >>
|
||||
punct!(":") >>
|
||||
punct!("{") >>
|
||||
fields: many0!(struct_field) >>
|
||||
fields: terminated_list!(punct!(","), struct_field) >>
|
||||
punct!("}") >>
|
||||
(Entry::Response(fields))
|
||||
)
|
||||
));
|
||||
@ -63,14 +64,22 @@ named!(struct_init_field -> (Ident, Expr), do_parse!(
|
||||
(ident, expr)
|
||||
));
|
||||
|
||||
named!(pub struct_like_body -> Vec<Field>, do_parse!(
|
||||
punct!("{") >>
|
||||
fields: terminated_list!(punct!(","), struct_field) >>
|
||||
punct!("}") >>
|
||||
(fields)
|
||||
));
|
||||
|
||||
named!(struct_field -> Field, do_parse!(
|
||||
attrs: many0!(outer_attr) >>
|
||||
vis: visibility >>
|
||||
id: ident >>
|
||||
punct!(":") >>
|
||||
ty: ty >>
|
||||
(Field {
|
||||
ident: Some(id),
|
||||
vis: Visibility::Public,
|
||||
vis: Visibility::Public, // Ignore declared visibility, always make fields public
|
||||
attrs: attrs,
|
||||
ty: ty,
|
||||
})
|
||||
@ -142,3 +151,9 @@ named!(nested_meta_item -> NestedMetaItem, alt!(
|
||||
|
|
||||
lit => { NestedMetaItem::Literal }
|
||||
));
|
||||
|
||||
named!(visibility -> Visibility, alt!(
|
||||
keyword!("pub") => { |_| Visibility::Public }
|
||||
|
|
||||
epsilon!() => { |_| Visibility::Inherited }
|
||||
));
|
||||
|
@ -8,16 +8,18 @@ pub mod get_supported_versions {
|
||||
use ruma_api_macros::ruma_api;
|
||||
|
||||
ruma_api! {
|
||||
metadata: {
|
||||
metadata {
|
||||
description: "Get the versions of the client-server API supported by this homeserver.",
|
||||
method: Method::Get,
|
||||
name: "api_versions",
|
||||
path: "/_matrix/client/versions",
|
||||
rate_limited: false,
|
||||
requires_authentication: true,
|
||||
},
|
||||
request: {},
|
||||
response: {
|
||||
}
|
||||
|
||||
request {}
|
||||
|
||||
response {
|
||||
/// A list of Matrix client API protocol versions supported by the homeserver.
|
||||
pub versions: Vec<String>,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user