use core::marker::PhantomData;
use derive_more::{IsVariant, TryUnwrap, Unwrap};
use super::*;
mod parser_input;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Deny(());
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Allow(());
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Require(());
pub type SeparatedByOptions<Trailing = (), Leading = (), Max = (), Min = ()> =
With<With<Trailing, Leading>, With<Max, Min>>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
Config = SeparatedByOptions,
Lang: ?Sized = (),
> {
pub(super) f: F,
pub(super) sep: SepClassifier,
pub(super) condition: Condition,
pub(super) config: Config,
pub(super) _m: PhantomData<O>,
pub(super) _decision_window: PhantomData<Window>,
pub(super) _l: PhantomData<L>,
pub(super) _ctx: PhantomData<Ctx>,
pub(super) _lang: PhantomData<Lang>,
}
impl<F, SepClassifier, Condition, O, W, L, Ctx, Lang: ?Sized>
SeparatedBy<F, SepClassifier, Condition, O, W, L, Ctx, SeparatedByOptions, Lang>
{
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn new(f: F, sep_classifier: SepClassifier, condition: Condition) -> Self {
Self {
f,
sep: sep_classifier,
condition,
config: SeparatedByOptions::new(With::new((), ()), With::new((), ())),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
}
impl<F, SepClassifier, Condition, O, Options, Window, L, Ctx, Lang: ?Sized>
SeparatedBy<F, SepClassifier, Condition, O, Window, L, Ctx, Options, Lang>
{
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn as_mut(
&mut self,
) -> SeparatedBy<&mut F, &mut SepClassifier, &mut Condition, O, Window, L, Ctx, &mut Options, Lang>
{
SeparatedBy {
f: &mut self.f,
sep: &mut self.sep,
condition: &mut self.condition,
config: &mut self.config,
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn collect<Container>(self) -> Collect<Self, Container, Ctx, Lang>
where
Container: Default,
{
Collect::new(self, Container::default())
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn collect_with<Container>(
self,
container: Container,
) -> Collect<Self, Container, Ctx, Lang> {
Collect::new(self, container)
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub const fn delimited_by<Open, Close, Delim>(
self,
left: Open,
right: Close,
delim: Delim,
) -> DelimitedSeparatedBy<
F,
SepClassifier,
Condition,
Open,
Close,
Delim,
O,
Window,
L,
Ctx,
Options,
Lang,
> {
DelimitedSeparatedBy::new_in(self, left, right, delim)
}
}
impl<F, SepClassifier, Condition, O, Trailing, Leading, Max, Min, Window, L, Ctx, Lang: ?Sized>
SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Trailing, Leading, Max, Min>,
Lang,
>
{
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn allow_trailing(
self,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Allow, Leading, Max, Min>,
Lang,
>
where
Trailing: Apply<Allow>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
With::new(Allow(()), self.config.primary.secondary),
self.config.secondary,
),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn require_trailing(
self,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Require, Leading, Max, Min>,
Lang,
>
where
Trailing: Apply<Require>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
With::new(Require(()), self.config.primary.secondary),
self.config.secondary,
),
_m: PhantomData,
_decision_window: PhantomData,
_ctx: PhantomData,
_l: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn allow_leading(
self,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Trailing, Allow, Max, Min>,
Lang,
>
where
Leading: Apply<Allow>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
With::new(self.config.primary.primary, Allow(())),
self.config.secondary,
),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn require_leading(
self,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Trailing, Require, Max, Min>,
Lang,
>
where
Leading: Apply<Require>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
With::new(self.config.primary.primary, Require(())),
self.config.secondary,
),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn at_least(
self,
n: Min::Options,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Trailing, Leading, Max, Minimum>,
Lang,
>
where
Min: Apply<Minimum>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
self.config.primary,
With::new(
self.config.secondary.primary,
Min::apply(self.config.secondary.secondary, n),
),
),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub fn at_most(
self,
n: Max::Options,
) -> SeparatedBy<
F,
SepClassifier,
Condition,
O,
Window,
L,
Ctx,
SeparatedByOptions<Trailing, Leading, Maximum, Min>,
Lang,
>
where
Max: Apply<Maximum>,
{
SeparatedBy {
f: self.f,
sep: self.sep,
condition: self.condition,
config: SeparatedByOptions::new(
self.config.primary,
With::new(
Max::apply(self.config.secondary.primary, n),
self.config.secondary.secondary,
),
),
_m: PhantomData,
_decision_window: PhantomData,
_l: PhantomData,
_ctx: PhantomData,
_lang: PhantomData,
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(private_bounds)]
pub fn leading(&self) -> SepFixSpec
where
Leading: LeadingSpec,
{
Leading::leading(&self.config.primary.secondary)
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(private_bounds)]
pub fn trailing(&self) -> SepFixSpec
where
Trailing: TrailingSpec,
{
Trailing::trailing(&self.config.primary.primary)
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(private_bounds)]
pub fn minimum(&self) -> usize
where
Min: MinSpec,
{
Min::minimum(&self.config.secondary.secondary)
}
#[cfg_attr(not(tarpaulin), inline(always))]
#[allow(private_bounds)]
pub fn maximum(&self) -> usize
where
Max: MaxSpec,
{
Max::maximum(&self.config.secondary.primary)
}
}
impl Apply<Allow> for () {
type Options = ();
#[cfg_attr(not(tarpaulin), inline(always))]
fn apply(self, _: Self::Options) -> Allow {
Allow(())
}
}
impl Apply<Require> for () {
type Options = ();
#[cfg_attr(not(tarpaulin), inline(always))]
fn apply(self, _: Self::Options) -> Require {
Require(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant, Unwrap, TryUnwrap)]
pub enum SepFixSpec {
Deny(Deny),
Allow(Allow),
Require(Require),
}
pub(super) trait LeadingSpec {
fn leading(&self) -> SepFixSpec;
}
impl<T: LeadingSpec> LeadingSpec for &mut T {
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
(**self).leading()
}
}
impl LeadingSpec for Deny {
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
SepFixSpec::Deny(*self)
}
}
impl LeadingSpec for Allow {
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
SepFixSpec::Allow(*self)
}
}
impl LeadingSpec for Require {
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
SepFixSpec::Require(*self)
}
}
pub(super) trait TrailingSpec {
fn trailing(&self) -> SepFixSpec;
}
impl<T: TrailingSpec> TrailingSpec for &mut T {
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
(**self).trailing()
}
}
impl TrailingSpec for Deny {
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
SepFixSpec::Deny(*self)
}
}
impl TrailingSpec for Allow {
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
SepFixSpec::Allow(*self)
}
}
impl TrailingSpec for Require {
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
SepFixSpec::Require(*self)
}
}
impl TrailingSpec for () {
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
SepFixSpec::Deny(Deny(()))
}
}
impl LeadingSpec for () {
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
SepFixSpec::Deny(Deny(()))
}
}
impl<T, L, MAX, MIN> MaxSpec for SeparatedByOptions<T, L, MAX, MIN>
where
MAX: MaxSpec,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn maximum(&self) -> usize {
self.secondary.primary.maximum()
}
}
impl<T, L, MAX, MIN> MinSpec for SeparatedByOptions<T, L, MAX, MIN>
where
MIN: MinSpec,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn minimum(&self) -> usize {
self.secondary.secondary.minimum()
}
}
impl<T, L, MAX, MIN> TrailingSpec for SeparatedByOptions<T, L, MAX, MIN>
where
T: TrailingSpec,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn trailing(&self) -> SepFixSpec {
T::trailing(&self.primary.primary)
}
}
impl<T, L, MAX, MIN> LeadingSpec for SeparatedByOptions<T, L, MAX, MIN>
where
L: LeadingSpec,
{
#[cfg_attr(not(tarpaulin), inline(always))]
fn leading(&self) -> SepFixSpec {
L::leading(&self.primary.secondary)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, IsVariant)]
pub(super) enum State<T, S> {
Start,
Element,
Leading(Spanned<T, S>),
Leadings(S),
Separator(Spanned<T, S>),
RepeatedSeparator(S),
}