Skip to content

Commit

Permalink
Add validation using validator crate
Browse files Browse the repository at this point in the history
  • Loading branch information
bikeshedder committed Sep 14, 2020
1 parent c25ae60 commit f5167b4
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/codegen/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn gen_struct(struct_: &schema::Struct) -> TokenStream {
let name = quote::format_ident!("{}", &struct_.fqtn.name);
let fields = gen_struct_fields(struct_);
quote! {
#[derive(Clone, Debug, Eq, PartialEq, ::serde::Serialize, ::serde::Deserialize)]
#[derive(Clone, Debug, Eq, PartialEq, ::serde::Serialize, ::serde::Deserialize, ::validator::Validate)]
pub struct #name {
#fields
}
Expand All @@ -115,11 +115,30 @@ fn gen_struct_field(field: &schema::Field) -> TokenStream {
if field.optional {
type_ = optional(type_);
}
let validation_macros = gen_validation_macros(field);
quote! {
#validation_macros
pub #name: #type_,
}
}

fn gen_validation_macros(field: &schema::Field) -> TokenStream {
let mut rules = TokenStream::new();
match field.length {
(Some(min), Some(max)) => rules.extend(quote! { length(min=#min, max=#max) }),
(Some(min), None) => rules.extend(quote! { length(min=#min) }),
(None, Some(max)) => rules.extend(quote! { length(max=#max) }),
(None, None) => {}
}
if rules.is_empty() {
quote! {}
} else {
quote! {
#[validate(#rules)]
}
}
}

fn gen_fieldset(fieldset: &schema::Fieldset) -> TokenStream {
let name = quote::format_ident!("{}", &fieldset.fqtn.name);
let fields = gen_fieldset_fields(fieldset);
Expand Down Expand Up @@ -240,18 +259,21 @@ fn gen_provider_matches(service: &schema::Service) -> TokenStream {
None => quote! { () },
};
*/
let deserialize_request = if method.input.is_none() {
quote! { ::bytes::Bytes::new() }
let method_call = if method.input.is_none() {
quote! {
let output = service.#name().await?;
}
} else {
quote! {
serde_json::from_slice::<#input>(&input)
.map_err(|e| ::webwire::ProviderError::DeserializerError(e))?;
let input = serde_json::from_slice::<#input>(&input)
.map_err(::webwire::ProviderError::DeserializerError)?;
::validator::Validate::validate(&input).map_err(::webwire::ProviderError::ValidationError)?;
let output = service.#name(&input).await?;
}
};
stream.extend(quote! {
#name_str => Box::pin(async move {
let input = #deserialize_request;
let output = service.#name(&input).await?;
#method_call
let response = serde_json::to_vec(&output)
.map_err(|e| ::webwire::ProviderError::SerializerError(e))
.map(::bytes::Bytes::from)?;
Expand Down
9 changes: 9 additions & 0 deletions src/schema/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct Field {
pub type_: Type,
pub optional: bool,
// FIXME add options
pub length: (Option<i64>, Option<i64>),
pub position: FilePosition,
}

Expand Down Expand Up @@ -47,12 +48,20 @@ impl Struct {

impl Field {
pub fn from_idl(ifield: &idl::Field, ns: &Namespace) -> Self {
let mut length: (Option<i64>, Option<i64>) = (None, None);
for option in &ifield.options {
match (option.name.as_str(), &option.value) {
("length", idl::Value::Range(min, max)) => length = (*min, *max),
(name, _) => panic!("Unsupported option: {}", name),
}
}
Field {
name: ifield.name.clone(),
type_: Type::from_idl(&ifield.type_, ns),
optional: ifield.optional,
// FIXME add options
//options: ifield.options
length,
position: ifield.position.clone(),
}
}
Expand Down

0 comments on commit f5167b4

Please sign in to comment.