use crate::ReadableRe;
use std::fmt::{Display, Formatter};
use std::ops::{Bound, RangeBounds};
macro_rules! impl_builder_from_iter {
($struct_name:ident) => {
impl<'a> FromIterator<ReadableRe<'a>> for $struct_name<'a> {
fn from_iter<T: IntoIterator<Item = ReadableRe<'a>>>(iter: T) -> Self {
Self(Box::new(ReadableRe::Concat(Concat::new(
iter.into_iter().collect::<Vec<_>>(),
))))
}
}
};
}
#[derive(Clone)]
pub struct Concat<'a>(pub(crate) Vec<ReadableRe<'a>>);
impl<'a> Concat<'a> {
pub fn new(v: impl IntoIterator<Item = ReadableRe<'a>>) -> Self {
Self::from_iter(v)
}
}
impl<'a> FromIterator<ReadableRe<'a>> for Concat<'a> {
fn from_iter<T: IntoIterator<Item = ReadableRe<'a>>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl<'a> Display for Concat<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for re in &self.0 {
write!(f, "{}", re)?;
}
Ok(())
}
}
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct BackReference(pub usize);
#[cfg(feature = "re-fancy")]
impl Display for BackReference {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, r"\{}", self.0)
}
}
#[derive(Clone)]
pub struct Escape<'a>(Box<ReadableRe<'a>>);
impl Display for Escape<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", regex::escape(&self.0.to_string()))
}
}
impl<'a> Escape<'a> {
pub fn new_str(s: &'a str) -> Self {
Self(Box::new(ReadableRe::Raw(s)))
}
pub fn new(readable_regex: ReadableRe<'a>) -> Self {
Self(Box::new(readable_regex))
}
}
impl_builder_from_iter!(Escape);
#[derive(Clone)]
pub struct Group<'a>(Box<ReadableRe<'a>>);
impl<'a> Group<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for Group<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "({})", self.0)
}
}
impl_builder_from_iter!(Group);
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct PositiveLookAhead<'a>(Box<ReadableRe<'a>>);
#[cfg(feature = "re-fancy")]
impl<'a> PositiveLookAhead<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
#[cfg(feature = "re-fancy")]
impl<'a> Display for PositiveLookAhead<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?={})", self.0)
}
}
#[cfg(feature = "re-fancy")]
impl_builder_from_iter!(PositiveLookAhead);
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct NegativeLookAhead<'a>(Box<ReadableRe<'a>>);
#[cfg(feature = "re-fancy")]
impl<'a> NegativeLookAhead<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
#[cfg(feature = "re-fancy")]
impl<'a> Display for NegativeLookAhead<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?!{})", self.0)
}
}
#[cfg(feature = "re-fancy")]
impl_builder_from_iter!(NegativeLookAhead);
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct PositiveLookBehind<'a>(Box<ReadableRe<'a>>);
#[cfg(feature = "re-fancy")]
impl<'a> PositiveLookBehind<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
#[cfg(feature = "re-fancy")]
impl<'a> Display for PositiveLookBehind<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?<={})", self.0)
}
}
#[cfg(feature = "re-fancy")]
impl_builder_from_iter!(PositiveLookBehind);
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct NegativeLookBehind<'a>(Box<ReadableRe<'a>>);
#[cfg(feature = "re-fancy")]
impl<'a> NegativeLookBehind<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
#[cfg(feature = "re-fancy")]
impl<'a> Display for NegativeLookBehind<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?<!{})", self.0)
}
}
#[cfg(feature = "re-fancy")]
impl_builder_from_iter!(NegativeLookBehind);
#[derive(Clone)]
pub struct NamedGroup<'a> {
name: &'a str,
regexes: Box<ReadableRe<'a>>,
}
impl<'a> NamedGroup<'a> {
pub fn new(name: &'a str, re: ReadableRe<'a>) -> Self {
Self {
name,
regexes: Box::new(re),
}
}
}
impl<'a> Display for NamedGroup<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?P<{}>{})", self.name, self.regexes)
}
}
#[derive(Clone)]
pub struct NonCaptureGroup<'a>(Box<ReadableRe<'a>>);
impl<'a> NonCaptureGroup<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for NonCaptureGroup<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?:{})", self.0)
}
}
impl_builder_from_iter!(NonCaptureGroup);
#[derive(Clone)]
pub struct Optional<'a>(Box<ReadableRe<'a>>);
impl<'a> Optional<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for Optional<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}?", self.0)
}
}
impl_builder_from_iter!(Optional);
#[derive(Clone)]
pub struct Either<'a>(Concat<'a>);
impl<'a> Either<'a> {
pub fn new(iter: impl IntoIterator<Item = ReadableRe<'a>>) -> Self {
Self::from_iter(iter)
}
}
impl<'a> Display for Either<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<'a> FromIterator<ReadableRe<'a>> for Either<'a> {
fn from_iter<T: IntoIterator<Item = ReadableRe<'a>>>(iter: T) -> Self {
let iter = iter
.into_iter()
.flat_map(|re| [re, ReadableRe::Raw("|")].into_iter());
let mut concat = Concat::from_iter(iter);
concat.0.pop();
Self(concat)
}
}
#[derive(Clone)]
pub struct Exactly<'a> {
quantity: usize,
re: Box<ReadableRe<'a>>,
}
impl<'a> Exactly<'a> {
pub fn new(quantity: usize, re: ReadableRe<'a>) -> Self {
Self {
quantity,
re: Box::new(re),
}
}
}
impl<'a> Display for Exactly<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{{{}}}", self.re, self.quantity)
}
}
pub struct Ranged<'a> {
range: (Bound<usize>, Bound<usize>),
re: Box<ReadableRe<'a>>,
}
impl<'a> Clone for Ranged<'a> {
fn clone(&self) -> Self {
Self {
range: self.range,
re: self.re.clone(),
}
}
}
impl<'a> Ranged<'a> {
pub fn new<R>(range: R, re: ReadableRe<'a>) -> Self
where
R: RangeBounds<usize> + 'static,
{
Self {
range: (range.start_bound().cloned(), range.end_bound().cloned()),
re: Box::new(re),
}
}
}
impl<'a> Display for Ranged<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let (min, max) = match self.range {
(
Bound::Included(min) | Bound::Excluded(min),
Bound::Included(max) | Bound::Excluded(max),
) => (min.to_string(), max.to_string()),
(Bound::Included(min) | Bound::Excluded(min), Bound::Unbounded) => {
(min.to_string(), "".to_string())
}
(Bound::Unbounded, Bound::Included(max) | Bound::Excluded(max)) => {
("".to_string(), max.to_string())
}
(Bound::Unbounded, Bound::Unbounded) => ("".to_string(), "".to_string()),
};
write!(f, "{}{{{},{}}}", self.re, min, max)
}
}
#[derive(Clone)]
pub struct ZeroOrMore<'a>(Box<ReadableRe<'a>>);
impl<'a> ZeroOrMore<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for ZeroOrMore<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}*", self.0)
}
}
impl_builder_from_iter!(ZeroOrMore);
#[derive(Clone)]
pub struct ZeroOrMoreLazy<'a>(Box<ReadableRe<'a>>);
impl<'a> ZeroOrMoreLazy<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for ZeroOrMoreLazy<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}*?", self.0)
}
}
impl_builder_from_iter!(ZeroOrMoreLazy);
#[derive(Clone)]
pub struct OneOrMore<'a>(Box<ReadableRe<'a>>);
impl<'a> OneOrMore<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for OneOrMore<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}+", self.0)
}
}
impl_builder_from_iter!(OneOrMore);
#[derive(Clone)]
pub struct OneOrMoreLazy<'a>(Box<ReadableRe<'a>>);
impl<'a> OneOrMoreLazy<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for OneOrMoreLazy<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}+?", self.0)
}
}
impl_builder_from_iter!(OneOrMoreLazy);
#[derive(Clone)]
pub struct StartsWith<'a>(Box<ReadableRe<'a>>);
impl<'a> StartsWith<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for StartsWith<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "^{}", self.0)
}
}
impl_builder_from_iter!(StartsWith);
#[derive(Clone)]
pub struct EndsWith<'a>(Box<ReadableRe<'a>>);
impl<'a> EndsWith<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
impl<'a> Display for EndsWith<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}$", self.0)
}
}
impl_builder_from_iter!(EndsWith);
#[derive(Clone)]
pub struct StartsAndEndsWith<'a>(Box<ReadableRe<'a>>);
impl<'a> StartsAndEndsWith<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(ReadableRe::StartsWith(StartsWith::new(
ReadableRe::EndsWith(EndsWith::new(re)),
))))
}
}
impl<'a> Display for StartsAndEndsWith<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl_builder_from_iter!(StartsAndEndsWith);
#[derive(Clone)]
pub struct Chars(String);
impl Chars {
pub fn new(s: &str) -> Self {
Self(s.to_string())
}
}
impl Display for Chars {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}]", self.0)
}
}
#[derive(Clone)]
pub struct NotChars(String);
impl NotChars {
pub fn new(s: &str) -> Self {
Self(s.to_string())
}
}
impl Display for NotChars {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "[^{}]", self.0)
}
}
#[cfg(feature = "re-fancy")]
#[derive(Clone)]
pub struct AtomicGroup<'a>(Box<ReadableRe<'a>>);
#[cfg(feature = "re-fancy")]
impl<'a> AtomicGroup<'a> {
pub fn new(re: ReadableRe<'a>) -> Self {
Self(Box::new(re))
}
}
#[cfg(feature = "re-fancy")]
impl<'a> Display for AtomicGroup<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "(?>{})", self.0)
}
}
#[cfg(feature = "re-fancy")]
impl_builder_from_iter!(AtomicGroup);