1 use ::regex::{Error, Regex, RegexSet};
2 
3 use core::{convert::TryFrom, ops::Deref, str::FromStr};
4 use std::borrow::Cow;
5 
6 /// Contains either a regular expression or a set of them or a reference to one.
7 ///
8 /// See [Arg::validator_regex(][crate::Arg::validator_regex] to set this on an argument.
9 #[derive(Debug, Clone)]
10 pub enum RegexRef<'a> {
11     /// Used if the underlying is a regex set
12     RegexSet(Cow<'a, RegexSet>),
13     /// Used if the underlying is a regex
14     Regex(Cow<'a, Regex>),
15 }
16 
17 impl<'a> RegexRef<'a> {
is_match(&self, text: &str) -> bool18     pub(crate) fn is_match(&self, text: &str) -> bool {
19         match self {
20             Self::Regex(r) => r.deref().is_match(text),
21             Self::RegexSet(r) => r.deref().is_match(text),
22         }
23     }
24 }
25 
26 impl<'a> From<&'a Regex> for RegexRef<'a> {
from(r: &'a Regex) -> Self27     fn from(r: &'a Regex) -> Self {
28         Self::Regex(Cow::Borrowed(r))
29     }
30 }
31 
32 impl<'a> From<Regex> for RegexRef<'a> {
from(r: Regex) -> Self33     fn from(r: Regex) -> Self {
34         Self::Regex(Cow::Owned(r))
35     }
36 }
37 
38 impl<'a> From<&'a RegexSet> for RegexRef<'a> {
from(r: &'a RegexSet) -> Self39     fn from(r: &'a RegexSet) -> Self {
40         Self::RegexSet(Cow::Borrowed(r))
41     }
42 }
43 
44 impl<'a> From<RegexSet> for RegexRef<'a> {
from(r: RegexSet) -> Self45     fn from(r: RegexSet) -> Self {
46         Self::RegexSet(Cow::Owned(r))
47     }
48 }
49 
50 impl<'a> TryFrom<&'a str> for RegexRef<'a> {
51     type Error = <Self as FromStr>::Err;
52 
try_from(r: &'a str) -> Result<Self, Self::Error>53     fn try_from(r: &'a str) -> Result<Self, Self::Error> {
54         Self::from_str(r)
55     }
56 }
57 
58 impl<'a> FromStr for RegexRef<'a> {
59     type Err = Error;
60 
from_str(s: &str) -> Result<Self, Self::Err>61     fn from_str(s: &str) -> Result<Self, Self::Err> {
62         Regex::from_str(s).map(|v| Self::Regex(Cow::Owned(v)))
63     }
64 }
65 
66 #[cfg(test)]
67 mod tests {
68     use super::*;
69     use core::convert::TryInto;
70 
71     #[test]
test_try_from_with_valid_string()72     fn test_try_from_with_valid_string() {
73         let t: Result<RegexRef, _> = "^Hello, World$".try_into();
74         assert!(t.is_ok())
75     }
76 
77     #[test]
test_try_from_with_invalid_string()78     fn test_try_from_with_invalid_string() {
79         let t: Result<RegexRef, _> = "^Hello, World)$".try_into();
80         assert!(t.is_err());
81     }
82 
83     #[test]
from_str()84     fn from_str() {
85         let t: Result<RegexRef, _> = RegexRef::from_str("^Hello, World");
86         assert!(t.is_ok());
87     }
88 }
89