chasa 0.5.0

A parser combinator focused on rollback/commit, streaming inputs, and composable method chains.
Documentation
use ::std::ops;

pub trait ItemSet<Item> {
    type Copyable: ItemSet<Item>;

    fn has(&self, item: &Item) -> bool;
    fn into_copyable(self) -> Self::Copyable;

    fn cap<A: ItemSet<Item>>(self, other: A) -> Intersection<Self, A>
    where
        Self: Sized,
    {
        Intersection(self, other)
    }

    fn and<A: ItemSet<Item>>(self, other: A) -> Union<Self, A>
    where
        Self: Sized,
    {
        Union(self, other)
    }

    fn sub<A: ItemSet<Item>>(self, other: A) -> Difference<Self, A>
    where
        Self: Sized,
    {
        Difference(self, other)
    }

    fn complement(self) -> Complement<Self>
    where
        Self: Sized,
    {
        Complement(self)
    }
}

impl<'a> ItemSet<char> for &'a str {
    type Copyable = &'a str;

    fn has(&self, item: &char) -> bool {
        self.contains(*item)
    }

    fn into_copyable(self) -> Self::Copyable {
        self
    }
}

impl ItemSet<char> for char {
    type Copyable = char;

    fn has(&self, item: &char) -> bool {
        self == item
    }

    fn into_copyable(self) -> Self::Copyable {
        self
    }
}

impl<Item: Clone, F: Fn(Item) -> bool> ItemSet<Item> for F {
    type Copyable = F;

    fn has(&self, item: &Item) -> bool {
        self(item.clone())
    }

    fn into_copyable(self) -> Self::Copyable {
        self
    }
}

#[derive(Clone, Copy, Debug, Hash)]
pub struct Intersection<A, B>(pub A, pub B);
impl<Item, A: ItemSet<Item>, B: ItemSet<Item>> ItemSet<Item> for Intersection<A, B> {
    type Copyable = Intersection<A::Copyable, B::Copyable>;

    fn has(&self, item: &Item) -> bool {
        self.0.has(item) && self.1.has(item)
    }

    fn into_copyable(self) -> Self::Copyable {
        Intersection(self.0.into_copyable(), self.1.into_copyable())
    }
}

#[derive(Clone, Copy, Debug, Hash)]
pub struct Union<A, B>(pub A, pub B);
impl<Item, A: ItemSet<Item>, B: ItemSet<Item>> ItemSet<Item> for Union<A, B> {
    type Copyable = Union<A::Copyable, B::Copyable>;

    fn has(&self, item: &Item) -> bool {
        self.0.has(item) || self.1.has(item)
    }

    fn into_copyable(self) -> Self::Copyable {
        Union(self.0.into_copyable(), self.1.into_copyable())
    }
}

#[derive(Clone, Copy, Debug, Hash)]
pub struct Difference<A, B>(pub A, pub B);
impl<Item, A: ItemSet<Item>, B: ItemSet<Item>> ItemSet<Item> for Difference<A, B> {
    type Copyable = Difference<A::Copyable, B::Copyable>;

    fn has(&self, item: &Item) -> bool {
        self.0.has(item) && !self.1.has(item)
    }

    fn into_copyable(self) -> Self::Copyable {
        Difference(self.0.into_copyable(), self.1.into_copyable())
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Complement<A>(pub A);
impl<Item, A: ItemSet<Item>> ItemSet<Item> for Complement<A> {
    type Copyable = Complement<A::Copyable>;

    fn has(&self, item: &Item) -> bool {
        !self.0.has(item)
    }

    fn into_copyable(self) -> Self::Copyable {
        Complement(self.0.into_copyable())
    }
}

impl<T> ItemSet<T> for ops::RangeFull {
    type Copyable = ops::RangeFull;

    fn has(&self, _: &T) -> bool {
        true
    }

    fn into_copyable(self) -> Self::Copyable {
        self
    }
}

macro_rules! impl_range_same {
    ($Range:ident) => {
        impl<T: PartialOrd> ItemSet<T> for ops::$Range<T> {
            type Copyable = ops::$Range<T>;

            fn has(&self, item: &T) -> bool {
                self.contains(item)
            }

            fn into_copyable(self) -> Self::Copyable {
                self
            }
        }
    };
}

impl_range_same!(RangeTo);
impl_range_same!(RangeToInclusive);

macro_rules! impl_copy_range {
    ($StdRange:ident, $CopyRange:ident) => {
        impl<T: PartialOrd> ItemSet<T> for ops::$StdRange<T> {
            type Copyable = copy_range::$CopyRange<T>;

            fn has(&self, item: &T) -> bool {
                self.contains(item)
            }

            fn into_copyable(self) -> Self::Copyable {
                copy_range::$CopyRange::from_std(self)
            }
        }

        impl<T: PartialOrd> ItemSet<T> for copy_range::$CopyRange<T> {
            type Copyable = copy_range::$CopyRange<T>;

            fn has(&self, item: &T) -> bool {
                self.contains(item)
            }

            fn into_copyable(self) -> Self::Copyable {
                self
            }
        }
    };
}

impl_copy_range!(Range, CopyRange);
impl_copy_range!(RangeFrom, CopyRangeFrom);
impl_copy_range!(RangeInclusive, CopyRangeInclusive);