Use a custom parser for the raw input.
This commit is contained in:
parent
8f6bc5af77
commit
38746660b6
@ -1,7 +1,5 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
|
||||||
use syn::punctuated::Pair;
|
use syn::punctuated::Pair;
|
||||||
use syn::synom::Synom;
|
use syn::{Expr, FieldValue, Lit, Member};
|
||||||
use syn::{Expr, ExprStruct, Ident, Lit, Member};
|
|
||||||
|
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
@ -12,8 +10,8 @@ pub struct Metadata {
|
|||||||
pub requires_authentication: bool,
|
pub requires_authentication: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExprStruct> for Metadata {
|
impl From<Vec<FieldValue>> for Metadata {
|
||||||
fn from(expr: ExprStruct) -> Self {
|
fn from(field_values: Vec<FieldValue>) -> Self {
|
||||||
let mut description = None;
|
let mut description = None;
|
||||||
let mut method = None;
|
let mut method = None;
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
@ -21,15 +19,15 @@ impl From<ExprStruct> for Metadata {
|
|||||||
let mut rate_limited = None;
|
let mut rate_limited = None;
|
||||||
let mut requires_authentication = None;
|
let mut requires_authentication = None;
|
||||||
|
|
||||||
for field in expr.fields {
|
for field_value in field_values {
|
||||||
let identifier = match field.member {
|
let identifier = match field_value.member {
|
||||||
Member::Named(identifier) => identifier,
|
Member::Named(identifier) => identifier,
|
||||||
_ => panic!("expected Member::Named"),
|
_ => panic!("expected Member::Named"),
|
||||||
};
|
};
|
||||||
|
|
||||||
match identifier.as_ref() {
|
match identifier.as_ref() {
|
||||||
"description" => {
|
"description" => {
|
||||||
let expr_lit = match field.expr {
|
let expr_lit = match field_value.expr {
|
||||||
Expr::Lit(expr_lit) => expr_lit,
|
Expr::Lit(expr_lit) => expr_lit,
|
||||||
_ => panic!("expected Expr::Lit"),
|
_ => panic!("expected Expr::Lit"),
|
||||||
};
|
};
|
||||||
@ -40,7 +38,7 @@ impl From<ExprStruct> for Metadata {
|
|||||||
description = Some(lit_str.value());
|
description = Some(lit_str.value());
|
||||||
}
|
}
|
||||||
"method" => {
|
"method" => {
|
||||||
let expr_path = match field.expr {
|
let expr_path = match field_value.expr {
|
||||||
Expr::Path(expr_path) => expr_path,
|
Expr::Path(expr_path) => expr_path,
|
||||||
_ => panic!("expected Expr::Path"),
|
_ => panic!("expected Expr::Path"),
|
||||||
};
|
};
|
||||||
@ -57,7 +55,7 @@ impl From<ExprStruct> for Metadata {
|
|||||||
method = Some(method_name.ident.to_string());
|
method = Some(method_name.ident.to_string());
|
||||||
}
|
}
|
||||||
"name" => {
|
"name" => {
|
||||||
let expr_lit = match field.expr {
|
let expr_lit = match field_value.expr {
|
||||||
Expr::Lit(expr_lit) => expr_lit,
|
Expr::Lit(expr_lit) => expr_lit,
|
||||||
_ => panic!("expected Expr::Lit"),
|
_ => panic!("expected Expr::Lit"),
|
||||||
};
|
};
|
||||||
@ -68,7 +66,7 @@ impl From<ExprStruct> for Metadata {
|
|||||||
name = Some(lit_str.value());
|
name = Some(lit_str.value());
|
||||||
}
|
}
|
||||||
"path" => {
|
"path" => {
|
||||||
let expr_lit = match field.expr {
|
let expr_lit = match field_value.expr {
|
||||||
Expr::Lit(expr_lit) => expr_lit,
|
Expr::Lit(expr_lit) => expr_lit,
|
||||||
_ => panic!("expected Expr::Lit"),
|
_ => panic!("expected Expr::Lit"),
|
||||||
};
|
};
|
||||||
@ -79,7 +77,7 @@ impl From<ExprStruct> for Metadata {
|
|||||||
path = Some(lit_str.value());
|
path = Some(lit_str.value());
|
||||||
}
|
}
|
||||||
"rate_limited" => {
|
"rate_limited" => {
|
||||||
let expr_lit = match field.expr {
|
let expr_lit = match field_value.expr {
|
||||||
Expr::Lit(expr_lit) => expr_lit,
|
Expr::Lit(expr_lit) => expr_lit,
|
||||||
_ => panic!("expected Expr::Lit"),
|
_ => panic!("expected Expr::Lit"),
|
||||||
};
|
};
|
||||||
@ -90,7 +88,7 @@ impl From<ExprStruct> for Metadata {
|
|||||||
rate_limited = Some(lit_bool.value)
|
rate_limited = Some(lit_bool.value)
|
||||||
}
|
}
|
||||||
"requires_authentication" => {
|
"requires_authentication" => {
|
||||||
let expr_lit = match field.expr {
|
let expr_lit = match field_value.expr {
|
||||||
Expr::Lit(expr_lit) => expr_lit,
|
Expr::Lit(expr_lit) => expr_lit,
|
||||||
_ => panic!("expected Expr::Lit"),
|
_ => panic!("expected Expr::Lit"),
|
||||||
};
|
};
|
||||||
|
103
src/api/mod.rs
103
src/api/mod.rs
@ -1,7 +1,7 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::punctuated::Pair;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::synom::Synom;
|
use syn::synom::Synom;
|
||||||
use syn::{Expr, FieldValue, Ident, Member, Meta};
|
use syn::{Field, FieldValue, Meta};
|
||||||
|
|
||||||
mod metadata;
|
mod metadata;
|
||||||
mod request;
|
mod request;
|
||||||
@ -11,10 +11,10 @@ use self::metadata::Metadata;
|
|||||||
use self::request::Request;
|
use self::request::Request;
|
||||||
use self::response::Response;
|
use self::response::Response;
|
||||||
|
|
||||||
pub fn strip_serde_attrs(field_value: &FieldValue) -> FieldValue {
|
pub fn strip_serde_attrs(field: &Field) -> Field {
|
||||||
let mut field_value = field_value.clone();
|
let mut field = field.clone();
|
||||||
|
|
||||||
field_value.attrs = field_value.attrs.into_iter().filter(|attr| {
|
field.attrs = field.attrs.into_iter().filter(|attr| {
|
||||||
let meta = attr.interpret_meta()
|
let meta = attr.interpret_meta()
|
||||||
.expect("ruma_api! could not parse field attributes");
|
.expect("ruma_api! could not parse field attributes");
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ pub fn strip_serde_attrs(field_value: &FieldValue) -> FieldValue {
|
|||||||
false
|
false
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
field_value
|
field
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Api {
|
pub struct Api {
|
||||||
@ -39,59 +39,13 @@ pub struct Api {
|
|||||||
response: Response,
|
response: Response,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vec<Expr>> for Api {
|
impl From<RawApi> for Api {
|
||||||
fn from(exprs: Vec<Expr>) -> Self {
|
fn from(raw_api: RawApi) -> Self {
|
||||||
if exprs.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 expr in exprs {
|
|
||||||
let expr = match expr {
|
|
||||||
Expr::Struct(expr) => expr,
|
|
||||||
_ => panic!("ruma_api! blocks should use struct syntax"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let segments = expr.path.segments.clone();
|
|
||||||
|
|
||||||
if segments.len() != 1 {
|
|
||||||
panic!("ruma_api! blocks must be one of: metadata, request, or response");
|
|
||||||
}
|
|
||||||
|
|
||||||
let last_segment = match segments.last().unwrap() {
|
|
||||||
Pair::End(last_segment) => last_segment,
|
|
||||||
_ => panic!("expected Pair::End"),
|
|
||||||
};
|
|
||||||
|
|
||||||
match last_segment.ident.as_ref() {
|
|
||||||
"metadata" => metadata = Some(expr.into()),
|
|
||||||
"request" => request = Some(expr.into()),
|
|
||||||
"response" => response = Some(expr.into()),
|
|
||||||
_ => panic!("ruma_api! blocks must be one of: metadata, request, or response"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadata.is_none() {
|
|
||||||
panic!("ruma_api! is missing metadata");
|
|
||||||
}
|
|
||||||
|
|
||||||
if request.is_none() {
|
|
||||||
panic!("ruma_api! is missing request");
|
|
||||||
}
|
|
||||||
|
|
||||||
if response.is_none() {
|
|
||||||
panic!("ruma_api! is missing response");
|
|
||||||
}
|
|
||||||
|
|
||||||
Api {
|
Api {
|
||||||
metadata: metadata.unwrap(),
|
metadata: raw_api.metadata.into(),
|
||||||
request: request.unwrap(),
|
request: raw_api.request.into(),
|
||||||
response: response.unwrap(),
|
response: raw_api.response.into(),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,10 +137,7 @@ impl ToTokens for Api {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let add_body_to_request = if let Some(field) = self.request.newtype_body_field() {
|
let add_body_to_request = if let Some(field) = self.request.newtype_body_field() {
|
||||||
let field_name = match field.member {
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
Member::Named(field_name) => field_name,
|
|
||||||
_ => panic!("expected Member::Named"),
|
|
||||||
};
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
let request_body = RequestBody(request.#field_name);
|
let request_body = RequestBody(request.#field_name);
|
||||||
@ -208,10 +159,8 @@ impl ToTokens for Api {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() {
|
let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() {
|
||||||
let field_type = match field.expr {
|
let field_type = &field.ty;
|
||||||
Expr::Path(ref field_type) => field_type,
|
|
||||||
_ => panic!("expected Expr::Path"),
|
|
||||||
};
|
|
||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
@ -362,15 +311,27 @@ impl ToTokens for Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Exprs {
|
type ParseMetadata = Punctuated<FieldValue, Token![,]>;
|
||||||
pub inner: Vec<Expr>,
|
type ParseFields = Punctuated<Field, Token![,]>;
|
||||||
|
|
||||||
|
pub struct RawApi {
|
||||||
|
pub metadata: Vec<FieldValue>,
|
||||||
|
pub request: Vec<Field>,
|
||||||
|
pub response: Vec<Field>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Synom for Exprs {
|
impl Synom for RawApi {
|
||||||
named!(parse -> Self, do_parse!(
|
named!(parse -> Self, do_parse!(
|
||||||
exprs: many0!(syn!(Expr)) >>
|
custom_keyword!(metadata) >>
|
||||||
(Exprs {
|
metadata: braces!(ParseMetadata::parse_terminated) >>
|
||||||
inner: exprs,
|
custom_keyword!(request) >>
|
||||||
|
request: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >>
|
||||||
|
custom_keyword!(response) >>
|
||||||
|
response: braces!(call!(ParseFields::parse_terminated_with, Field::parse_named)) >>
|
||||||
|
(RawApi {
|
||||||
|
metadata: metadata.1.into_iter().collect(),
|
||||||
|
request: request.1.into_iter().collect(),
|
||||||
|
response: response.1.into_iter().collect(),
|
||||||
})
|
})
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::synom::Synom;
|
use syn::{Field, Meta, NestedMeta};
|
||||||
use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta};
|
|
||||||
|
|
||||||
use api::strip_serde_attrs;
|
use api::strip_serde_attrs;
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ impl Request {
|
|||||||
self.fields.iter().filter(|field| field.is_path()).count()
|
self.fields.iter().filter(|field| field.is_path()).count()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newtype_body_field(&self) -> Option<&FieldValue> {
|
pub fn newtype_body_field(&self) -> Option<&Field> {
|
||||||
for request_field in self.fields.iter() {
|
for request_field in self.fields.iter() {
|
||||||
match *request_field {
|
match *request_field {
|
||||||
RequestField::NewtypeBody(ref field) => {
|
RequestField::NewtypeBody(ref field) => {
|
||||||
@ -54,10 +53,7 @@ impl Request {
|
|||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
|
|
||||||
for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
|
for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
|
||||||
let field_name = match field.member {
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
Member::Named(field_name) => field_name,
|
|
||||||
_ => panic!("expected Member::Named"),
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
#field_name: request.#field_name,
|
#field_name: request.#field_name,
|
||||||
@ -68,14 +64,14 @@ impl Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExprStruct> for Request {
|
impl From<Vec<Field>> for Request {
|
||||||
fn from(expr: ExprStruct) -> Self {
|
fn from(fields: Vec<Field>) -> Self {
|
||||||
let mut has_newtype_body = false;
|
let mut has_newtype_body = false;
|
||||||
|
|
||||||
let fields = expr.fields.into_iter().map(|mut field_value| {
|
let fields = fields.into_iter().map(|mut field| {
|
||||||
let mut field_kind = RequestFieldKind::Body;
|
let mut field_kind = RequestFieldKind::Body;
|
||||||
|
|
||||||
field_value.attrs = field_value.attrs.into_iter().filter(|attr| {
|
field.attrs = field.attrs.into_iter().filter(|attr| {
|
||||||
let meta = attr.interpret_meta()
|
let meta = attr.interpret_meta()
|
||||||
.expect("ruma_api! could not parse request field attributes");
|
.expect("ruma_api! could not parse request field attributes");
|
||||||
|
|
||||||
@ -127,7 +123,7 @@ impl From<ExprStruct> for Request {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestField::new(field_kind, field_value)
|
RequestField::new(field_kind, field)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
Request {
|
Request {
|
||||||
@ -160,12 +156,12 @@ impl ToTokens for Request {
|
|||||||
|
|
||||||
if let Some(newtype_body_field) = self.newtype_body_field() {
|
if let Some(newtype_body_field) = self.newtype_body_field() {
|
||||||
let mut field = newtype_body_field.clone();
|
let mut field = newtype_body_field.clone();
|
||||||
let expr = field.expr;
|
let ty = field.ty;
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
/// Data in the request body.
|
/// Data in the request body.
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct RequestBody(#expr);
|
struct RequestBody(#ty);
|
||||||
});
|
});
|
||||||
} else if self.has_body_fields() {
|
} else if self.has_body_fields() {
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
@ -239,15 +235,15 @@ impl ToTokens for Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum RequestField {
|
pub enum RequestField {
|
||||||
Body(FieldValue),
|
Body(Field),
|
||||||
Header(FieldValue),
|
Header(Field),
|
||||||
NewtypeBody(FieldValue),
|
NewtypeBody(Field),
|
||||||
Path(FieldValue),
|
Path(Field),
|
||||||
Query(FieldValue),
|
Query(Field),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestField {
|
impl RequestField {
|
||||||
fn new(kind: RequestFieldKind, field: FieldValue) -> RequestField {
|
fn new(kind: RequestFieldKind, field: Field) -> RequestField {
|
||||||
match kind {
|
match kind {
|
||||||
RequestFieldKind::Body => RequestField::Body(field),
|
RequestFieldKind::Body => RequestField::Body(field),
|
||||||
RequestFieldKind::Header => RequestField::Header(field),
|
RequestFieldKind::Header => RequestField::Header(field),
|
||||||
@ -279,7 +275,7 @@ impl RequestField {
|
|||||||
self.kind() == RequestFieldKind::Query
|
self.kind() == RequestFieldKind::Query
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field(&self) -> &FieldValue {
|
fn field(&self) -> &Field {
|
||||||
match *self {
|
match *self {
|
||||||
RequestField::Body(ref field) => field,
|
RequestField::Body(ref field) => field,
|
||||||
RequestField::Header(ref field) => field,
|
RequestField::Header(ref field) => field,
|
||||||
@ -289,7 +285,7 @@ impl RequestField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field_(&self, kind: RequestFieldKind) -> Option<&FieldValue> {
|
fn field_(&self, kind: RequestFieldKind) -> Option<&Field> {
|
||||||
if self.kind() == kind {
|
if self.kind() == kind {
|
||||||
Some(self.field())
|
Some(self.field())
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::{Expr, ExprStruct, Field, FieldValue, FieldsNamed, Member, Meta, NestedMeta};
|
use syn::{Field, Meta, NestedMeta};
|
||||||
|
|
||||||
use api::strip_serde_attrs;
|
use api::strip_serde_attrs;
|
||||||
|
|
||||||
@ -26,25 +26,15 @@ impl Response {
|
|||||||
for response_field in self.fields.iter() {
|
for response_field in self.fields.iter() {
|
||||||
match *response_field {
|
match *response_field {
|
||||||
ResponseField::Body(ref field) => {
|
ResponseField::Body(ref field) => {
|
||||||
let field_name = match field.member {
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
Member::Named(field_name) => field_name,
|
|
||||||
_ => panic!("expected Member::Named"),
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
#field_name: response_body.#field_name,
|
#field_name: response_body.#field_name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ResponseField::Header(ref field) => {
|
ResponseField::Header(ref field) => {
|
||||||
let field_name = match field.member {
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
Member::Named(field_name) => field_name,
|
let field_type = &field.ty;
|
||||||
_ => panic!("expected Member::Named"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let field_type = match field.expr {
|
|
||||||
Expr::Path(ref field_type) => field_type,
|
|
||||||
_ => panic!("expected Expr::Path"),
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
#field_name: headers.remove::<#field_type>()
|
#field_name: headers.remove::<#field_type>()
|
||||||
@ -52,10 +42,7 @@ impl Response {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
ResponseField::NewtypeBody(ref field) => {
|
ResponseField::NewtypeBody(ref field) => {
|
||||||
let field_name = match field.member {
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
Member::Named(field_name) => field_name,
|
|
||||||
_ => panic!("expected Member::Named"),
|
|
||||||
};
|
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
#field_name: response_body,
|
#field_name: response_body,
|
||||||
@ -67,7 +54,7 @@ impl Response {
|
|||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn newtype_body_field(&self) -> Option<&FieldValue> {
|
pub fn newtype_body_field(&self) -> Option<&Field> {
|
||||||
for response_field in self.fields.iter() {
|
for response_field in self.fields.iter() {
|
||||||
match *response_field {
|
match *response_field {
|
||||||
ResponseField::NewtypeBody(ref field) => {
|
ResponseField::NewtypeBody(ref field) => {
|
||||||
@ -83,14 +70,14 @@ impl Response {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ExprStruct> for Response {
|
impl From<Vec<Field>> for Response {
|
||||||
fn from(expr: ExprStruct) -> Self {
|
fn from(fields: Vec<Field>) -> Self {
|
||||||
let mut has_newtype_body = false;
|
let mut has_newtype_body = false;
|
||||||
|
|
||||||
let fields = expr.fields.into_iter().map(|mut field_value| {
|
let fields = fields.into_iter().map(|mut field| {
|
||||||
let mut field_kind = ResponseFieldKind::Body;
|
let mut field_kind = ResponseFieldKind::Body;
|
||||||
|
|
||||||
field_value.attrs = field_value.attrs.into_iter().filter(|attr| {
|
field.attrs = field.attrs.into_iter().filter(|attr| {
|
||||||
let meta = attr.interpret_meta()
|
let meta = attr.interpret_meta()
|
||||||
.expect("ruma_api! could not parse response field attributes");
|
.expect("ruma_api! could not parse response field attributes");
|
||||||
|
|
||||||
@ -138,11 +125,11 @@ impl From<ExprStruct> for Response {
|
|||||||
if has_newtype_body {
|
if has_newtype_body {
|
||||||
panic!("ruma_api! responses cannot have both normal body fields and a newtype body field");
|
panic!("ruma_api! responses cannot have both normal body fields and a newtype body field");
|
||||||
} else {
|
} else {
|
||||||
return ResponseField::Body(field_value);
|
return ResponseField::Body(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseFieldKind::Header => ResponseField::Header(field_value),
|
ResponseFieldKind::Header => ResponseField::Header(field),
|
||||||
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field_value),
|
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
@ -176,12 +163,12 @@ impl ToTokens for Response {
|
|||||||
|
|
||||||
if let Some(newtype_body_field) = self.newtype_body_field() {
|
if let Some(newtype_body_field) = self.newtype_body_field() {
|
||||||
let mut field = newtype_body_field.clone();
|
let mut field = newtype_body_field.clone();
|
||||||
let expr = field.expr;
|
let ty = field.ty;
|
||||||
|
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
/// Data in the response body.
|
/// Data in the response body.
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct ResponseBody(#expr);
|
struct ResponseBody(#ty);
|
||||||
});
|
});
|
||||||
} else if self.has_body_fields() {
|
} else if self.has_body_fields() {
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
@ -209,13 +196,13 @@ impl ToTokens for Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum ResponseField {
|
pub enum ResponseField {
|
||||||
Body(FieldValue),
|
Body(Field),
|
||||||
Header(FieldValue),
|
Header(Field),
|
||||||
NewtypeBody(FieldValue),
|
NewtypeBody(Field),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseField {
|
impl ResponseField {
|
||||||
fn field(&self) -> &FieldValue {
|
fn field(&self) -> &Field {
|
||||||
match *self {
|
match *self {
|
||||||
ResponseField::Body(ref field) => field,
|
ResponseField::Body(ref field) => field,
|
||||||
ResponseField::Header(ref field) => field,
|
ResponseField::Header(ref field) => field,
|
||||||
|
12
src/lib.rs
12
src/lib.rs
@ -4,9 +4,8 @@
|
|||||||
//! See the documentation for the `ruma_api!` macro for usage details.
|
//! See the documentation for the `ruma_api!` macro for usage details.
|
||||||
|
|
||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![feature(proc_macro, try_from)]
|
#![feature(proc_macro)]
|
||||||
#![recursion_limit="256"]
|
#![recursion_limit="256"]
|
||||||
#![allow(warnings)]
|
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
#[macro_use] extern crate quote;
|
#[macro_use] extern crate quote;
|
||||||
@ -14,11 +13,10 @@ extern crate ruma_api;
|
|||||||
#[macro_use] extern crate syn;
|
#[macro_use] extern crate syn;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use quote::{ToTokens, Tokens};
|
use quote::ToTokens;
|
||||||
|
|
||||||
use api::{Api, Exprs};
|
use api::{Api, RawApi};
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
|
|
||||||
@ -195,9 +193,9 @@ mod api;
|
|||||||
/// ```
|
/// ```
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn ruma_api(input: TokenStream) -> TokenStream {
|
pub fn ruma_api(input: TokenStream) -> TokenStream {
|
||||||
let exprs: Exprs = syn::parse(input).expect("ruma_api! failed to parse input");
|
let raw_api: RawApi = syn::parse(input).expect("ruma_api! failed to parse input");
|
||||||
|
|
||||||
let api = Api::from(exprs.inner);
|
let api = Api::from(raw_api);
|
||||||
|
|
||||||
api.into_tokens().into()
|
api.into_tokens().into()
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![feature(associated_consts, proc_macro, try_from)]
|
#![feature(associated_consts, proc_macro, try_from)]
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate hyper;
|
|
||||||
extern crate ruma_api;
|
extern crate ruma_api;
|
||||||
extern crate ruma_api_macros;
|
extern crate ruma_api_macros;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
@ -17,7 +16,7 @@ pub mod some_endpoint {
|
|||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
metadata {
|
||||||
description: "Does something.",
|
description: "Does something.",
|
||||||
method: Method::Get, // A `hyper::Method` value. No need to import the name.
|
method: GET, // An `http::Method` constant. No imports required.
|
||||||
name: "some_endpoint",
|
name: "some_endpoint",
|
||||||
path: "/_matrix/some/endpoint/:baz",
|
path: "/_matrix/some/endpoint/:baz",
|
||||||
rate_limited: false,
|
rate_limited: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user