#![allow(unused_imports)] use std::{ error, fmt::{ self, Write, }, sync::{ Arc, Mutex, } }; pub type Groups = Vec; pub struct Regex { #[cfg(feature="perl")] internal: Arc>, #[cfg(not(feature = "perl"))] internal: regex::Regex, } #[derive(Debug)] pub enum Error { Compile(String), Execute, Internal, Unknown, } impl error::Error for Error{} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "regex error: ")?; match self { Error::Compile(s) => write!(f, "compilation failed: {}", s), Error::Execute => write!(f, "execution failed"), Error::Internal => write!(f, "internal"), _ => write!(f, "unknown"), } } } impl Regex { pub fn compile(string: impl AsRef) -> Result { #[cfg(feature = "perl")] return Ok(Self{internal: Arc::new(Mutex::new(pcre::Pcre::compile(string.as_ref())?))}); #[cfg(not(feature = "perl"))] return Ok(Self{internal: regex::Regex::new(string.as_ref())?}); } pub fn exec(&self, string: impl AsRef) -> Result, Error> { #[cfg(feature = "perl")] return { let mut re = self.internal.lock().unwrap(); Ok(match re.exec(string.as_ref()) { Some(m) => { let len = m.string_count(); let mut output = Vec::with_capacity(len); for i in 0..len { output.push(m.group(i).to_owned()); } Some(output) }, None => None, }) }; #[cfg(not(feature = "perl"))] return { Ok(match self.internal.captures(string.as_ref()) { Some(m) => { let mut output = Vec::with_capacity(m.len()); for i in 0..m.len() { let ma = m.get(i).unwrap(); let mut op = String::with_capacity(ma.range().len()); write!(op, "{}", ma.as_str())?; output.push(op); } Some(output) }, None => None, }) }; } } impl From for Error { fn from(_er: fmt::Error) -> Self { Self::Internal } } #[cfg(not(feature = "perl"))] impl From for Error { fn from(er: regex::Error) -> Self { Self::Compile(format!("{}", er)) } } #[cfg(feature = "perl")] impl From for Error { fn from(er: pcre::CompilationError) -> Self { Self::Compile(format!("{}", er)) } }