Skip to content

Commit 02e1579

Browse files
feat: support struct lifetimes and generics
1 parent afb392a commit 02e1579

5 files changed

Lines changed: 89 additions & 4 deletions

File tree

packages/fortifier-macros/src/validate/struct.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashMap;
33
use convert_case::{Case, Casing};
44
use proc_macro2::{Literal, TokenStream};
55
use quote::{ToTokens, TokenStreamExt, format_ident, quote};
6-
use syn::{DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident, Result};
6+
use syn::{DataStruct, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Generics, Ident, Result};
77

88
use crate::validate::field::ValidateField;
99

@@ -38,6 +38,7 @@ impl ToTokens for ValidateStruct {
3838
pub struct ValidateNamedStruct {
3939
ident: Ident,
4040
error_ident: Ident,
41+
generics: Generics,
4142
fields: HashMap<Ident, ValidateField>,
4243
}
4344

@@ -46,6 +47,7 @@ impl ValidateNamedStruct {
4647
let mut result = Self {
4748
ident: input.ident.clone(),
4849
error_ident: format_ident!("{}ValidationError", input.ident),
50+
generics: input.generics.clone(),
4951
fields: HashMap::default(),
5052
};
5153

@@ -70,6 +72,8 @@ impl ToTokens for ValidateNamedStruct {
7072
fn to_tokens(&self, tokens: &mut TokenStream) {
7173
let ident = &self.ident;
7274
let error_ident = &self.error_ident;
75+
let (impl_generics, type_generics, where_clause) = &self.generics.split_for_impl();
76+
7377
let mut error_field_idents = vec![];
7478
let mut error_field_types = vec![];
7579
let mut error_field_enums = vec![];
@@ -127,7 +131,7 @@ impl ToTokens for ValidateNamedStruct {
127131
#(#error_field_enums)*
128132

129133
#[automatically_derived]
130-
impl Validate for #ident {
134+
impl #impl_generics Validate for #ident #type_generics #where_clause {
131135
type Error = #error_ident;
132136

133137
fn validate_sync(&self) -> Result<(), ValidationErrors<Self::Error>> {
@@ -163,6 +167,7 @@ impl ToTokens for ValidateNamedStruct {
163167
pub struct ValidateUnnamedStruct {
164168
ident: Ident,
165169
error_ident: Ident,
170+
generics: Generics,
166171
fields: Vec<ValidateField>,
167172
}
168173

@@ -171,6 +176,7 @@ impl ValidateUnnamedStruct {
171176
let mut result = Self {
172177
ident: input.ident.clone(),
173178
error_ident: format_ident!("{}ValidationError", input.ident),
179+
generics: input.generics.clone(),
174180
fields: Vec::default(),
175181
};
176182

@@ -195,6 +201,8 @@ impl ToTokens for ValidateUnnamedStruct {
195201
fn to_tokens(&self, tokens: &mut TokenStream) {
196202
let ident = &self.ident;
197203
let error_ident = &self.error_ident;
204+
let (impl_generics, type_generics, where_clause) = &self.generics.split_for_impl();
205+
198206
let mut error_field_idents = vec![];
199207
let mut error_field_types = vec![];
200208
let mut error_field_enums = vec![];
@@ -251,7 +259,7 @@ impl ToTokens for ValidateUnnamedStruct {
251259
#(#error_field_enums)*
252260

253261
#[automatically_derived]
254-
impl Validate for #ident {
262+
impl #impl_generics Validate for #ident #type_generics #where_clause {
255263
type Error = #error_ident;
256264

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

287295
pub struct ValidateUnitStruct {
288296
ident: Ident,
297+
generics: Generics,
289298
}
290299

291300
impl ValidateUnitStruct {
292301
fn parse(input: &DeriveInput) -> Result<Self> {
293302
Ok(Self {
294303
ident: input.ident.clone(),
304+
generics: input.generics.clone(),
295305
})
296306
}
297307
}
298308

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

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

306317
#[automatically_derived]
307-
impl Validate for #ident {
318+
impl #impl_generics Validate for #ident #type_generics #where_clause {
308319
type Error = ::std::convert::Infallible;
309320

310321
fn validate_sync(&self) -> Result<(), ValidationErrors<Self::Error>> {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::error::Error;
2+
3+
use fortifier::Validate;
4+
5+
#[derive(Validate)]
6+
struct CreateUser<E: ValidateEmail, N: ValidateLength<usize>> {
7+
#[validate(email)]
8+
email: E,
9+
10+
#[validate(length(min = 1, max = 256))]
11+
name: N,
12+
}
13+
14+
fn main() -> Result<(), Box<dyn Error>> {
15+
let data = CreateUser {
16+
email: "john@doe.com",
17+
name: "John Doe",
18+
};
19+
20+
data.validate_sync()?;
21+
22+
Ok(())
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::error::Error;
2+
3+
use fortifier::Validate;
4+
5+
#[derive(Validate)]
6+
struct CreateUser<'a, 'b> {
7+
#[validate(email)]
8+
email: &'a str,
9+
10+
#[validate(length(min = 1, max = 256))]
11+
name: &'b str,
12+
}
13+
14+
fn main() -> Result<(), Box<dyn Error>> {
15+
let data = CreateUser {
16+
email: "john@doe.com",
17+
name: "John Doe",
18+
};
19+
20+
data.validate_sync()?;
21+
22+
Ok(())
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use std::error::Error;
2+
3+
use fortifier::Validate;
4+
5+
#[derive(Validate)]
6+
struct CreateUser<N: ValidateLength<usize>>(#[validate(length(min = 1, max = 256))] N);
7+
8+
fn main() -> Result<(), Box<dyn Error>> {
9+
let data = CreateUser("John Doe");
10+
11+
data.validate_sync()?;
12+
13+
Ok(())
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use std::error::Error;
2+
3+
use fortifier::Validate;
4+
5+
#[derive(Validate)]
6+
struct CreateUser<'a>(#[validate(length(min = 1, max = 256))] &'a str);
7+
8+
fn main() -> Result<(), Box<dyn Error>> {
9+
let data = CreateUser("John Doe");
10+
11+
data.validate_sync()?;
12+
13+
Ok(())
14+
}

0 commit comments

Comments
 (0)