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