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 proc_macro::TokenStream;
|
||||||
|
|
||||||
use quote::Tokens;
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::{Expr, Field, Ident, Item};
|
use syn::{Expr, Field, Ident, Item};
|
||||||
|
|
||||||
use parse::{Entry, parse_entries};
|
use parse::{Entry, parse_entries};
|
||||||
@ -38,17 +38,26 @@ impl Api {
|
|||||||
|
|
||||||
impl From<Vec<Entry>> for Api {
|
impl From<Vec<Entry>> for Api {
|
||||||
fn from(entries: Vec<Entry>) -> 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 {
|
Api {
|
||||||
metadata: Metadata {
|
metadata: metadata.expect("ruma_api! is missing metadata"),
|
||||||
description: Tokens::new(),
|
request: request.expect("ruma_api! is missing request"),
|
||||||
method: Tokens::new(),
|
response: response.expect("ruma_api! is missing response"),
|
||||||
name: Tokens::new(),
|
|
||||||
path: Tokens::new(),
|
|
||||||
rate_limited: Tokens::new(),
|
|
||||||
requires_authentication: Tokens::new(),
|
|
||||||
},
|
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,20 +71,68 @@ struct Metadata {
|
|||||||
requires_authentication: Tokens,
|
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;
|
struct Request;
|
||||||
|
|
||||||
impl From<Item> for Request {
|
impl From<Vec<Field>> for Request {
|
||||||
fn from(item: Item) -> Self {
|
fn from(fields: Vec<Field>) -> Self {
|
||||||
Request
|
Request
|
||||||
// panic!("ruma_api! could not parse Request");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Response;
|
struct Response;
|
||||||
|
|
||||||
impl From<Item> for Response {
|
impl From<Vec<Field>> for Response {
|
||||||
fn from(item: Item) -> Self {
|
fn from(fields: Vec<Field>) -> Self {
|
||||||
Response
|
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 syn::parse::{expr, ident, lit, ty};
|
||||||
use synom::space::{block_comment, whitespace};
|
use synom::space::{block_comment, whitespace};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Entry {
|
pub enum Entry {
|
||||||
Metadata(Vec<(Ident, Expr)>),
|
Metadata(Vec<(Ident, Expr)>),
|
||||||
Request(Vec<Field>),
|
Request(Vec<Field>),
|
||||||
@ -30,25 +31,25 @@ named!(pub parse_entries -> Vec<Entry>, do_parse!(
|
|||||||
named!(entry -> Entry, alt!(
|
named!(entry -> Entry, alt!(
|
||||||
do_parse!(
|
do_parse!(
|
||||||
keyword!("metadata") >>
|
keyword!("metadata") >>
|
||||||
punct!(":") >>
|
|
||||||
punct!("{") >>
|
punct!("{") >>
|
||||||
fields: many0!(struct_init_field) >>
|
fields: many0!(struct_init_field) >>
|
||||||
|
punct!("}") >>
|
||||||
(Entry::Metadata(fields))
|
(Entry::Metadata(fields))
|
||||||
)
|
)
|
||||||
|
|
|
|
||||||
do_parse!(
|
do_parse!(
|
||||||
keyword!("request") >>
|
keyword!("request") >>
|
||||||
punct!(":") >>
|
|
||||||
punct!("{") >>
|
punct!("{") >>
|
||||||
fields: many0!(struct_field) >>
|
fields: terminated_list!(punct!(","), struct_field) >>
|
||||||
|
punct!("}") >>
|
||||||
(Entry::Request(fields))
|
(Entry::Request(fields))
|
||||||
)
|
)
|
||||||
|
|
|
|
||||||
do_parse!(
|
do_parse!(
|
||||||
keyword!("response") >>
|
keyword!("response") >>
|
||||||
punct!(":") >>
|
|
||||||
punct!("{") >>
|
punct!("{") >>
|
||||||
fields: many0!(struct_field) >>
|
fields: terminated_list!(punct!(","), struct_field) >>
|
||||||
|
punct!("}") >>
|
||||||
(Entry::Response(fields))
|
(Entry::Response(fields))
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
@ -63,14 +64,22 @@ named!(struct_init_field -> (Ident, Expr), do_parse!(
|
|||||||
(ident, expr)
|
(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!(
|
named!(struct_field -> Field, do_parse!(
|
||||||
attrs: many0!(outer_attr) >>
|
attrs: many0!(outer_attr) >>
|
||||||
|
vis: visibility >>
|
||||||
id: ident >>
|
id: ident >>
|
||||||
punct!(":") >>
|
punct!(":") >>
|
||||||
ty: ty >>
|
ty: ty >>
|
||||||
(Field {
|
(Field {
|
||||||
ident: Some(id),
|
ident: Some(id),
|
||||||
vis: Visibility::Public,
|
vis: Visibility::Public, // Ignore declared visibility, always make fields public
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
ty: ty,
|
ty: ty,
|
||||||
})
|
})
|
||||||
@ -142,3 +151,9 @@ named!(nested_meta_item -> NestedMetaItem, alt!(
|
|||||||
|
|
|
|
||||||
lit => { NestedMetaItem::Literal }
|
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;
|
use ruma_api_macros::ruma_api;
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata: {
|
metadata {
|
||||||
description: "Get the versions of the client-server API supported by this homeserver.",
|
description: "Get the versions of the client-server API supported by this homeserver.",
|
||||||
method: Method::Get,
|
method: Method::Get,
|
||||||
name: "api_versions",
|
name: "api_versions",
|
||||||
path: "/_matrix/client/versions",
|
path: "/_matrix/client/versions",
|
||||||
rate_limited: false,
|
rate_limited: false,
|
||||||
requires_authentication: true,
|
requires_authentication: true,
|
||||||
},
|
}
|
||||||
request: {},
|
|
||||||
response: {
|
request {}
|
||||||
|
|
||||||
|
response {
|
||||||
/// A list of Matrix client API protocol versions supported by the homeserver.
|
/// A list of Matrix client API protocol versions supported by the homeserver.
|
||||||
pub versions: Vec<String>,
|
pub versions: Vec<String>,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user