use std::str::FromStr;
use std::sync::OnceLock;
use serde::{Serialize, Deserialize};
use regex::Regex;
use crate::util::*;
pub mod regex_parts;
pub use regex_parts::*;
#[derive(Clone, Debug, Serialize, Deserialize, Suitability)]
#[serde(from = "RegexParts", into = "RegexParts")]
pub struct RegexWrapper {
#[suitable(always)]
regex: OnceLock<Regex>,
parts: RegexParts
}
impl RegexWrapper {
pub fn parts(&self) -> &RegexParts {
&self.parts
}
pub fn get_no_compile(&self) -> Option<&Regex> {
self.regex.get()
}
pub fn get(&self) -> Result<&Regex, regex::Error> {
if let Some(regex) = self.regex.get() {
Ok(regex)
} else {
let temp = self.parts.build()?;
Ok(self.regex.get_or_init(|| temp))
}
}
}
impl From<RegexParts> for RegexWrapper {
fn from(parts: RegexParts) -> Self {
Self {
regex: OnceLock::new(),
parts
}
}
}
impl FromStr for RegexWrapper {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(RegexParts::from(s).into())
}
}
impl From<&str> for RegexWrapper {
fn from(s: &str) -> Self {
RegexParts::from(s).into()
}
}
impl PartialEq for RegexWrapper {
fn eq(&self, other: &Self) -> bool {
self.parts.eq(&other.parts)
}
}
impl Eq for RegexWrapper {}
impl From<RegexWrapper> for RegexParts {
fn from(value: RegexWrapper) -> Self {
value.parts
}
}
impl AsRef<RegexParts> for RegexWrapper {
fn as_ref(&self) -> &RegexParts {
&self.parts
}
}
impl TryFrom<RegexWrapper> for Regex {
type Error = regex::Error;
fn try_from(value: RegexWrapper) -> Result<Self, Self::Error> {
if let Some(regex) = value.regex.into_inner() {
Ok(regex)
} else {
value.parts.build()
}
}
}