use core::fmt::Debug;
use core::marker::PhantomData;
use crate::ctor::Ctor;
use crate::ctor::Handler;
use crate::ctor::Map;
use crate::ctx::CtxGuard;
use crate::ctx::Match;
use crate::debug_ctor_stage;
use crate::err::Error;
use crate::map::Select0;
use crate::map::Select1;
use crate::map::SelectEq;
use crate::regex::Regex;
use crate::regex::impl_not_for_regex;
use crate::span::Span;
pub struct DynamicCtorThenBuilder<C, P, F> {
pat: P,
func: F,
marker: PhantomData<C>,
}
impl_not_for_regex!(DynamicCtorThenBuilder<C, P, F>);
impl<C, P, F> Debug for DynamicCtorThenBuilder<C, P, F>
where
P: Debug,
F: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DynamicCtorBuilder")
.field("pat", &self.pat)
.field("func", &self.func)
.finish()
}
}
impl<C, P, F> Default for DynamicCtorThenBuilder<C, P, F>
where
P: Default,
F: Default,
{
fn default() -> Self {
Self {
pat: Default::default(),
func: Default::default(),
marker: Default::default(),
}
}
}
impl<C, P, F> Clone for DynamicCtorThenBuilder<C, P, F>
where
P: Clone,
F: Clone,
{
fn clone(&self) -> Self {
Self {
pat: self.pat.clone(),
func: self.func.clone(),
marker: self.marker,
}
}
}
impl<C, P, F> Copy for DynamicCtorThenBuilder<C, P, F>
where
P: Copy,
F: Copy,
{
}
impl<C, P, F> DynamicCtorThenBuilder<C, P, F> {
pub const fn new(pat: P, func: F) -> Self {
Self {
pat,
func,
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 func(&self) -> &F {
&self.func
}
pub const fn func_mut(&mut self) -> &mut F {
&mut self.func
}
pub fn set_pat(&mut self, pat: P) -> &mut Self {
self.pat = pat;
self
}
pub fn set_func(&mut self, func: F) -> &mut Self {
self.func = func;
self
}
pub fn _0<O>(self) -> Map<C, Self, Select0, O> {
Map::new(self, Select0)
}
pub fn _1<O>(self) -> Map<C, Self, Select1, O> {
Map::new(self, Select1)
}
pub fn _eq<I1, I2>(self) -> Map<C, Self, SelectEq, (I1, I2)> {
Map::new(self, SelectEq)
}
}
impl<'a, C, P, F> Regex<C> for DynamicCtorThenBuilder<C, P, F>
where
P: Regex<C>,
C: Match<'a>,
{
fn try_parse(&self, _: &mut C) -> Result<Span, Error> {
unimplemented!("DynamicCtorThenBuilder not support Regex trait")
}
}
impl<'a, C, P, F, T, O1, O2, H> Ctor<C, (O1, O2), H> for DynamicCtorThenBuilder<C, P, F>
where
C: Match<'a>,
P: Ctor<C, O1, H>,
T: Ctor<C, O2, H>,
F: Fn(&mut C, &O1) -> Result<T, Error>,
H: Handler<C>,
{
#[inline(always)]
fn construct(&self, ctx: &mut C, func: &mut H) -> Result<(O1, O2), Error> {
let mut ctx = CtxGuard::new(ctx);
crate::debug_ctor_beg!("DynamicCtorThenBuilder", ctx.beg());
let l = {
debug_ctor_stage!(
"DynamicCtorThenBuilder",
"left",
self.pat.construct(ctx.ctx(), func)
)
};
let l = ctx.process_ret(l)?;
let r = {
debug_ctor_stage!(
"DynamicCtorThenBuilder",
"right",
(self.func)(ctx.ctx(), &l)?.construct(ctx.ctx(), func)
)
};
let r = ctx.process_ret(r)?;
crate::debug_ctor_reval!("DynamicCtorThenBuilder", ctx.beg(), ctx.end(), true);
Ok((l, r))
}
}
pub trait DynamicCtorThenBuilderHelper<'a, C>
where
Self: Sized,
C: Match<'a>,
{
fn into_ctor_then_builder<F, O1, R>(self, func: F) -> DynamicCtorThenBuilder<C, Self, F>
where
F: Fn(&mut C, &O1) -> Result<R, Error>;
}
impl<'a, C, T> DynamicCtorThenBuilderHelper<'a, C> for T
where
Self: Sized,
C: Match<'a>,
{
fn into_ctor_then_builder<F, O1, R>(self, func: F) -> DynamicCtorThenBuilder<C, Self, F>
where
F: Fn(&mut C, &O1) -> Result<R, Error>,
{
DynamicCtorThenBuilder::new(self, func)
}
}