use std::ops::{BitAnd, BitXor, Not, Sub};
use crate::{Ascii, Chain, CharClass, Custom, PrettyRegex, Standard, Text};
impl<T> PrettyRegex<CharClass<T>> {
#[inline]
#[must_use]
pub fn and<R>(self, rhs: PrettyRegex<CharClass<R>>) -> PrettyRegex<CharClass<Custom>> {
self & rhs
}
#[inline]
#[must_use]
pub fn symmetric_difference_with<R>(
self,
rhs: PrettyRegex<CharClass<R>>,
) -> PrettyRegex<CharClass<Custom>> {
self ^ rhs
}
}
pub fn symmetric_difference_between<L, R>(
left: PrettyRegex<CharClass<L>>,
right: PrettyRegex<CharClass<R>>,
) -> PrettyRegex<CharClass<Custom>> {
left ^ right
}
impl<L, R> BitAnd<PrettyRegex<CharClass<R>>> for PrettyRegex<L> {
type Output = PrettyRegex<CharClass<Custom>>;
#[inline]
#[must_use]
fn bitand(self, rhs: PrettyRegex<CharClass<R>>) -> Self::Output {
PrettyRegex::from(format!("[{}&&{}]", self, rhs))
}
}
impl<L, R> Sub<PrettyRegex<CharClass<R>>> for PrettyRegex<L> {
type Output = PrettyRegex<CharClass<Custom>>;
fn sub(self, rhs: PrettyRegex<CharClass<R>>) -> Self::Output {
PrettyRegex::from(format!("[{}--{}]", self, rhs))
}
}
pub fn not<T, O>(regex: PrettyRegex<T>) -> PrettyRegex<O>
where
PrettyRegex<T>: Not<Output = PrettyRegex<O>>,
{
regex.not()
}
impl Not for PrettyRegex<CharClass<Standard>> {
type Output = Self;
fn not(self) -> Self::Output {
if self.0.len() < 2 {
return self;
}
if self.0.chars().nth(1).unwrap().is_lowercase() {
PrettyRegex::from(
self.0
.replace(r"\d", r"\D")
.replace(r"\p", r"\P")
.replace(r"\w", r"\W")
.replace(r"\s", r"\S")
.replace(r"\b", r"\B"),
)
} else {
PrettyRegex::from(
self.0
.replace(r"\D", r"\d")
.replace(r"\P", r"\p")
.replace(r"\W", r"\w")
.replace(r"\S", r"\s")
.replace(r"\B", r"\b"),
)
}
}
}
impl Not for PrettyRegex<CharClass<Custom>> {
type Output = Self;
fn not(self) -> Self::Output {
if self
.0
.chars()
.nth(1)
.expect("There must be 2 characters in custom regex")
== '^'
{
PrettyRegex::from(self.0.replace("[^", "["))
} else {
PrettyRegex::from(self.0.replace('[', "[^"))
}
}
}
impl Not for PrettyRegex<CharClass<Ascii>> {
type Output = Self;
fn not(self) -> Self::Output {
if self
.0
.chars()
.nth(3)
.expect("There must be 4 characters in ascii regex")
== '^'
{
PrettyRegex::from(self.0.replace("[[:^", "[[:"))
} else {
PrettyRegex::from(self.0.replace("[[:", "[[:^"))
}
}
}
impl Not for PrettyRegex<Text> {
type Output = PrettyRegex<Chain>;
fn not(self) -> Self::Output {
PrettyRegex::from(
self.0
.chars()
.fold("".to_owned(), |s, c| format!("{s}[^{c}]")),
)
}
}
impl<T, M> BitXor<PrettyRegex<CharClass<M>>> for PrettyRegex<CharClass<T>> {
type Output = PrettyRegex<CharClass<Custom>>;
fn bitxor(self, rhs: PrettyRegex<CharClass<M>>) -> Self::Output {
PrettyRegex::from(format!("[{}~~{}]", self, rhs))
}
}