Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions packages/fortifier-macros/src/validate/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
use convert_case::{Case, Casing};
use proc_macro2::{Literal, TokenStream};
use quote::{ToTokens, TokenStreamExt, format_ident, quote};
use syn::{DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident, Result};
use syn::{DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Generics, Ident, Result};

use crate::validate::field::ValidateField;

Expand Down Expand Up @@ -38,6 +38,7 @@ impl ToTokens for ValidateStruct {
pub struct ValidateNamedStruct {
ident: Ident,
error_ident: Ident,
generics: Generics,
fields: HashMap<Ident, ValidateField>,
}

Expand All @@ -46,6 +47,7 @@ impl ValidateNamedStruct {
let mut result = Self {
ident: input.ident.clone(),
error_ident: format_ident!("{}ValidationError", input.ident),
generics: input.generics.clone(),
fields: HashMap::default(),
};

Expand All @@ -70,6 +72,8 @@ impl ToTokens for ValidateNamedStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = &self.ident;
let error_ident = &self.error_ident;
let (impl_generics, type_generics, where_clause) = &self.generics.split_for_impl();

let mut error_field_idents = vec![];
let mut error_field_types = vec![];
let mut error_field_enums = vec![];
Expand Down Expand Up @@ -127,7 +131,7 @@ impl ToTokens for ValidateNamedStruct {
#(#error_field_enums)*

#[automatically_derived]
impl Validate for #ident {
impl #impl_generics Validate for #ident #type_generics #where_clause {
type Error = #error_ident;

fn validate_sync(&self) -> Result<(), ValidationErrors<Self::Error>> {
Expand Down Expand Up @@ -163,6 +167,7 @@ impl ToTokens for ValidateNamedStruct {
pub struct ValidateUnnamedStruct {
ident: Ident,
error_ident: Ident,
generics: Generics,
fields: Vec<ValidateField>,
}

Expand All @@ -171,6 +176,7 @@ impl ValidateUnnamedStruct {
let mut result = Self {
ident: input.ident.clone(),
error_ident: format_ident!("{}ValidationError", input.ident),
generics: input.generics.clone(),
fields: Vec::default(),
};

Expand All @@ -195,6 +201,8 @@ impl ToTokens for ValidateUnnamedStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = &self.ident;
let error_ident = &self.error_ident;
let (impl_generics, type_generics, where_clause) = &self.generics.split_for_impl();

let mut error_field_idents = vec![];
let mut error_field_types = vec![];
let mut error_field_enums = vec![];
Expand Down Expand Up @@ -251,7 +259,7 @@ impl ToTokens for ValidateUnnamedStruct {
#(#error_field_enums)*

#[automatically_derived]
impl Validate for #ident {
impl #impl_generics Validate for #ident #type_generics #where_clause {
type Error = #error_ident;

fn validate_sync(&self) -> Result<(), ValidationErrors<Self::Error>> {
Expand Down Expand Up @@ -286,25 +294,28 @@ impl ToTokens for ValidateUnnamedStruct {

pub struct ValidateUnitStruct {
ident: Ident,
generics: Generics,
}

impl ValidateUnitStruct {
fn parse(input: &DeriveInput) -> Result<Self> {
Ok(Self {
ident: input.ident.clone(),
generics: input.generics.clone(),
})
}
}

impl ToTokens for ValidateUnitStruct {
fn to_tokens(&self, tokens: &mut TokenStream) {
let ident = &self.ident;
let (impl_generics, type_generics, where_clause) = &self.generics.split_for_impl();

tokens.append_all(quote! {
use fortifier::ValidationErrors;

#[automatically_derived]
impl Validate for #ident {
impl #impl_generics Validate for #ident #type_generics #where_clause {
type Error = ::std::convert::Infallible;

fn validate_sync(&self) -> Result<(), ValidationErrors<Self::Error>> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::error::Error;

use fortifier::Validate;

#[derive(Validate)]
struct CreateUser<E: ValidateEmail, N: ValidateLength<usize>> {
#[validate(email)]
email: E,

#[validate(length(min = 1, max = 256))]
name: N,
}

fn main() -> Result<(), Box<dyn Error>> {
let data = CreateUser {
email: "john@doe.com",
name: "John Doe",
};

data.validate_sync()?;

Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::error::Error;

use fortifier::Validate;

#[derive(Validate)]
struct CreateUser<'a, 'b> {
#[validate(email)]
email: &'a str,

#[validate(length(min = 1, max = 256))]
name: &'b str,
}

fn main() -> Result<(), Box<dyn Error>> {
let data = CreateUser {
email: "john@doe.com",
name: "John Doe",
};

data.validate_sync()?;

Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std::error::Error;

use fortifier::Validate;

#[derive(Validate)]
struct CreateUser<N: ValidateLength<usize>>(#[validate(length(min = 1, max = 256))] N);

fn main() -> Result<(), Box<dyn Error>> {
let data = CreateUser("John Doe");

data.validate_sync()?;

Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std::error::Error;

use fortifier::Validate;

#[derive(Validate)]
struct CreateUser<'a>(#[validate(length(min = 1, max = 256))] &'a str);

fn main() -> Result<(), Box<dyn Error>> {
let data = CreateUser("John Doe");

data.validate_sync()?;

Ok(())
}