use core::fmt::Debug;
use core::marker::PhantomData;
use crate::ctor::Ctor;
use crate::ctor::Handler;
use crate::ctx::Match;
use crate::debug_ctor_beg;
use crate::debug_ctor_reval;
use crate::debug_ctor_stage;
use crate::debug_regex_beg;
use crate::debug_regex_reval;
use crate::debug_regex_stage;
use crate::err::Error;
use crate::regex::Regex;
use crate::regex::impl_not_for_regex;
use crate::span::Span;
pub struct Branch<C, P, F, E> {
pat: P,
test: F,
other: E,
marker: PhantomData<C>,
}
impl_not_for_regex!(Branch<C, P, I, E>);
impl<C, P, F, E> Debug for Branch<C, P, F, E>
where
P: Debug,
F: Debug,
E: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Branch")
.field("pat", &self.pat)
.field("test", &self.test)
.field("other", &self.other)
.finish()
}
}
impl<C, P, F, E> Default for Branch<C, P, F, E>
where
P: Default,
F: Default,
E: Default,
{
fn default() -> Self {
Self {
pat: Default::default(),
test: Default::default(),
other: Default::default(),
marker: Default::default(),
}
}
}
impl<C, P, F, E> Clone for Branch<C, P, F, E>
where
P: Clone,
F: Clone,
E: Clone,
{
fn clone(&self) -> Self {
Self {
pat: self.pat.clone(),
test: self.test.clone(),
other: self.other.clone(),
marker: self.marker,
}
}
}
impl<C, P, F, E> Copy for Branch<C, P, F, E>
where
P: Copy,
F: Copy,
E: Copy,
{
}
impl<C, P, F, E> Branch<C, P, F, E> {
pub const fn new(test: F, pat: P, other: E) -> Self {
Self {
pat,
test,
other,
marker: PhantomData,
}
}
pub const fn pat(&self) -> &P {
&self.pat
}
pub const fn pat_mut(&mut self) -> &mut P {
&mut self.pat
}
pub const fn test(&self) -> &F {
&self.test
}
pub const fn test_mut(&mut self) -> &mut F {
&mut self.test
}
pub const fn other(&self) -> &E {
&self.other
}
pub const fn other_mut(&mut self) -> &mut E {
&mut self.other
}
pub fn set_pat(&mut self, pat: P) -> &mut Self {
self.pat = pat;
self
}
pub fn set_test(&mut self, test: F) -> &mut Self {
self.test = test;
self
}
pub fn set_other(&mut self, other: E) -> &mut Self {
self.other = other;
self
}
}
impl<'a, C, P, F, E, O, H> Ctor<C, O, H> for Branch<C, P, F, E>
where
P: Ctor<C, O, H>,
E: Ctor<C, O, H>,
C: Match<'a>,
F: Fn(&C) -> Result<bool, Error>,
H: Handler<C>,
{
#[inline(always)]
fn construct(&self, ctx: &mut C, func: &mut H) -> Result<O, Error> {
let offset = ctx.offset();
debug_ctor_beg!("Branch", offset);
let ret = debug_ctor_stage!("Branch", "test", (self.test)(ctx)?);
let ret = if ret {
debug_ctor_stage!("Branch", "true", self.pat.construct(ctx, func))
} else {
debug_ctor_stage!("Branch", "false", self.other.construct(ctx, func))
}
.inspect_err(|_| {
ctx.set_offset(offset);
});
debug_ctor_reval!("Branch", offset, ctx.offset(), ret.is_ok());
ret
}
}
impl<'a, C, P, F, E> Regex<C> for Branch<C, P, F, E>
where
P: Regex<C>,
E: Regex<C>,
C: Match<'a>,
F: Fn(&C) -> Result<bool, Error>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let offset = ctx.offset();
debug_regex_beg!("Branch", offset);
let ret = debug_regex_stage!("Branch", "test", (self.test)(ctx)?);
let ret = if ret {
debug_regex_stage!("Branch", "true", ctx.try_mat(&self.pat))
} else {
debug_regex_stage!("Branch", "false", ctx.try_mat(&self.other))
}
.inspect_err(|_| {
ctx.set_offset(offset);
});
debug_regex_reval!("Branch", ret)
}
}
pub const fn branch<'a, C, P, F, E>(test: F, pat: P, other: E) -> Branch<C, P, F, E>
where
C: Match<'a>,
E: Regex<C>,
P: Regex<C>,
F: Fn(&C) -> Result<bool, Error>,
{
Branch::new(test, pat, other)
}