use std::borrow::Cow;
use validator::{
ValidateContains, ValidateEmail, ValidateIp, ValidateLength, ValidateRegex, ValidateUrl,
};
use super::{Classified, ClassifiedField};
impl<T: ValidateEmail, F: ClassifiedField> ValidateEmail for Classified<T, F> {
fn validate_email(&self) -> bool {
self.inner().validate_email()
}
fn as_email_string(&self) -> Option<Cow<'_, str>> {
None
}
}
impl<T: ValidateUrl, F: ClassifiedField> ValidateUrl for Classified<T, F> {
fn validate_url(&self) -> bool {
self.inner().validate_url()
}
fn as_url_string(&self) -> Option<Cow<'_, str>> {
None
}
}
impl<T: ValidateContains, F: ClassifiedField> ValidateContains for Classified<T, F> {
fn validate_contains(&self, needle: &str) -> bool {
self.inner().validate_contains(needle)
}
}
impl<T: ValidateLength<u64>, F: ClassifiedField> ValidateLength<u64> for Classified<T, F> {
fn length(&self) -> Option<u64> {
self.inner().length()
}
}
impl<T: ValidateRegex, F: ClassifiedField> ValidateRegex for Classified<T, F> {
fn validate_regex(&self, regex: impl validator::AsRegex) -> bool {
self.inner().validate_regex(regex)
}
}
impl<T: ValidateIp, F: ClassifiedField> ValidateIp for Classified<T, F> {
fn validate_ipv4(&self) -> bool {
self.inner().validate_ipv4()
}
fn validate_ipv6(&self) -> bool {
self.inner().validate_ipv6()
}
fn validate_ip(&self) -> bool {
self.inner().validate_ip()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::classify::Classification;
struct EmailField;
impl crate::classify::ClassifiedField for EmailField {
const MODEL: &'static str = "Customer";
const MODEL_PATH: &'static str = "test::Customer";
const FIELD: &'static str = "email";
const CLASSIFICATION: Classification = Classification::PersonalData;
}
fn classified(value: &str) -> Classified<String, EmailField> {
Classified::new(value.to_string())
}
#[test]
fn email_rules_see_through_the_wrapper() {
assert!(classified("ada@example.com").validate_email());
assert!(!classified("not-an-email").validate_email());
}
#[test]
fn length_rules_see_through_the_wrapper() {
assert!(classified("abcd").validate_length(Some(2), Some(8), None));
assert!(!classified("a").validate_length(Some(2), Some(8), None));
}
#[test]
fn contains_and_its_blanket_negation_see_through_the_wrapper() {
use validator::ValidateDoesNotContain as _;
assert!(classified("ada@example.com").validate_contains("@"));
assert!(classified("ada@example.com").validate_does_not_contain("#"));
}
#[test]
fn url_rules_see_through_the_wrapper() {
assert!(classified("https://example.com").validate_url());
assert!(!classified("not a url").validate_url());
}
#[test]
fn the_value_returning_accessors_hand_back_nothing() {
let c = classified("ada@example.com");
assert!(c.as_email_string().is_none());
assert!(c.as_url_string().is_none());
assert!(c.validate_email());
}
#[test]
fn ip_rules_see_through_the_wrapper() {
assert!(classified("127.0.0.1").validate_ipv4());
assert!(!classified("127.0.0.1").validate_ipv6());
}
}