validator_async/validation/
urls.rs1use std::{
2 borrow::Cow,
3 cell::{Ref, RefMut},
4 rc::Rc,
5 sync::Arc,
6};
7use url::Url;
8
9pub trait ValidateUrl {
11 fn validate_url(&self) -> bool {
12 if let Some(u) = self.as_url_string() {
13 Url::parse(&u).is_ok()
14 } else {
15 true
16 }
17 }
18
19 fn as_url_string(&self) -> Option<Cow<str>>;
20}
21
22macro_rules! validate_type_that_derefs {
23 ($type_:ty) => {
24 impl<T> ValidateUrl for $type_
25 where
26 T: ValidateUrl,
27 {
28 fn as_url_string(&self) -> Option<Cow<str>> {
29 T::as_url_string(self)
30 }
31 }
32 };
33}
34
35validate_type_that_derefs!(&T);
36validate_type_that_derefs!(Arc<T>);
37validate_type_that_derefs!(Box<T>);
38validate_type_that_derefs!(Rc<T>);
39validate_type_that_derefs!(Ref<'_, T>);
40validate_type_that_derefs!(RefMut<'_, T>);
41
42macro_rules! validate_type_of_str {
43 ($type_:ty) => {
44 impl ValidateUrl for $type_ {
45 fn as_url_string(&self) -> Option<Cow<str>> {
46 Some(Cow::Borrowed(self))
47 }
48 }
49 };
50}
51
52validate_type_of_str!(str);
53validate_type_of_str!(&str);
54validate_type_of_str!(String);
55
56impl<T> ValidateUrl for Option<T>
57where
58 T: ValidateUrl,
59{
60 fn as_url_string(&self) -> Option<Cow<str>> {
61 let Some(u) = self else {
62 return None;
63 };
64
65 T::as_url_string(u)
66 }
67}
68
69impl ValidateUrl for Cow<'_, str> {
70 fn as_url_string(&self) -> Option<Cow<'_, str>> {
71 <str as ValidateUrl>::as_url_string(self)
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use std::borrow::Cow;
78
79 use super::ValidateUrl;
80
81 #[test]
82 fn test_validate_url() {
83 let tests = vec![
84 ("http", false),
85 ("https://google.com", true),
86 ("http://localhost:80", true),
87 ("ftp://localhost:80", true),
88 ];
89
90 for (url, expected) in tests {
91 assert_eq!(url.validate_url(), expected);
92 }
93 }
94
95 #[test]
96 fn test_validate_url_cow() {
97 let test: Cow<'static, str> = "http://localhost:80".into();
98 assert!(test.validate_url());
99 let test: Cow<'static, str> = String::from("http://localhost:80").into();
100 assert!(test.validate_url());
101 let test: Cow<'static, str> = "http".into();
102 assert!(!test.validate_url());
103 let test: Cow<'static, str> = String::from("http").into();
104 assert!(!test.validate_url());
105 }
106}