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