use crate::{
Cons, Either, Error, Except, Expect, Parse, Parser, Result, ToTokens, TokenIter, TokenStream,
TokenTree,
};
use std::any::TypeId;
use std::marker::PhantomData;
pub trait PredicateOp: Parser + ToTokens + Clone + 'static {}
#[derive(Debug, Clone, Default)]
pub struct Enable;
impl Parser for Enable {
#[inline]
#[mutants::skip] fn parser(_tokens: &mut TokenIter) -> Result<Self> {
Ok(Enable)
}
}
impl ToTokens for Enable {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {}
}
impl PredicateOp for Enable {}
#[derive(Debug, Clone)]
pub struct Disable;
impl Parser for Disable {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Error::unexpected_token(None, tokens)
}
}
impl ToTokens for Disable {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {}
}
impl PredicateOp for Disable {}
#[derive(Debug, Clone)]
pub struct TokensRemain;
impl Parser for TokensRemain {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Expect::<TokenTree>::parse(tokens)?;
Ok(TokensRemain)
}
}
impl ToTokens for TokensRemain {
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {}
}
impl Default for TokensRemain {
#[inline]
fn default() -> Self {
TokensRemain
}
}
impl PredicateOp for TokensRemain {}
#[derive(Debug, Clone)]
pub struct Not<T: PredicateOp>(Except<T>);
impl<T: PredicateOp> Parser for Not<T> {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Except::<T>::parse(tokens).map(Not)
}
}
impl<T: PredicateOp> ToTokens for Not<T> {
#[inline]
#[mutants::skip] fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<T: PredicateOp> Default for Not<T>
where
Except<T>: Default,
{
#[inline]
fn default() -> Self {
Not(Except::default())
}
}
impl<T: PredicateOp> PredicateOp for Not<T> {}
#[derive(Debug, Clone)]
pub struct AllOf<
A: PredicateOp,
B: PredicateOp,
C: PredicateOp + 'static = Enable,
D: PredicateOp + 'static = Enable,
>(Cons<A, B, C, D>);
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Parser for AllOf<A, B, C, D> {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Cons::<A, B, C, D>::parse(tokens).map(AllOf)
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> ToTokens
for AllOf<A, B, C, D>
{
#[inline]
#[mutants::skip] fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Default for AllOf<A, B, C, D>
where
Cons<A, B, C, D>: Default,
{
#[inline]
fn default() -> Self {
AllOf(Cons::default())
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> PredicateOp
for AllOf<A, B, C, D>
{
}
#[derive(Debug, Clone)]
pub struct AnyOf<
A: PredicateOp,
B: PredicateOp,
C: PredicateOp + 'static = Disable,
D: PredicateOp + 'static = Disable,
>(Either<A, B, C, D>);
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Parser for AnyOf<A, B, C, D> {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
Either::<A, B, C, D>::parse(tokens).map(AnyOf)
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> ToTokens
for AnyOf<A, B, C, D>
{
#[inline]
#[mutants::skip] fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Default for AnyOf<A, B, C, D>
where
Either<A, B, C, D>: Default,
{
#[inline]
fn default() -> Self {
AnyOf(Either::default())
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> PredicateOp
for AnyOf<A, B, C, D>
{
}
#[allow(clippy::type_complexity)]
#[derive(Debug, Clone)]
pub struct OneOf<
A: PredicateOp + 'static,
B: PredicateOp + 'static,
C: PredicateOp + 'static = Disable,
D: PredicateOp + 'static = Disable,
>(
AnyOf<
AllOf<A, Not<B>, Not<C>, Not<D>>,
AllOf<Not<A>, B, Not<C>, Not<D>>,
AllOf<Not<A>, Not<B>, C, Not<D>>,
AllOf<Not<A>, Not<B>, Not<C>, D>,
>,
);
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Parser for OneOf<A, B, C, D> {
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
AnyOf::<
AllOf<A, Not<B>, Not<C>, Not<D>>,
AllOf<Not<A>, B, Not<C>, Not<D>>,
AllOf<Not<A>, Not<B>, C, Not<D>>,
AllOf<Not<A>, Not<B>, Not<C>, D>,
>::parse(tokens)
.map(OneOf)
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> ToTokens
for OneOf<A, B, C, D>
{
#[inline]
#[mutants::skip] fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> Default for OneOf<A, B, C, D>
where
AnyOf<
AllOf<A, Not<B>, Not<C>, Not<D>>,
AllOf<Not<A>, B, Not<C>, Not<D>>,
AllOf<Not<A>, Not<B>, C, Not<D>>,
AllOf<Not<A>, Not<B>, Not<C>, D>,
>: Default,
{
#[inline]
fn default() -> Self {
OneOf(AnyOf::default())
}
}
impl<A: PredicateOp, B: PredicateOp, C: PredicateOp, D: PredicateOp> PredicateOp
for OneOf<A, B, C, D>
{
}
#[derive(Debug)]
pub struct PredicateCmp<
A: PredicateOp,
B: PredicateOp,
Same: PredicateOp = Enable,
Different: PredicateOp = Disable,
>(PhantomData<(A, B, Same, Different)>);
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> PredicateOp
for PredicateCmp<A, B, Same, Different>
{
}
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp>
PredicateCmp<A, B, Same, Different>
{
#[inline]
#[must_use]
pub const fn new() -> Self {
PredicateCmp(PhantomData)
}
}
#[mutants::skip]
#[allow(clippy::expl_impl_clone_on_copy)]
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> Clone
for PredicateCmp<A, B, Same, Different>
{
fn clone(&self) -> Self {
*self
}
}
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> Copy
for PredicateCmp<A, B, Same, Different>
{
}
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> Parser
for PredicateCmp<A, B, Same, Different>
{
#[inline]
fn parser(tokens: &mut TokenIter) -> Result<Self> {
if TypeId::of::<A>() == TypeId::of::<B>() {
Same::parse(tokens)?;
} else {
Different::parse(tokens)?;
}
Ok(Self(PhantomData))
}
}
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> ToTokens
for PredicateCmp<A, B, Same, Different>
{
#[inline]
fn to_tokens(&self, _tokens: &mut TokenStream) {
}
}
impl<A: PredicateOp, B: PredicateOp, Same: PredicateOp, Different: PredicateOp> Default
for PredicateCmp<A, B, Same, Different>
{
#[inline]
fn default() -> Self {
if TypeId::of::<A>() == TypeId::of::<B>() {
PredicateCmp(PhantomData)
} else {
panic!("PredicateCmp::default() called with mismatched types")
}
}
}