//! PCRE use super::*; use pcre::{ Pcre, }; use std::{ sync::{ Mutex, }, error, fmt, }; #[derive(Debug)] pub struct Regex(Mutex, String); /// A regex error #[derive(Debug)] pub struct Error(pcre::CompilationError); impl error::Error for Error{} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f,"regex failed to compile: ")?; self.0.fmt(f) } } impl From for Error { #[inline] fn from(from: pcre::CompilationError) -> Self { Self(from) } } pub struct Iter<'a>(Option>, usize); impl<'a> Iterator for Iter<'a> { type Item = &'a str; fn next(&mut self) -> Option { if let Some(m) = &mut self.0 { if self.1 >= m.string_count() { None } else { let string = m.group(self.1); self.1 +=1; Some(string) } } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl<'a> std::iter::FusedIterator for Iter<'a>{} impl<'a> ExactSizeIterator for Iter<'a> { fn len(&self) -> usize { match &self.0 { Some(m) => m.string_count(), None => 0, } } } impl Regex { /// Create a new regular expression from a string pub fn new(from: impl AsRef, opt: I) -> Result where I: IntoIterator { let string = from.as_ref(); Ok(Self(Mutex::new(Pcre::compile_with_options(string, &opt.into_iter().collect())?), string.to_owned())) } /// Test against string pub fn test(&self, string: impl AsRef) -> bool { let mut regex = self.0.lock().unwrap(); regex.exec(string.as_ref()).is_some() } /// Get the groups of a match against string pub fn exec_ref<'a>(&mut self, string: &'a (impl AsRef + ?Sized)) -> Iter<'a> { let regex = self.0.get_mut().unwrap(); Iter(regex.exec(string.as_ref()), 0) } /// Get the groups as an owned string vector from map against string pub fn exec(&self, string: impl AsRef) -> Vec { let mut regex = self.0.lock().unwrap(); Iter(regex.exec(string.as_ref()), 0).map(std::borrow::ToOwned::to_owned).collect() } /// Get the string used to create this regex #[inline] pub fn as_str(&self) -> &str{ &self.1[..] } } impl From for Pcre { #[inline] fn from(from: Regex) -> Self { from.0.into_inner().unwrap() } } impl fmt::Display for Regex { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.1) } }