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
3 changes: 1 addition & 2 deletions validator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ rust-version = { workspace = true }
[dependencies]
url = "2"
regex = { version = "1", default-features = false, features = ["std"] }
once_cell = "1.18.0"
idna = "1"
serde = "1"
serde_derive = "1"
Expand All @@ -26,4 +25,4 @@ indexmap = { version = "2.0.0", features = ["serde"], optional = true }
[features]
card = ["card-validate"]
derive = ["validator_derive"]
derive_nightly_features = ["derive","validator_derive/nightly_features"]
derive_nightly_features = ["derive", "validator_derive/nightly_features"]
4 changes: 2 additions & 2 deletions validator/src/validation/contains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ where
}
}

impl<'cow, T> ValidateContains for Cow<'cow, T>
impl<T> ValidateContains for Cow<'_, T>
where
T: ToOwned + ?Sized,
for<'a> &'a T: ValidateContains,
Expand All @@ -44,7 +44,7 @@ where
}
}

impl<'a> ValidateContains for &'a str {
impl ValidateContains for &str {
fn validate_contains(&self, needle: &str) -> bool {
self.contains(needle)
}
Expand Down
19 changes: 9 additions & 10 deletions validator/src/validation/email.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
use idna::domain_to_ascii;
use once_cell::sync::Lazy;
use regex::Regex;
use std::borrow::Cow;
use std::{borrow::Cow, sync::LazyLock};

use crate::ValidateIp;

// Regex from the specs
// https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
// It will mark esoteric email addresses like quoted string as invalid
static EMAIL_USER_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+\z").unwrap());
static EMAIL_DOMAIN_RE: Lazy<Regex> = Lazy::new(|| {
static EMAIL_USER_RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+\z").unwrap());
static EMAIL_DOMAIN_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r"^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
).unwrap()
});
// literal form, ipv4 or ipv6 address (SMTP 4.1.3)
static EMAIL_LITERAL_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"\[([a-fA-F0-9:\.]+)\]\z").unwrap());
static EMAIL_LITERAL_RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"\[([a-fA-F0-9:\.]+)\]\z").unwrap());

/// Checks if the domain is a valid domain and if not, check whether it's an IP
#[must_use]
Expand Down Expand Up @@ -109,7 +108,7 @@ where
}
}

impl<'a> ValidateEmail for &'a str {
impl ValidateEmail for &str {
fn as_email_string(&self) -> Option<Cow<'_, str>> {
Some(Cow::from(*self))
}
Expand Down Expand Up @@ -209,9 +208,9 @@ mod tests {
fn test_validate_email_rfc5321() {
// 65 character local part
let test = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@mail.com";
assert_eq!(test.validate_email(), false);
assert!(!test.validate_email());
// 256 character domain part
let test = "a@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
assert_eq!(test.validate_email(), false);
assert!(!test.validate_email());
}
}
4 changes: 2 additions & 2 deletions validator/src/validation/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ where
T: ToString,
{
fn validate_ipv4(&self) -> bool {
IpAddr::from_str(&self.to_string()).map_or(false, |i| i.is_ipv4())
IpAddr::from_str(&self.to_string()).is_ok_and(|i| i.is_ipv4())
}

fn validate_ipv6(&self) -> bool {
IpAddr::from_str(&self.to_string()).map_or(false, |i| i.is_ipv6())
IpAddr::from_str(&self.to_string()).is_ok_and(|i| i.is_ipv6())
}

fn validate_ip(&self) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion validator/src/validation/regex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ where
}
}

impl<'cow, T> ValidateRegex for Cow<'cow, T>
impl<T> ValidateRegex for Cow<'_, T>
where
T: ToOwned + ?Sized,
for<'a> &'a T: ValidateRegex,
Expand Down
3 changes: 1 addition & 2 deletions validator_derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ quote = "1"
proc-macro2 = "1"
proc-macro-error2 = "2"
darling = { version = "0.20", features = ["suggestions"] }
once_cell = "1.18.0"

[features]
nightly_features = ["proc-macro-error2/nightly"]
nightly_features = ["proc-macro-error2/nightly"]
35 changes: 13 additions & 22 deletions validator_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,37 +263,28 @@ impl ValidationData {
if let Some(context) = &self.context {
// Check if context lifetime is not `'v_a`
for segment in &context.segments {
match &segment.arguments {
PathArguments::AngleBracketed(args) => {
for arg in &args.args {
match arg {
syn::GenericArgument::Lifetime(lt) => {
if lt.ident != "v_a" {
abort! {
lt.ident, "Invalid argument reference";
note = "The lifetime `'{}` is not supported.", lt.ident;
help = "Please use the validator lifetime `'v_a`";
}
}
if let PathArguments::AngleBracketed(args) = &segment.arguments {
for arg in &args.args {
if let syn::GenericArgument::Lifetime(lt) = arg {
if lt.ident != "v_a" {
abort! {
lt.ident, "Invalid argument reference";
note = "The lifetime `'{}` is not supported.", lt.ident;
help = "Please use the validator lifetime `'v_a`";
}
_ => (),
}
}
}
_ => (),
}
}
}

match &self.data {
Data::Struct(fields) => {
let original_fields: Vec<&Field> =
fields.fields.iter().map(|f| &f.original).collect();
for f in &fields.fields {
f.parsed.validate(&self.ident, &original_fields, &f.original);
}
if let Data::Struct(fields) = &self.data {
let original_fields: Vec<&Field> =
fields.fields.iter().map(|f| &f.original).collect();
for f in &fields.fields {
f.parsed.validate(&self.ident, &original_fields, &f.original);
}
_ => (),
}

Ok(self)
Expand Down
6 changes: 3 additions & 3 deletions validator_derive/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use once_cell::sync::Lazy;
use std::sync::LazyLock;

use darling::util::Override;
use darling::{FromField, FromMeta};
Expand All @@ -12,7 +12,7 @@ use crate::utils::{get_attr, CrateName};

static OPTIONS_TYPE: [&str; 3] = ["Option|", "std|option|Option|", "core|option|Option|"];

pub(crate) static NUMBER_TYPES: Lazy<Vec<String>> = Lazy::new(|| {
pub(crate) static NUMBER_TYPES: LazyLock<Vec<String>> = LazyLock::new(|| {
let number_types = [
quote!(usize),
quote!(u8),
Expand Down Expand Up @@ -154,7 +154,7 @@ impl ValidateField {
fn find_option(mut count: u8, ty: &syn::Type) -> u8 {
if let syn::Type::Path(p) = ty {
let idents_of_path =
p.path.segments.iter().into_iter().fold(String::new(), |mut acc, v| {
p.path.segments.iter().fold(String::new(), |mut acc, v| {
acc.push_str(&v.ident.to_string());
acc.push('|');
acc
Expand Down
1 change: 0 additions & 1 deletion validator_derive_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
trybuild = "1.0"
regex = "1"
once_cell = "1.18.0"

[dependencies]
indexmap = { version = "2", features = ["serde"], optional = true }
7 changes: 3 additions & 4 deletions validator_derive_tests/tests/complex.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{borrow::Cow, collections::HashMap};
use std::{borrow::Cow, collections::HashMap, sync::LazyLock};

use once_cell::sync::Lazy;
use regex::Regex;
use serde::Deserialize;

Expand Down Expand Up @@ -73,7 +72,7 @@ fn is_fine_with_many_valid_validations() {

#[test]
fn test_can_validate_option_fields_with_lifetime() {
static RE2: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-z]{2}$").unwrap());
static RE2: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[a-z]{2}$").unwrap());

#[derive(Debug, Validate)]
struct PutStruct<'a> {
Expand Down Expand Up @@ -117,7 +116,7 @@ fn test_can_validate_option_fields_with_lifetime() {

#[test]
fn test_can_validate_option_fields_without_lifetime() {
static RE2: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-z]{2}$").unwrap());
static RE2: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[a-z]{2}$").unwrap());

#[derive(Debug, Validate)]
struct PutStruct {
Expand Down
3 changes: 1 addition & 2 deletions validator_derive_tests/tests/regex.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use once_cell::sync::Lazy;
use std::cell::OnceCell;
use std::sync::{LazyLock, Mutex, OnceLock};

use regex::Regex;
use validator::Validate;

static RE2: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[a-z]{2}$").unwrap());
static RE2: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[a-z]{2}$").unwrap());

static REGEX_ONCE_LOCK: OnceLock<Regex> = OnceLock::new();
static REGEX_MUTEX_ONCE_CELL: Mutex<OnceCell<Regex>> = Mutex::new(OnceCell::new());
Expand Down
8 changes: 2 additions & 6 deletions validator_derive_tests/tests/run-pass/regex.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@

use once_cell::sync::Lazy;
use regex::Regex;
use std::sync::LazyLock;
use validator::Validate;

static RE2: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"^[a-z]{2}$").unwrap()
});

static RE2: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[a-z]{2}$").unwrap());

#[derive(Validate)]
struct Test {
Expand Down
Loading