Refactor request module to reduce code duplication

This commit is contained in:
Jonas Platte 2017-06-29 19:22:13 +10:00
parent 170e00a487
commit 5180297d81
2 changed files with 60 additions and 124 deletions

View File

@ -155,7 +155,9 @@ impl ToTokens for Api {
fn try_from(request: Request) -> Result<Self, Self::Error> { fn try_from(request: Request) -> Result<Self, Self::Error> {
let metadata = Endpoint::METADATA; let metadata = Endpoint::METADATA;
// The homeserver url has to be overwritten in the calling code. // Use dummy homeserver url which has to be overwritten in
// the calling code. Previously (with hyper::Uri) this was
// not required, but Url::parse only accepts absolute urls.
let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap(); let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap();
url.set_path(metadata.path); url.set_path(metadata.path);
#set_request_query #set_request_query

View File

@ -19,7 +19,6 @@ impl Request {
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) => {
return Some(field); return Some(field);
} }
_ => continue, _ => continue,
@ -30,14 +29,17 @@ impl Request {
} }
pub fn request_body_init_fields(&self) -> Tokens { pub fn request_body_init_fields(&self) -> Tokens {
self.struct_init_fields(RequestFieldKind::Body)
}
pub fn request_query_init_fields(&self) -> Tokens {
self.struct_init_fields(RequestFieldKind::Query)
}
fn struct_init_fields(&self, request_field_kind: RequestFieldKind) -> Tokens {
let mut tokens = Tokens::new(); let mut tokens = Tokens::new();
for request_field in self.body_fields() { for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
let field = match *request_field {
RequestField::Body(ref field) => field,
_ => panic!("expected body field"),
};
let field_name = field.ident.as_ref().expect("expected body field to have a name"); let field_name = field.ident.as_ref().expect("expected body field to have a name");
tokens.append(quote! { tokens.append(quote! {
@ -47,33 +49,6 @@ impl Request {
tokens tokens
} }
pub fn request_query_init_fields(&self) -> Tokens {
let mut tokens = Tokens::new();
for query_field in self.query_fields() {
let field = match *query_field {
RequestField::Query(ref field) => field,
_ => panic!("expected query field"),
};
let field_name = field.ident.as_ref().expect("expected query field to have a name");
tokens.append(quote! {
#field_name: request.#field_name,
});
}
tokens
}
fn body_fields(&self) -> RequestBodyFields {
RequestBodyFields::new(&self.fields)
}
fn query_fields(&self) -> RequestQueryFields {
RequestQueryFields::new(&self.fields)
}
} }
impl From<Vec<Field>> for Request { impl From<Vec<Field>> for Request {
@ -127,19 +102,14 @@ impl From<Vec<Field>> for Request {
false false
}).collect(); }).collect();
match request_field_kind { if request_field_kind == RequestFieldKind::Body {
RequestFieldKind::Body => { assert!(
if has_newtype_body { !has_newtype_body,
panic!("ruma_api! requests cannot have both normal body fields and a newtype body field"); "ruma_api! requests cannot have both normal body fields and a newtype body field"
} else { );
return RequestField::Body(field);
}
}
RequestFieldKind::Header => RequestField::Header(field),
RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
RequestFieldKind::Path => RequestField::Path(field),
RequestFieldKind::Query => RequestField::Query(field),
} }
RequestField::new(request_field_kind, field)
}).collect(); }).collect();
Request { Request {
@ -162,14 +132,7 @@ impl ToTokens for Request {
tokens.append("{"); tokens.append("{");
for request_field in self.fields.iter() { for request_field in self.fields.iter() {
match *request_field { request_field.field().to_tokens(&mut tokens);
RequestField::Body(ref field) => field.to_tokens(&mut tokens),
RequestField::Header(ref field) => field.to_tokens(&mut tokens),
RequestField::NewtypeBody(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.append(",");
} }
@ -250,21 +213,54 @@ pub enum RequestField {
} }
impl RequestField { impl RequestField {
fn is_body(&self) -> bool { fn new(kind: RequestFieldKind, field: Field) -> RequestField {
match *self { match kind {
RequestField::Body(_) => true, RequestFieldKind::Body => RequestField::Body(field),
_ => false, RequestFieldKind::Header => RequestField::Header(field),
RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
RequestFieldKind::Path => RequestField::Path(field),
RequestFieldKind::Query => RequestField::Query(field),
} }
} }
fn is_query(&self) -> bool { fn kind(&self) -> RequestFieldKind {
match *self { match *self {
RequestField::Query(_) => true, RequestField::Body(_) => RequestFieldKind::Body,
_ => false, RequestField::Header(_) => RequestFieldKind::Header,
RequestField::NewtypeBody(_) => RequestFieldKind::NewtypeBody,
RequestField::Path(_) => RequestFieldKind::Path,
RequestField::Query(_) => RequestFieldKind::Query,
}
}
fn is_body(&self) -> bool {
self.kind() == RequestFieldKind::Body
}
fn is_query(&self) -> bool {
self.kind() == RequestFieldKind::Query
}
fn field(&self) -> &Field {
match *self {
RequestField::Body(ref field) => field,
RequestField::Header(ref field) => field,
RequestField::NewtypeBody(ref field) => field,
RequestField::Path(ref field) => field,
RequestField::Query(ref field) => field,
}
}
fn field_(&self, kind: RequestFieldKind) -> Option<&Field> {
if self.kind() == kind {
Some(self.field())
} else {
None
} }
} }
} }
#[derive(Clone, Copy, PartialEq, Eq)]
enum RequestFieldKind { enum RequestFieldKind {
Body, Body,
Header, Header,
@ -272,65 +268,3 @@ enum RequestFieldKind {
Path, Path,
Query, Query,
} }
#[derive(Debug)]
pub struct RequestBodyFields<'a> {
fields: &'a [RequestField],
index: usize,
}
impl<'a> RequestBodyFields<'a> {
pub fn new(fields: &'a [RequestField]) -> Self {
RequestBodyFields {
fields,
index: 0,
}
}
}
impl<'a> Iterator for RequestBodyFields<'a> {
type Item = &'a RequestField;
fn next(&mut self) -> Option<&'a RequestField> {
while let Some(value) = self.fields.get(self.index) {
self.index += 1;
if value.is_body() {
return Some(value);
}
}
None
}
}
#[derive(Debug)]
pub struct RequestQueryFields<'a> {
fields: &'a [RequestField],
index: usize,
}
impl<'a> RequestQueryFields<'a> {
pub fn new(fields: &'a [RequestField]) -> Self {
RequestQueryFields {
fields,
index: 0,
}
}
}
impl<'a> Iterator for RequestQueryFields<'a> {
type Item = &'a RequestField;
fn next(&mut self) -> Option<&'a RequestField> {
while let Some(value) = self.fields.get(self.index) {
self.index += 1;
if value.is_query() {
return Some(value);
}
}
None
}
}