You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yuurei/src/regex.rs

128 lines
2.5 KiB

//! PCRE
use super::*;
use pcre::{
Pcre,
};
use std::{
sync::{
Mutex,
},
error,
fmt,
};
#[derive(Debug)]
pub struct Regex(Mutex<Pcre>, 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<pcre::CompilationError> for Error
{
#[inline] fn from(from: pcre::CompilationError) -> Self
{
Self(from)
}
}
pub struct Iter<'a>(Option<pcre::Match<'a>>, usize);
impl<'a> Iterator for Iter<'a>
{
type Item = &'a str;
fn next(&mut self) -> Option<Self::Item> {
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<usize>) {
(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<I>(from: impl AsRef<str>, opt: I) -> Result<Self, Error>
where I: IntoIterator<Item=pcre::CompileOption>
{
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<str>) -> 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<str> + ?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<str>) -> Vec<String>
{
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<Regex> 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)
}
}