From b08ff772826c179ad99945107192770d3cbb48cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABlle=20Huisman?= Date: Sun, 14 Dec 2025 16:58:12 +0100 Subject: [PATCH] refactor: rename email to email address --- benchmarks/compile/Cargo.toml | 2 +- book/src/SUMMARY.md | 2 +- book/src/getting-started.md | 10 +- book/src/installation.md | 3 +- book/src/introduction.md | 2 +- book/src/validations/README.md | 2 +- .../{email.md => email-address.md} | 12 +- examples/basic/Cargo.toml | 2 +- examples/basic/src/email_address.rs | 4 +- examples/basic/src/main.rs | 2 +- examples/basic/src/user.rs | 4 +- examples/server/Cargo.toml | 2 +- examples/server/src/user/schemas.rs | 2 +- .../fortifier-macros/src/validate/field.rs | 8 +- packages/fortifier-macros/src/validations.rs | 4 +- .../{email.rs => email_address.rs} | 16 +- .../tests/validate/enum_named_pass.rs | 4 +- .../tests/validate/enum_unnamed_pass.rs | 4 +- .../validate/struct_named_generics_pass.rs | 10 +- .../validate/struct_named_lifetimes_pass.rs | 6 +- .../tests/validate/struct_named_pass.rs | 6 +- .../invalid_allow_display_text_fail.rs | 9 + .../invalid_allow_display_text_fail.stderr | 5 + .../invalid_allow_domain_literal_fail.rs | 9 + .../invalid_allow_domain_literal_fail.stderr | 5 + .../invalid_minimum_sub_domains_fail.rs | 9 + .../invalid_minimum_sub_domains_fail.stderr | 5 + .../validations/email-address/types_pass.rs | 35 ++++ .../{email => email-address}/unknown_fail.rs | 4 +- .../email-address/unknown_fail.stderr | 5 + .../email/invalid_allow_display_text_fail.rs | 9 - .../invalid_allow_display_text_fail.stderr | 5 - .../invalid_allow_domain_literal_fail.rs | 9 - .../invalid_allow_domain_literal_fail.stderr | 5 - .../email/invalid_minimum_sub_domains_fail.rs | 9 - .../invalid_minimum_sub_domains_fail.stderr | 5 - .../tests/validations/email/types_pass.rs | 31 --- .../validations/email/unknown_fail.stderr | 5 - packages/fortifier/Cargo.toml | 4 +- packages/fortifier/src/validations.rs | 8 +- .../{email.rs => email_address.rs} | 183 +++++++++++------- packages/fortifier/tests/serde.rs | 12 +- 42 files changed, 266 insertions(+), 212 deletions(-) rename book/src/validations/{email.md => email-address.md} (91%) rename packages/fortifier-macros/src/validations/{email.rs => email_address.rs} (85%) create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.rs create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.stderr create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.rs create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.stderr create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.rs create mode 100644 packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.stderr create mode 100644 packages/fortifier-macros/tests/validations/email-address/types_pass.rs rename packages/fortifier-macros/tests/validations/{email => email-address}/unknown_fail.rs (51%) create mode 100644 packages/fortifier-macros/tests/validations/email-address/unknown_fail.stderr delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.rs delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.stderr delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.rs delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.stderr delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.rs delete mode 100644 packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.stderr delete mode 100644 packages/fortifier-macros/tests/validations/email/types_pass.rs delete mode 100644 packages/fortifier-macros/tests/validations/email/unknown_fail.stderr rename packages/fortifier/src/validations/{email.rs => email_address.rs} (63%) diff --git a/benchmarks/compile/Cargo.toml b/benchmarks/compile/Cargo.toml index e817f14..19bf443 100644 --- a/benchmarks/compile/Cargo.toml +++ b/benchmarks/compile/Cargo.toml @@ -17,7 +17,7 @@ validator = ["dep:validator"] [dependencies] fortifier = { workspace = true, features = [ - "email", + "email-address", "serde", "url", ], optional = true } diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index f8bc154..f2d282a 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -7,7 +7,7 @@ - [Enum](./validate/enum.md) - [Struct](./validate/struct.md) - [Validations](./validations/README.md) - - [Email](./validations/email.md) + - [Email Address](./validations/email-address.md) - [Length](./validations/length.md) - [Phone Number](./validations/phone-number.md) - [Regex]() diff --git a/book/src/getting-started.md b/book/src/getting-started.md index 9828a92..88c58eb 100644 --- a/book/src/getting-started.md +++ b/book/src/getting-started.md @@ -5,7 +5,7 @@ Add Fortifier to your project: ```shell -cargo add fortifier --features email +cargo add fortifier --features email-address ``` See [Installation](installation.md) for more details. @@ -46,7 +46,7 @@ use fortifier::Validate; #[derive(Validate)] struct CreateUser { - #[validate(email)] + #[validate(email_address)] email_address: String, #[validate(length(min = 1, max = 256))] @@ -62,11 +62,11 @@ Call the `validate_sync` method on the data structure: ```rust # extern crate fortifier; -use fortifier::{EmailError, LengthError, Validate, ValidationErrors}; +use fortifier::{EmailAddressError, LengthError, Validate, ValidationErrors}; #[derive(Validate)] struct CreateUser { - #[validate(email)] + #[validate(email_address)] email_address: String, #[validate(length(min = 1, max = 256))] @@ -90,7 +90,7 @@ fn main() { data.validate_sync(), Err(ValidationErrors::from_iter([ CreateUserValidationError::EmailAddress( - EmailError::MissingSeparator {}, + EmailAddressError::MissingSeparator {}, ), CreateUserValidationError::Name( LengthError::Min { diff --git a/book/src/installation.md b/book/src/installation.md index 2da7d4e..4bfa7d8 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -22,7 +22,8 @@ cargo add fortifier ### Validations - `all-validations` - Enable all features below. -- `email` - Email address validation using the [`email_address`](https://docs.rs/email_address/latest/email_address/) crate. +- `email-address` - Email address validation using the [`email_address`](https://docs.rs/email_address/latest/email_address/) crate. +- `phone-number` - Phone number validation using the [`phonenumber`](https://docs.rs/phonenumber/latest/phonenumber/) crate. - `regex` - Regular expression validation using the [`regex`](https://docs.rs/regex/latest/regex/) crate. - `url` - URL validation using the [`url`](https://docs.rs/url/latest/url/) crate. diff --git a/book/src/introduction.md b/book/src/introduction.md index c3a811d..54127ae 100644 --- a/book/src/introduction.md +++ b/book/src/introduction.md @@ -6,7 +6,7 @@ Schema validation. - Enums & structs - Typed errors - Built-in validations - - Email + - Email address - Length - Phone number - Regex diff --git a/book/src/validations/README.md b/book/src/validations/README.md index eb96cf6..7053418 100644 --- a/book/src/validations/README.md +++ b/book/src/validations/README.md @@ -1,6 +1,6 @@ # Validations -- [Email](./email.md) +- [Email Address](./email-address.md) - [Length](./length.md) - [Phone Number](./phone-number.md) - [URL](./url.md) diff --git a/book/src/validations/email.md b/book/src/validations/email-address.md similarity index 91% rename from book/src/validations/email.md rename to book/src/validations/email-address.md index b5df3ba..4641e53 100644 --- a/book/src/validations/email.md +++ b/book/src/validations/email-address.md @@ -1,7 +1,7 @@ -# Email +# Email Address > [!NOTE] -> Requires the `email` feature. +> Requires the `email-address` feature. Validate a string is an RFC-compliant email address using the [`email_address`](https://docs.rs/email_address/latest/email_address/) crate. @@ -11,7 +11,7 @@ Validate a string is an RFC-compliant email address using the [`email_address`]( # ##[derive(Validate)] struct User { - #[validate(email)] + #[validate(email_address)] email_address: String } ``` @@ -47,7 +47,7 @@ See [`Options::allow_display_text`](https://docs.rs/email_address/latest/email_a # ##[derive(Validate)] struct User<'a> { - #[validate(email(allow_display_text = false))] + #[validate(email_address(allow_display_text = false))] email_address: &'a str } @@ -76,7 +76,7 @@ See [`Options::allow_domain_literal`](https://docs.rs/email_address/latest/email # ##[derive(Validate)] struct User<'a> { - #[validate(email(allow_domain_literal = false))] + #[validate(email_address(allow_domain_literal = false))] email_address: &'a str } @@ -105,7 +105,7 @@ See [`Options::minimum_sub_domains`](https://docs.rs/email_address/latest/email_ # ##[derive(Validate)] struct User<'a> { - #[validate(email(minimum_sub_domains = 2))] + #[validate(email_address(minimum_sub_domains = 2))] email_address: &'a str } diff --git a/examples/basic/Cargo.toml b/examples/basic/Cargo.toml index 22f6806..71cdbda 100644 --- a/examples/basic/Cargo.toml +++ b/examples/basic/Cargo.toml @@ -10,7 +10,7 @@ version.workspace = true [dependencies] fortifier = { workspace = true, features = [ - "email", + "email-address", "phone-number", "regex", "url", diff --git a/examples/basic/src/email_address.rs b/examples/basic/src/email_address.rs index 9c2a8fc..b6052a0 100644 --- a/examples/basic/src/email_address.rs +++ b/examples/basic/src/email_address.rs @@ -3,13 +3,13 @@ use fortifier::Validate; #[derive(Validate)] pub enum ChangeEmailAddressRelation { Create { - #[validate(email)] + #[validate(email_address)] email_address: String, }, Update { id: String, - #[validate(email)] + #[validate(email_address)] email_address: String, }, Delete { diff --git a/examples/basic/src/main.rs b/examples/basic/src/main.rs index b857151..fcfc30d 100644 --- a/examples/basic/src/main.rs +++ b/examples/basic/src/main.rs @@ -11,7 +11,7 @@ use crate::{email_address::ChangeEmailAddressRelation, user::CreateUser}; async fn main() -> Result<(), Box> { let data = CreateUser { name: "John Doe".to_owned(), - email: "john@doe.com".to_owned(), + email_address: "john@doe.com".to_owned(), phone_number: "+44 20 7946 0000".to_owned(), url: "https://john.doe.com".to_owned(), country_code: "GB".to_owned(), diff --git a/examples/basic/src/user.rs b/examples/basic/src/user.rs index 6fc2e2b..af5b1e2 100644 --- a/examples/basic/src/user.rs +++ b/examples/basic/src/user.rs @@ -11,8 +11,8 @@ pub struct CreateUser { #[validate(length(min = 1, max = 256))] pub name: String, - #[validate(email)] - pub email: String, + #[validate(email_address)] + pub email_address: String, #[validate(phone_number)] pub phone_number: String, diff --git a/examples/server/Cargo.toml b/examples/server/Cargo.toml index d54ff8d..5f1121b 100644 --- a/examples/server/Cargo.toml +++ b/examples/server/Cargo.toml @@ -11,7 +11,7 @@ version.workspace = true [dependencies] axum = "0.8.7" fortifier = { workspace = true, features = [ - "email", + "email-address", "regex", "serde", "url", diff --git a/examples/server/src/user/schemas.rs b/examples/server/src/user/schemas.rs index 6876fe3..cb12bd8 100644 --- a/examples/server/src/user/schemas.rs +++ b/examples/server/src/user/schemas.rs @@ -4,7 +4,7 @@ use utoipa::ToSchema; #[derive(Deserialize, ToSchema, Validate)] pub struct CreateUser { - #[validate(email)] + #[validate(email_address)] pub email_address: String, #[validate(length(min = 1, max = 256))] diff --git a/packages/fortifier-macros/src/validate/field.rs b/packages/fortifier-macros/src/validate/field.rs index b37ecf1..8aa3f97 100644 --- a/packages/fortifier-macros/src/validate/field.rs +++ b/packages/fortifier-macros/src/validate/field.rs @@ -6,7 +6,7 @@ use syn::{Field, Ident, Result, Visibility}; use crate::{ validate::{attributes::enum_attributes, r#type::should_validate_type}, validation::{Execution, Validation}, - validations::{Custom, Email, Length, Nested, PhoneNumber, Regex, Url}, + validations::{Custom, EmailAddress, Length, Nested, PhoneNumber, Regex, Url}, }; pub enum LiteralOrIdent { @@ -67,8 +67,10 @@ impl<'a> ValidateField<'a> { result.validations.push(Box::new(Custom::parse(&meta)?)); Ok(()) - } else if meta.path.is_ident("email") { - result.validations.push(Box::new(Email::parse(&meta)?)); + } else if meta.path.is_ident("email_address") { + result + .validations + .push(Box::new(EmailAddress::parse(&meta)?)); Ok(()) } else if meta.path.is_ident("length") { diff --git a/packages/fortifier-macros/src/validations.rs b/packages/fortifier-macros/src/validations.rs index 7ac870e..3dfb1bb 100644 --- a/packages/fortifier-macros/src/validations.rs +++ b/packages/fortifier-macros/src/validations.rs @@ -1,5 +1,5 @@ mod custom; -mod email; +mod email_address; mod length; mod nested; mod phone_number; @@ -7,7 +7,7 @@ mod regex; mod url; pub use custom::*; -pub use email::*; +pub use email_address::*; pub use length::*; pub use nested::*; pub use phone_number::*; diff --git a/packages/fortifier-macros/src/validations/email.rs b/packages/fortifier-macros/src/validations/email_address.rs similarity index 85% rename from packages/fortifier-macros/src/validations/email.rs rename to packages/fortifier-macros/src/validations/email_address.rs index 66255e8..67d9698 100644 --- a/packages/fortifier-macros/src/validations/email.rs +++ b/packages/fortifier-macros/src/validations/email_address.rs @@ -4,13 +4,13 @@ use syn::{Ident, LitBool, LitInt, Result, meta::ParseNestedMeta}; use crate::validation::{Execution, Validation}; -pub struct Email { +pub struct EmailAddress { allow_display_text: bool, allow_domain_literal: bool, minimum_sub_domains: usize, } -impl Default for Email { +impl Default for EmailAddress { fn default() -> Self { Self { allow_display_text: false, @@ -20,9 +20,9 @@ impl Default for Email { } } -impl Validation for Email { +impl Validation for EmailAddress { fn parse(meta: &ParseNestedMeta<'_>) -> Result { - let mut result = Email::default(); + let mut result = EmailAddress::default(); if !meta.input.is_empty() { meta.parse_nested_meta(|meta| { @@ -51,10 +51,10 @@ impl Validation for Email { } fn ident(&self) -> Ident { - format_ident!("Email") + format_ident!("EmailAddress") } fn error_type(&self) -> TokenStream { - quote!(::fortifier::EmailError) + quote!(::fortifier::EmailAddressError) } fn expr(&self, execution: Execution, expr: &TokenStream) -> Option { @@ -66,13 +66,13 @@ impl Validation for Email { Some(quote! { { - const EMAIL_ADDRESS_OPTIONS: ::fortifier::EmailOptions = ::fortifier::EmailOptions { + const EMAIL_ADDRESS_OPTIONS: ::fortifier::EmailAddressOptions = ::fortifier::EmailAddressOptions { allow_display_text: #allow_display_text, allow_domain_literal: #allow_domain_literal, minimum_sub_domains: #minimum_sub_domains, }; - ::fortifier::ValidateEmail::validate_email(&#expr, EMAIL_ADDRESS_OPTIONS) + ::fortifier::ValidateEmailAddress::validate_email_address(&#expr, EMAIL_ADDRESS_OPTIONS) } }) } diff --git a/packages/fortifier-macros/tests/validate/enum_named_pass.rs b/packages/fortifier-macros/tests/validate/enum_named_pass.rs index 93fb43e..24d2fdc 100644 --- a/packages/fortifier-macros/tests/validate/enum_named_pass.rs +++ b/packages/fortifier-macros/tests/validate/enum_named_pass.rs @@ -3,13 +3,13 @@ use fortifier::{Validate, ValidationErrors}; #[derive(Validate)] enum ChangeEmailAddressRelation { Create { - #[validate(email)] + #[validate(email_address)] email_address: String, }, Update { id: String, - #[validate(email)] + #[validate(email_address)] email_address: String, }, Delete { diff --git a/packages/fortifier-macros/tests/validate/enum_unnamed_pass.rs b/packages/fortifier-macros/tests/validate/enum_unnamed_pass.rs index 976a4c4..2f225ce 100644 --- a/packages/fortifier-macros/tests/validate/enum_unnamed_pass.rs +++ b/packages/fortifier-macros/tests/validate/enum_unnamed_pass.rs @@ -2,8 +2,8 @@ use fortifier::{Validate, ValidationErrors}; #[derive(Validate)] enum ChangeEmailAddressRelation { - Create(#[validate(email)] String), - Update(String, #[validate(email)] String), + Create(#[validate(email_address)] String), + Update(String, #[validate(email_address)] String), Delete(String), } diff --git a/packages/fortifier-macros/tests/validate/struct_named_generics_pass.rs b/packages/fortifier-macros/tests/validate/struct_named_generics_pass.rs index a5d3e25..1c7b398 100644 --- a/packages/fortifier-macros/tests/validate/struct_named_generics_pass.rs +++ b/packages/fortifier-macros/tests/validate/struct_named_generics_pass.rs @@ -1,9 +1,9 @@ -use fortifier::{Validate, ValidateEmail, ValidateLength, ValidationErrors}; +use fortifier::{Validate, ValidateEmailAddress, ValidateLength, ValidationErrors}; #[derive(Validate)] -struct CreateUser> { - #[validate(email)] - email: E, +struct CreateUser> { + #[validate(email_address)] + email_address: E, #[validate(length(min = 1, max = 256))] name: N, @@ -11,7 +11,7 @@ struct CreateUser> { fn main() -> Result<(), ValidationErrors> { let data = CreateUser { - email: "john@doe.com", + email_address: "john@doe.com", name: "John Doe", }; diff --git a/packages/fortifier-macros/tests/validate/struct_named_lifetimes_pass.rs b/packages/fortifier-macros/tests/validate/struct_named_lifetimes_pass.rs index b0a452c..ae3615c 100644 --- a/packages/fortifier-macros/tests/validate/struct_named_lifetimes_pass.rs +++ b/packages/fortifier-macros/tests/validate/struct_named_lifetimes_pass.rs @@ -2,8 +2,8 @@ use fortifier::{Validate, ValidationErrors}; #[derive(Validate)] struct CreateUser<'a, 'b> { - #[validate(email)] - email: &'a str, + #[validate(email_address)] + email_address: &'a str, #[validate(length(min = 1, max = 256))] name: &'b str, @@ -11,7 +11,7 @@ struct CreateUser<'a, 'b> { fn main() -> Result<(), ValidationErrors> { let data = CreateUser { - email: "john@doe.com", + email_address: "john@doe.com", name: "John Doe", }; diff --git a/packages/fortifier-macros/tests/validate/struct_named_pass.rs b/packages/fortifier-macros/tests/validate/struct_named_pass.rs index 621edcb..b162dee 100644 --- a/packages/fortifier-macros/tests/validate/struct_named_pass.rs +++ b/packages/fortifier-macros/tests/validate/struct_named_pass.rs @@ -2,8 +2,8 @@ use fortifier::{Validate, ValidationErrors}; #[derive(Validate)] struct CreateUser { - #[validate(email)] - email: String, + #[validate(email_address)] + email_address: String, #[validate(length(min = 1, max = 256))] name: String, @@ -11,7 +11,7 @@ struct CreateUser { fn main() -> Result<(), ValidationErrors> { let data = CreateUser { - email: "john@doe.com".to_owned(), + email_address: "john@doe.com".to_owned(), name: "John Doe".to_owned(), }; diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.rs b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.rs new file mode 100644 index 0000000..3454839 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.rs @@ -0,0 +1,9 @@ +use fortifier::Validate; + +#[derive(Validate)] +struct EmailAddressData<'a> { + #[validate(email_address(allow_display_text = 1))] + value: &'a str, +} + +fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.stderr b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.stderr new file mode 100644 index 0000000..55c67fd --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_display_text_fail.stderr @@ -0,0 +1,5 @@ +error: expected boolean literal + --> tests/validations/email-address/invalid_allow_display_text_fail.rs:5:51 + | +5 | #[validate(email_address(allow_display_text = 1))] + | ^ diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.rs b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.rs new file mode 100644 index 0000000..be61569 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.rs @@ -0,0 +1,9 @@ +use fortifier::Validate; + +#[derive(Validate)] +struct EmailAddressData<'a> { + #[validate(email_address(allow_domain_literal = 1))] + value: &'a str, +} + +fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.stderr b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.stderr new file mode 100644 index 0000000..6088c45 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_allow_domain_literal_fail.stderr @@ -0,0 +1,5 @@ +error: expected boolean literal + --> tests/validations/email-address/invalid_allow_domain_literal_fail.rs:5:53 + | +5 | #[validate(email_address(allow_domain_literal = 1))] + | ^ diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.rs b/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.rs new file mode 100644 index 0000000..f2149ac --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.rs @@ -0,0 +1,9 @@ +use fortifier::Validate; + +#[derive(Validate)] +struct EmailAddressData<'a> { + #[validate(email_address(minimum_sub_domains = -1))] + value: &'a str, +} + +fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.stderr b/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.stderr new file mode 100644 index 0000000..b532029 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/invalid_minimum_sub_domains_fail.stderr @@ -0,0 +1,5 @@ +error: invalid digit found in string + --> tests/validations/email-address/invalid_minimum_sub_domains_fail.rs:5:52 + | +5 | #[validate(email_address(minimum_sub_domains = -1))] + | ^ diff --git a/packages/fortifier-macros/tests/validations/email-address/types_pass.rs b/packages/fortifier-macros/tests/validations/email-address/types_pass.rs new file mode 100644 index 0000000..06c0510 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/types_pass.rs @@ -0,0 +1,35 @@ +use email_address::EmailAddress; +use fortifier::{EmailAddressError, Validate, ValidationErrors}; + +#[derive(Validate)] +struct EmailAddressData<'a> { + #[validate(email_address)] + r#str: &'a str, + #[validate(email_address)] + string: String, + #[validate(email_address)] + email_address: EmailAddress, +} + +fn main() { + let data = EmailAddressData { + r#str: "admin", + string: "admin@".to_owned(), + email_address: EmailAddress::new_unchecked("Admin "), + }; + + assert_eq!( + data.validate_sync(), + Err(ValidationErrors::from_iter([ + EmailAddressDataValidationError::Str(EmailAddressError::from( + email_address::Error::MissingSeparator + )), + EmailAddressDataValidationError::String(EmailAddressError::from( + email_address::Error::DomainEmpty + )), + EmailAddressDataValidationError::EmailAddress(EmailAddressError::from( + email_address::Error::UnsupportedDisplayName + )), + ])) + ); +} diff --git a/packages/fortifier-macros/tests/validations/email/unknown_fail.rs b/packages/fortifier-macros/tests/validations/email-address/unknown_fail.rs similarity index 51% rename from packages/fortifier-macros/tests/validations/email/unknown_fail.rs rename to packages/fortifier-macros/tests/validations/email-address/unknown_fail.rs index 8e92e97..0990016 100644 --- a/packages/fortifier-macros/tests/validations/email/unknown_fail.rs +++ b/packages/fortifier-macros/tests/validations/email-address/unknown_fail.rs @@ -1,8 +1,8 @@ use fortifier::Validate; #[derive(Validate)] -struct EmailData<'a> { - #[validate(email(unknown = true))] +struct EmailAddressData<'a> { + #[validate(email_address(unknown = true))] value: &'a str, } diff --git a/packages/fortifier-macros/tests/validations/email-address/unknown_fail.stderr b/packages/fortifier-macros/tests/validations/email-address/unknown_fail.stderr new file mode 100644 index 0000000..c2d3543 --- /dev/null +++ b/packages/fortifier-macros/tests/validations/email-address/unknown_fail.stderr @@ -0,0 +1,5 @@ +error: unknown parameter + --> tests/validations/email-address/unknown_fail.rs:5:30 + | +5 | #[validate(email_address(unknown = true))] + | ^^^^^^^ diff --git a/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.rs b/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.rs deleted file mode 100644 index 4e9b1be..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.rs +++ /dev/null @@ -1,9 +0,0 @@ -use fortifier::Validate; - -#[derive(Validate)] -struct EmailData<'a> { - #[validate(email(allow_display_text = 1))] - value: &'a str, -} - -fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.stderr b/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.stderr deleted file mode 100644 index 59a4d2b..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_allow_display_text_fail.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected boolean literal - --> tests/validations/email/invalid_allow_display_text_fail.rs:5:43 - | -5 | #[validate(email(allow_display_text = 1))] - | ^ diff --git a/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.rs b/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.rs deleted file mode 100644 index f7a06cc..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.rs +++ /dev/null @@ -1,9 +0,0 @@ -use fortifier::Validate; - -#[derive(Validate)] -struct EmailData<'a> { - #[validate(email(allow_domain_literal = 1))] - value: &'a str, -} - -fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.stderr b/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.stderr deleted file mode 100644 index a3c7ea9..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_allow_domain_literal_fail.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expected boolean literal - --> tests/validations/email/invalid_allow_domain_literal_fail.rs:5:45 - | -5 | #[validate(email(allow_domain_literal = 1))] - | ^ diff --git a/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.rs b/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.rs deleted file mode 100644 index b858e5a..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.rs +++ /dev/null @@ -1,9 +0,0 @@ -use fortifier::Validate; - -#[derive(Validate)] -struct EmailData<'a> { - #[validate(email(minimum_sub_domains = -1))] - value: &'a str, -} - -fn main() {} diff --git a/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.stderr b/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.stderr deleted file mode 100644 index c2a35c1..0000000 --- a/packages/fortifier-macros/tests/validations/email/invalid_minimum_sub_domains_fail.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: invalid digit found in string - --> tests/validations/email/invalid_minimum_sub_domains_fail.rs:5:44 - | -5 | #[validate(email(minimum_sub_domains = -1))] - | ^ diff --git a/packages/fortifier-macros/tests/validations/email/types_pass.rs b/packages/fortifier-macros/tests/validations/email/types_pass.rs deleted file mode 100644 index 5ac8c9a..0000000 --- a/packages/fortifier-macros/tests/validations/email/types_pass.rs +++ /dev/null @@ -1,31 +0,0 @@ -use email_address::EmailAddress; -use fortifier::{EmailError, Validate, ValidationErrors}; - -#[derive(Validate)] -struct EmailData<'a> { - #[validate(email)] - r#str: &'a str, - #[validate(email)] - string: String, - #[validate(email)] - email_address: EmailAddress, -} - -fn main() { - let data = EmailData { - r#str: "admin", - string: "admin@".to_owned(), - email_address: EmailAddress::new_unchecked("Admin "), - }; - - assert_eq!( - data.validate_sync(), - Err(ValidationErrors::from_iter([ - EmailDataValidationError::Str(EmailError::from(email_address::Error::MissingSeparator)), - EmailDataValidationError::String(EmailError::from(email_address::Error::DomainEmpty)), - EmailDataValidationError::EmailAddress(EmailError::from( - email_address::Error::UnsupportedDisplayName - )), - ])) - ); -} diff --git a/packages/fortifier-macros/tests/validations/email/unknown_fail.stderr b/packages/fortifier-macros/tests/validations/email/unknown_fail.stderr deleted file mode 100644 index 7606e2c..0000000 --- a/packages/fortifier-macros/tests/validations/email/unknown_fail.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: unknown parameter - --> tests/validations/email/unknown_fail.rs:5:22 - | -5 | #[validate(email(unknown = true))] - | ^^^^^^^ diff --git a/packages/fortifier/Cargo.toml b/packages/fortifier/Cargo.toml index f69cfc4..be706dd 100644 --- a/packages/fortifier/Cargo.toml +++ b/packages/fortifier/Cargo.toml @@ -13,8 +13,8 @@ all-features = true [features] default = ["macros"] -all-validations = ["email", "phone-number", "regex", "url"] -email = ["dep:email_address"] +all-validations = ["email-address", "phone-number", "regex", "url"] +email-address = ["dep:email_address"] indexmap = ["dep:indexmap"] macros = ["dep:fortifier-macros"] message = [] diff --git a/packages/fortifier/src/validations.rs b/packages/fortifier/src/validations.rs index f1f9509..9dcbc97 100644 --- a/packages/fortifier/src/validations.rs +++ b/packages/fortifier/src/validations.rs @@ -1,5 +1,5 @@ -#[cfg(feature = "email")] -mod email; +#[cfg(feature = "email-address")] +mod email_address; mod length; #[cfg(feature = "phone-number")] mod phone_number; @@ -8,8 +8,8 @@ mod regex; #[cfg(feature = "url")] mod url; -#[cfg(feature = "email")] -pub use email::*; +#[cfg(feature = "email-address")] +pub use email_address::*; pub use length::*; #[cfg(feature = "phone-number")] pub use phone_number::*; diff --git a/packages/fortifier/src/validations/email.rs b/packages/fortifier/src/validations/email_address.rs similarity index 63% rename from packages/fortifier/src/validations/email.rs rename to packages/fortifier/src/validations/email_address.rs index ad27091..63aa54a 100644 --- a/packages/fortifier/src/validations/email.rs +++ b/packages/fortifier/src/validations/email_address.rs @@ -6,7 +6,7 @@ use std::{ }; use email_address::EmailAddress; -pub use email_address::Options as EmailOptions; +pub use email_address::Options as EmailAddressOptions; /// Email validation error. #[derive(Debug, Eq, PartialEq)] @@ -20,7 +20,7 @@ pub use email_address::Options as EmailOptions; ) )] #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] -pub enum EmailError { +pub enum EmailAddressError { /// Invalid character error. InvalidCharacter { /// A human-readable error message. @@ -125,7 +125,7 @@ pub enum EmailError { }, } -impl From for EmailError { +impl From for EmailAddressError { fn from(value: email_address::Error) -> Self { match value { email_address::Error::InvalidCharacter => Self::InvalidCharacter { @@ -201,59 +201,63 @@ impl From for EmailError { } /// Validate an email address. -pub trait ValidateEmail { +pub trait ValidateEmailAddress { /// The email address. - fn email(&self) -> Option>; + fn email_address(&self) -> Option>; /// Validate email address. - fn validate_email(&self, options: EmailOptions) -> Result<(), EmailError> { - let Some(email) = self.email() else { + fn validate_email_address( + &self, + options: EmailAddressOptions, + ) -> Result<(), EmailAddressError> { + let Some(email_address) = self.email_address() else { return Ok(()); }; - EmailAddress::parse_with_options(&email, options).map_err(EmailError::from)?; + EmailAddress::parse_with_options(&email_address, options) + .map_err(EmailAddressError::from)?; Ok(()) } } -impl ValidateEmail for str { - fn email(&self) -> Option> { +impl ValidateEmailAddress for str { + fn email_address(&self) -> Option> { Some(self.into()) } } -impl ValidateEmail for &str { - fn email(&self) -> Option> { +impl ValidateEmailAddress for &str { + fn email_address(&self) -> Option> { Some((*self).into()) } } -impl ValidateEmail for String { - fn email(&self) -> Option> { +impl ValidateEmailAddress for String { + fn email_address(&self) -> Option> { Some(self.into()) } } -impl ValidateEmail for Cow<'_, str> { - fn email(&self) -> Option> { +impl ValidateEmailAddress for Cow<'_, str> { + fn email_address(&self) -> Option> { Some(self.clone()) } } -impl ValidateEmail for EmailAddress { - fn email(&self) -> Option> { +impl ValidateEmailAddress for EmailAddress { + fn email_address(&self) -> Option> { Some(self.as_str().into()) } } -impl ValidateEmail for Option +impl ValidateEmailAddress for Option where - T: ValidateEmail, + T: ValidateEmailAddress, { - fn email(&self) -> Option> { + fn email_address(&self) -> Option> { if let Some(s) = self { - T::email(s) + T::email_address(s) } else { None } @@ -262,12 +266,12 @@ where macro_rules! validate_with_deref { ($type:ty) => { - impl ValidateEmail for $type + impl ValidateEmailAddress for $type where - T: ValidateEmail, + T: ValidateEmailAddress, { - fn email(&self) -> Option> { - T::email(self) + fn email_address(&self) -> Option> { + T::email_address(self) } } }; @@ -286,106 +290,147 @@ mod tests { use email_address::EmailAddress; - use super::{EmailError, EmailOptions, ValidateEmail}; + use super::{EmailAddressError, EmailAddressOptions, ValidateEmailAddress}; #[test] fn ok() { - let options = EmailOptions::default().without_display_text(); + let options = EmailAddressOptions::default().without_display_text(); - assert_eq!((*"admin@localhost").validate_email(options), Ok(())); - assert_eq!("admin@localhost".validate_email(options), Ok(())); - assert_eq!("admin@localhost".to_owned().validate_email(options), Ok(())); + assert_eq!((*"admin@localhost").validate_email_address(options), Ok(())); + assert_eq!("admin@localhost".validate_email_address(options), Ok(())); assert_eq!( - Cow::::Borrowed("admin@localhost").validate_email(options), + "admin@localhost".to_owned().validate_email_address(options), Ok(()) ); assert_eq!( - Cow::::Owned("admin@localhost".to_owned()).validate_email(options), + Cow::::Borrowed("admin@localhost").validate_email_address(options), Ok(()) ); assert_eq!( - EmailAddress::new_unchecked("admin@localhost").validate_email(options), + Cow::::Owned("admin@localhost".to_owned()).validate_email_address(options), + Ok(()) + ); + assert_eq!( + EmailAddress::new_unchecked("admin@localhost").validate_email_address(options), Ok(()) ); - assert_eq!(None::<&str>.validate_email(options), Ok(())); - assert_eq!(Some("admin@localhost").validate_email(options), Ok(())); + assert_eq!(None::<&str>.validate_email_address(options), Ok(())); + assert_eq!( + Some("admin@localhost").validate_email_address(options), + Ok(()) + ); - assert_eq!((&"admin@localhost").validate_email(options), Ok(())); + assert_eq!((&"admin@localhost").validate_email_address(options), Ok(())); #[expect(unused_allocation)] { - assert_eq!(Box::new("admin@localhost").validate_email(options), Ok(())); + assert_eq!( + Box::new("admin@localhost").validate_email_address(options), + Ok(()) + ); } - assert_eq!(Arc::new("admin@localhost").validate_email(options), Ok(())); - assert_eq!(Rc::new("admin@localhost").validate_email(options), Ok(())); + assert_eq!( + Arc::new("admin@localhost").validate_email_address(options), + Ok(()) + ); + assert_eq!( + Rc::new("admin@localhost").validate_email_address(options), + Ok(()) + ); let cell = RefCell::new("admin@localhost"); - assert_eq!(cell.borrow().validate_email(options), Ok(())); - assert_eq!(cell.borrow_mut().validate_email(options), Ok(())); + assert_eq!(cell.borrow().validate_email_address(options), Ok(())); + assert_eq!(cell.borrow_mut().validate_email_address(options), Ok(())); } #[test] fn invalid_error() { - let options = EmailOptions::default().without_display_text(); + let options = EmailAddressOptions::default().without_display_text(); assert_eq!( - (*"admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + (*"admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - "admin".validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + "admin".validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - "admin".to_owned().validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + "admin".to_owned().validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - Cow::::Borrowed("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Cow::::Borrowed("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - Cow::::Owned("admin".to_owned()).validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Cow::::Owned("admin".to_owned()).validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - EmailAddress::new_unchecked("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + EmailAddress::new_unchecked("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - Some("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Some("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - (&"admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + (&"admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); #[expect(unused_allocation)] { assert_eq!( - Box::new("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Box::new("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); } assert_eq!( - Arc::new("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Arc::new("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - Rc::new("admin").validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + Rc::new("admin").validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); let cell = RefCell::new("admin"); assert_eq!( - cell.borrow().validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + cell.borrow().validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); assert_eq!( - cell.borrow_mut().validate_email(options), - Err(EmailError::from(email_address::Error::MissingSeparator)) + cell.borrow_mut().validate_email_address(options), + Err(EmailAddressError::from( + email_address::Error::MissingSeparator + )) ); } } diff --git a/packages/fortifier/tests/serde.rs b/packages/fortifier/tests/serde.rs index 41dab99..779721f 100644 --- a/packages/fortifier/tests/serde.rs +++ b/packages/fortifier/tests/serde.rs @@ -1,6 +1,6 @@ #![cfg(feature = "serde")] -use fortifier::{EmailError, LengthError, RegexError, UrlError, ValidationErrors}; +use fortifier::{EmailAddressError, LengthError, RegexError, UrlError, ValidationErrors}; use pretty_assertions::assert_eq; use serde::{Deserialize, Serialize}; use serde_json::{Value, json}; @@ -9,7 +9,7 @@ use url::ParseError; #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(tag = "code", rename_all = "camelCase")] enum TestError { - Email(EmailError), + EmailAddress(EmailAddressError), Length(LengthError), Regex(RegexError), Url(UrlError), @@ -18,7 +18,9 @@ enum TestError { fn setup() -> (ValidationErrors, Value) { ( ValidationErrors::from_iter([ - TestError::Email(EmailError::from(email_address::Error::MissingSeparator)), + TestError::EmailAddress(EmailAddressError::from( + email_address::Error::MissingSeparator, + )), TestError::Length(LengthError::Equal { equal: 1, length: 2, @@ -31,7 +33,7 @@ fn setup() -> (ValidationErrors, Value) { #[cfg(not(feature = "message"))] json!([ { - "code": "email", + "code": "emailAddress", "subcode": "missingSeparator", }, { @@ -51,7 +53,7 @@ fn setup() -> (ValidationErrors, Value) { #[cfg(feature = "message")] json!([ { - "code": "email", + "code": "emailAddress", "subcode": "missingSeparator", "message": "", },