#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))]
#![feature(generic_associated_types)]
#![allow(incomplete_features)]
#![forbid(unsafe_code)]
#![no_std]
use core::{iter::FromIterator, slice};
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "parse")]
use core::str::FromStr;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub trait Reference<'e, E>: From<&'e E>
where
E: 'e + Expression,
{
fn cases(self) -> ExprRef<'e, E>;
#[allow(clippy::wrong_self_convention)]
#[must_use]
#[inline]
fn is_atom(self) -> bool
where
Self: Sized,
{
ExprRef::is_atom(&self.cases())
}
#[allow(clippy::wrong_self_convention)]
#[must_use]
#[inline]
fn is_group(self) -> bool
where
Self: Sized,
{
ExprRef::is_group(&self.cases())
}
#[must_use]
#[inline]
fn atom(self) -> Option<&'e E::Atom>
where
Self: Sized,
{
ExprRef::atom(self.cases())
}
#[must_use]
#[inline]
fn group(self) -> Option<GroupRef<'e, E>>
where
Self: Sized,
{
ExprRef::group(self.cases())
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
fn unwrap_atom(self) -> &'e E::Atom
where
Self: Sized,
{
ExprRef::unwrap_atom(self.cases())
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
fn unwrap_group(self) -> GroupRef<'e, E>
where
Self: Sized,
{
ExprRef::unwrap_group(self.cases())
}
#[allow(clippy::wrong_self_convention)]
#[inline]
fn to_owned(self) -> E
where
Self: Sized,
E::Atom: Clone,
E::Group: FromIterator<E>,
{
ExprRef::to_owned(self.cases())
}
#[inline]
fn substitute_ref<F>(self, f: F) -> E
where
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
ExprRef::substitute_ref(&self.cases(), f)
}
}
impl<'e, E> Reference<'e, E> for &'e E
where
E: Expression,
{
#[inline]
fn cases(self) -> ExprRef<'e, E> {
self.cases()
}
}
impl<'e, E> Reference<'e, E> for ExprRef<'e, E>
where
E: Expression,
{
#[inline]
fn cases(self) -> Self {
self
}
}
pub trait GroupReference<E>
where
E: Expression,
{
type Item<'e>: Reference<'e, E>
where
E: 'e;
type Iter<'e>: Iterator<Item = Self::Item<'e>>
where
E: 'e;
fn iter(&self) -> Self::Iter<'_>;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter().size_hint()
}
#[inline]
fn len(&self) -> Option<usize> {
let (min, max) = self.size_hint();
max.filter(move |m| *m == min)
}
#[inline]
fn is_empty(&self) -> bool {
matches!(self.len(), Some(0))
}
#[inline]
fn get(&self, index: usize) -> Option<Self::Item<'_>> {
self.iter().nth(index)
}
#[inline]
fn to_owned(&self) -> E::Group
where
E::Atom: Clone,
E::Group: FromIterator<E>,
{
self.iter().map(Reference::to_owned).collect()
}
#[inline]
fn substitute_ref<F>(&self, mut f: F) -> E::Group
where
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
ExprRef::substitute_ref_group_inner(self.iter(), &mut f)
}
}
impl<E> GroupReference<E> for &[E]
where
E: Expression,
{
type Item<'e>
where
E: 'e,
= &'e E;
type Iter<'e>
where
E: 'e,
= slice::Iter<'e, E>;
#[inline]
fn iter(&self) -> Self::Iter<'_> {
(self[..]).iter()
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<E> GroupReference<E> for &Vec<E>
where
E: Expression,
{
type Item<'e>
where
E: 'e,
= &'e E;
type Iter<'e>
where
E: 'e,
= slice::Iter<'e, E>;
#[inline]
fn iter(&self) -> Self::Iter<'_> {
(self[..]).iter()
}
}
pub trait Group<E>
where
E: Expression,
{
type Ref<'e>: GroupReference<E>
where
E: 'e;
fn reference(&self) -> Self::Ref<'_>;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.reference().size_hint()
}
#[inline]
fn len(&self) -> Option<usize> {
self.reference().len()
}
#[inline]
fn is_empty(&self) -> bool {
self.reference().is_empty()
}
#[inline]
fn empty() -> E::Group
where
E::Group: FromIterator<E>,
{
E::Group::from_iter(None)
}
#[inline]
fn clone(&self) -> E::Group
where
E::Atom: Clone,
E::Group: FromIterator<E>,
{
self.reference().to_owned()
}
#[inline]
fn substitute<F>(self, mut f: F) -> E::Group
where
Self: Sized + IntoIterator<Item = E>,
E::Group: FromIterator<E> + IntoIterator<Item = E>,
F: FnMut(E::Atom) -> E,
{
Expr::substitute_group_inner(self.into_iter(), &mut f)
}
#[inline]
fn substitute_ref<F>(&self, f: F) -> E::Group
where
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
self.reference().substitute_ref(f)
}
}
impl<E> Group<E> for [E]
where
E: Expression,
{
type Ref<'e>
where
E: 'e,
= &'e Self;
#[inline]
fn reference(&self) -> Self::Ref<'_> {
self
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl<E> Group<E> for Vec<E>
where
E: Expression,
{
type Ref<'e>
where
E: 'e,
= &'e Self;
#[inline]
fn reference(&self) -> Self::Ref<'_> {
self
}
}
pub type GroupRef<'e, E> = <<E as Expression>::Group as Group<E>>::Ref<'e>;
pub type GroupRefIter<'e, 'i, E> = <GroupRef<'e, E> as GroupReference<E>>::Iter<'i>;
pub type GroupRefItem<'e, 'i, E> = <GroupRef<'e, E> as GroupReference<E>>::Item<'i>;
pub trait Expression
where
Self: Into<Expr<Self>>,
{
type Atom;
type Group: Group<Self>;
fn cases(&self) -> ExprRef<Self>;
fn from_atom(atom: Self::Atom) -> Self;
fn from_group(group: Self::Group) -> Self;
#[must_use]
#[inline]
fn from_expr(expr: Expr<Self>) -> Self {
match expr {
Expr::Atom(atom) => Self::from_atom(atom),
Expr::Group(group) => Self::from_group(group),
}
}
#[cfg(feature = "parse")]
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
#[inline]
fn from_str(s: &str) -> parse::Result<Self, parse::FromCharactersParseError>
where
Self::Atom: FromIterator<char>,
Self::Group: FromIterator<Self>,
{
parse::from_str(s)
}
#[must_use]
#[inline]
fn is_atom(&self) -> bool {
ExprRef::is_atom(&self.cases())
}
#[must_use]
#[inline]
fn is_group(&self) -> bool {
ExprRef::is_group(&self.cases())
}
#[must_use]
#[inline]
fn atom(self) -> Option<Self::Atom> {
Expr::atom(self.into())
}
#[must_use]
#[inline]
fn atom_ref(&self) -> Option<&Self::Atom> {
ExprRef::atom(self.cases())
}
#[must_use]
#[inline]
fn group(self) -> Option<Self::Group> {
Expr::group(self.into())
}
#[must_use]
#[inline]
fn group_ref(&self) -> Option<GroupRef<Self>> {
ExprRef::group(self.cases())
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
fn unwrap_atom(self) -> Self::Atom {
Expr::unwrap_atom(self.into())
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
fn unwrap_group(self) -> Self::Group {
Expr::unwrap_group(self.into())
}
#[inline]
fn default_atom<T>() -> Self::Atom
where
Self::Atom: FromIterator<T>,
{
None.into_iter().collect()
}
#[inline]
fn default_group() -> Self::Group
where
Self::Group: FromIterator<Self>,
{
Self::Group::empty()
}
#[inline]
fn empty() -> Self
where
Self::Group: FromIterator<Self>,
{
Self::empty_group()
}
#[inline]
fn empty_atom<T>() -> Self
where
Self::Atom: FromIterator<T>,
{
Self::from_atom(Self::default_atom::<T>())
}
#[inline]
fn empty_group() -> Self
where
Self::Group: FromIterator<Self>,
{
Self::from_group(Self::default_group())
}
#[inline]
fn clone(&self) -> Self
where
Self::Atom: Clone,
Self::Group: FromIterator<Self>,
{
ExprRef::to_owned(self.cases())
}
#[inline]
fn eq<E>(&self, other: &E) -> bool
where
E: Expression,
Self::Atom: PartialEq<E::Atom>,
{
self.cases().eq(&other.cases())
}
#[inline]
fn is_subexpression<E>(&self, other: &E) -> bool
where
E: Expression,
Self::Atom: PartialEq<E::Atom>,
{
self.cases().is_subexpression(&other.cases())
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
#[inline]
fn matches<P>(&self, pattern: P) -> bool
where
P: pattern::Pattern<Self>,
{
pattern.matches(self)
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
#[inline]
fn matches_equal<P>(&self, pattern: &P) -> bool
where
P: Expression,
P::Atom: PartialEq<Self::Atom>,
{
self.matches(pattern::EqualExpressionPattern::new(pattern))
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
#[inline]
fn matches_subexpression<P>(&self, pattern: &P) -> bool
where
P: Expression,
P::Atom: PartialEq<Self::Atom>,
{
self.matches(pattern::SubExpressionPattern::new(pattern))
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
#[inline]
fn matches_basic_shape<P>(&self, pattern: &P) -> bool
where
P: Expression<Atom = pattern::BasicShape>,
P::Atom: PartialEq<Self::Atom>,
{
self.matches(pattern::BasicShapePattern::new(pattern))
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
#[inline]
fn matches_wildcard<W, P>(&self, is_wildcard: W, pattern: &P) -> bool
where
P: Expression,
P::Atom: PartialEq<Self::Atom>,
W: Fn(&P::Atom) -> bool,
{
self.matches(pattern::WildCardPattern::new(is_wildcard, pattern))
}
#[inline]
fn map<E, F>(self, f: F) -> E
where
Self::Group: IntoIterator<Item = Self>,
E: Expression,
E::Group: FromIterator<E>,
F: FnMut(Self::Atom) -> E::Atom,
{
Expr::map(self.into(), f)
}
#[inline]
fn map_ref<E, F>(&self, f: F) -> E
where
E: Expression,
E::Group: FromIterator<E>,
F: FnMut(&Self::Atom) -> E::Atom,
{
ExprRef::map_ref(&self.cases(), f)
}
#[inline]
fn substitute<F>(self, f: F) -> Self
where
Self::Group: FromIterator<Self> + IntoIterator<Item = Self>,
F: FnMut(Self::Atom) -> Self,
{
Expr::substitute(self.into(), f)
}
#[inline]
fn substitute_ref<F>(&self, f: F) -> Self
where
Self::Group: FromIterator<Self>,
F: FnMut(&Self::Atom) -> Self,
{
ExprRef::substitute_ref(&self.cases(), f)
}
}
#[cfg(feature = "multi")]
#[cfg_attr(docsrs, doc(cfg(feature = "multi")))]
pub mod multi {
use super::*;
pub trait MultiGroupReference<E>: GroupReference<E>
where
E: Expression,
{
type Kind<'e>;
fn kind(&self) -> Self::Kind<'_>;
}
pub trait MultiGroup<E>: Group<E>
where
E: Expression,
{
type MultiRef<'e>: MultiGroupReference<E>
where
E: 'e;
fn multi_reference(&self) -> Self::MultiRef<'_>;
}
pub trait MultiExpression: Expression
where
<Self as Expression>::Group: MultiGroup<Self>,
{
}
}
pub enum ExprRef<'e, E>
where
E: 'e + Expression,
{
Atom(&'e E::Atom),
Group(GroupRef<'e, E>),
}
impl<'e, E> ExprRef<'e, E>
where
E: Expression,
{
#[must_use]
#[inline]
pub fn is_atom(&self) -> bool {
matches!(self, Self::Atom(_))
}
#[must_use]
#[inline]
pub fn is_group(&self) -> bool {
matches!(self, Self::Group(_))
}
#[must_use]
#[inline]
pub fn atom(self) -> Option<&'e E::Atom> {
match self {
Self::Atom(atom) => Some(atom),
_ => None,
}
}
#[must_use]
#[inline]
pub fn atom_ref(&self) -> Option<&'e E::Atom> {
match self {
Self::Atom(atom) => Some(atom),
_ => None,
}
}
#[must_use]
#[inline]
pub fn group(self) -> Option<GroupRef<'e, E>> {
match self {
Self::Group(group) => Some(group),
_ => None,
}
}
#[must_use]
#[inline]
pub fn group_ref(&self) -> Option<&GroupRef<'e, E>> {
match self {
Self::Group(group) => Some(group),
_ => None,
}
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn unwrap_atom(self) -> &'e E::Atom {
self.atom().unwrap()
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn unwrap_group(self) -> GroupRef<'e, E> {
self.group().unwrap()
}
pub fn is_subexpression<'r, R>(&self, other: &ExprRef<'r, R>) -> bool
where
R: Expression,
E::Atom: PartialEq<R::Atom>,
{
match self {
Self::Atom(atom) => match other {
ExprRef::Atom(other) => atom == other,
ExprRef::Group(other) => {
other.iter().any(move |e| self.is_subexpression(&e.cases()))
}
},
Self::Group(group) => match other {
ExprRef::Atom(_) => false,
ExprRef::Group(other) => {
other.iter().any(move |e| self.is_subexpression(&e.cases()))
|| Self::eq_groups::<R>(group, other)
}
},
}
}
#[allow(clippy::wrong_self_convention)]
#[inline]
pub fn to_owned(self) -> E
where
E::Atom: Clone,
E::Group: FromIterator<E>,
{
E::from_expr(self.into())
}
#[inline]
pub fn map_ref<O, F>(&self, mut f: F) -> O
where
O: Expression,
O::Group: FromIterator<O>,
F: FnMut(&E::Atom) -> O::Atom,
{
self.map_ref_inner(&mut f)
}
#[inline]
fn map_ref_inner<O, F>(&self, f: &mut F) -> O
where
O: Expression,
O::Group: FromIterator<O>,
F: FnMut(&E::Atom) -> O::Atom,
{
match self {
Self::Atom(atom) => O::from_atom(f(atom)),
Self::Group(group) => O::from_group(
group
.iter()
.map(move |e| e.cases().map_ref_inner(f))
.collect(),
),
}
}
#[inline]
pub fn substitute_ref<F>(&self, mut f: F) -> E
where
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
self.substitute_ref_inner(&mut f)
}
#[inline]
fn substitute_ref_group_inner<I, F>(iter: I, f: &mut F) -> E::Group
where
E: 'e,
I: Iterator,
I::Item: Reference<'e, E>,
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
iter.map(move |e| e.cases().substitute_ref_inner(f))
.collect()
}
#[inline]
fn substitute_ref_inner<F>(&self, f: &mut F) -> E
where
E::Group: FromIterator<E>,
F: FnMut(&E::Atom) -> E,
{
match self {
Self::Atom(atom) => f(atom),
Self::Group(group) => {
E::from_group(ExprRef::substitute_ref_group_inner(group.iter(), f))
}
}
}
#[inline]
pub fn eq_groups<'r, R>(lhs: &GroupRef<'e, E>, rhs: &GroupRef<'r, R>) -> bool
where
R: Expression,
E::Atom: PartialEq<R::Atom>,
{
util::eq_by(lhs.iter(), rhs.iter(), move |l, r| l.cases().eq(&r.cases()))
}
}
impl<'e, E> Clone for ExprRef<'e, E>
where
E: Expression,
GroupRef<'e, E>: Clone,
{
#[inline]
fn clone(&self) -> Self {
match &self {
Self::Atom(atom) => Self::Atom(atom),
Self::Group(group) => Self::Group(group.clone()),
}
}
}
impl<'e, E> Copy for ExprRef<'e, E>
where
E: Expression,
GroupRef<'e, E>: Copy,
{
}
impl<'l, 'r, L, R> PartialEq<ExprRef<'r, R>> for ExprRef<'l, L>
where
L: Expression,
R: Expression,
L::Atom: PartialEq<R::Atom>,
{
fn eq(&self, other: &ExprRef<'r, R>) -> bool {
match (self, other) {
(Self::Atom(lhs), ExprRef::Atom(rhs)) => *lhs == *rhs,
(Self::Group(lhs), ExprRef::Group(rhs)) => Self::eq_groups::<R>(lhs, rhs),
_ => false,
}
}
}
impl<'e, E> From<&'e E> for ExprRef<'e, E>
where
E: Expression,
{
#[inline]
fn from(expr: &'e E) -> Self {
expr.cases()
}
}
impl<'e, E> From<&'e Expr<E>> for ExprRef<'e, E>
where
E: Expression,
{
#[must_use]
#[inline]
fn from(expr: &'e Expr<E>) -> Self {
match expr {
Expr::Atom(atom) => Self::Atom(atom),
Expr::Group(group) => Self::Group(group.reference()),
}
}
}
#[derive(Debug)]
pub enum Expr<E>
where
E: Expression,
{
Atom(E::Atom),
Group(E::Group),
}
impl<E> Expr<E>
where
E: Expression,
{
#[must_use]
#[inline]
pub fn is_atom(&self) -> bool {
matches!(self, Expr::Atom(_))
}
#[must_use]
#[inline]
pub fn is_group(&self) -> bool {
matches!(self, Expr::Group(_))
}
#[must_use]
#[inline]
pub fn atom(self) -> Option<E::Atom> {
match self {
Expr::Atom(atom) => Some(atom),
_ => None,
}
}
#[must_use]
#[inline]
pub fn atom_ref(&self) -> Option<&E::Atom> {
match self {
Expr::Atom(atom) => Some(atom),
_ => None,
}
}
#[must_use]
#[inline]
pub fn group(self) -> Option<E::Group> {
match self {
Expr::Group(group) => Some(group),
_ => None,
}
}
#[must_use]
#[inline]
pub fn group_ref(&self) -> Option<&E::Group> {
match self {
Expr::Group(group) => Some(group),
_ => None,
}
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn unwrap_atom(self) -> E::Atom {
self.atom().unwrap()
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn unwrap_group(self) -> E::Group {
self.group().unwrap()
}
#[inline]
pub fn map<O, F>(self, mut f: F) -> O
where
E::Group: IntoIterator<Item = E>,
O: Expression,
O::Group: FromIterator<O>,
F: FnMut(E::Atom) -> O::Atom,
{
self.map_inner(&mut f)
}
fn map_inner<O, F>(self, f: &mut F) -> O
where
E::Group: IntoIterator<Item = E>,
O: Expression,
O::Group: FromIterator<O>,
F: FnMut(E::Atom) -> O::Atom,
{
match self {
Self::Atom(atom) => O::from_atom(f(atom)),
Self::Group(group) => O::from_group(
group
.into_iter()
.map(move |e| e.into().map_inner(f))
.collect(),
),
}
}
#[inline]
pub fn substitute<F>(self, mut f: F) -> E
where
E::Group: FromIterator<E> + IntoIterator<Item = E>,
F: FnMut(E::Atom) -> E,
{
self.substitute_inner(&mut f)
}
#[inline]
fn substitute_group_inner<I, F>(iter: I, f: &mut F) -> E::Group
where
I: Iterator<Item = E>,
E::Group: FromIterator<E> + IntoIterator<Item = E>,
F: FnMut(E::Atom) -> E,
{
iter.map(move |e| e.into().substitute_inner(f)).collect()
}
#[inline]
fn substitute_inner<F>(self, f: &mut F) -> E
where
E::Group: FromIterator<E> + IntoIterator<Item = E>,
F: FnMut(E::Atom) -> E,
{
match self {
Self::Atom(atom) => f(atom),
Self::Group(group) => E::from_group(Self::substitute_group_inner(group.into_iter(), f)),
}
}
}
impl<E> Clone for Expr<E>
where
E: Expression,
E::Atom: Clone,
E::Group: FromIterator<E>,
{
#[inline]
fn clone(&self) -> Self {
match self {
Self::Atom(atom) => Self::Atom(atom.clone()),
Self::Group(group) => Self::Group(group.clone()),
}
}
}
impl<E> Default for Expr<E>
where
E: Expression,
E::Group: FromIterator<E>,
{
#[inline]
fn default() -> Self {
E::empty().into()
}
}
impl<L, R> PartialEq<Expr<R>> for Expr<L>
where
L: Expression,
R: Expression,
L::Atom: PartialEq<R::Atom>,
{
#[inline]
fn eq(&self, other: &Expr<R>) -> bool {
ExprRef::from(self).eq(&ExprRef::from(other))
}
}
impl<E> Eq for Expr<E>
where
E: Expression,
E::Atom: PartialEq,
{
}
impl<'e, E> From<ExprRef<'e, E>> for Expr<E>
where
E: Expression,
E::Atom: Clone,
E::Group: FromIterator<E>,
{
#[must_use]
#[inline]
fn from(expr: ExprRef<'e, E>) -> Self {
match expr {
ExprRef::Atom(atom) => Self::Atom(atom.clone()),
ExprRef::Group(group) => Self::Group(group.to_owned()),
}
}
}
#[cfg(feature = "parse")]
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
impl<E> FromStr for Expr<E>
where
E: Expression,
E::Atom: FromIterator<char>,
E::Group: FromIterator<E>,
{
type Err = parse::Error<parse::FromCharactersParseError>;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
E::from_str(s).map(E::into)
}
}
pub mod util {
pub fn eq_by<L, R, F>(lhs: L, rhs: R, mut eq: F) -> bool
where
L: IntoIterator,
R: IntoIterator,
F: FnMut(L::Item, R::Item) -> bool,
{
let mut lhs = lhs.into_iter();
let mut rhs = rhs.into_iter();
loop {
let x = match lhs.next() {
None => return rhs.next().is_none(),
Some(val) => val,
};
let y = match rhs.next() {
None => return false,
Some(val) => val,
};
if !eq(x, y) {
return false;
}
}
}
}
#[cfg(feature = "parse")]
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
pub mod parse {
use {
super::Expression,
core::{
iter::{empty, from_fn, FromIterator, Peekable},
result,
},
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Error<A> {
TooManyExpressions,
OpenGroup,
UnopenedGroup,
BadEmptyGroup,
LeadingWhitespace,
TrailingSymbols,
BadOpenGroup,
BadStartAtom,
AtomParseError(A),
}
impl<A> From<A> for Error<A> {
#[inline]
fn from(err: A) -> Self {
Self::AtomParseError(err)
}
}
pub type Result<T, A> = result::Result<T, Error<A>>;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SymbolType {
Whitespace,
GroupOpen,
GroupClose,
Other,
}
pub trait Parser<T, E>
where
E: Expression,
{
type AtomParseError;
fn classify(term: &T) -> SymbolType;
fn parse<I>(iter: I) -> Result<E, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: IntoIterator<Item = T>,
{
let mut iter = iter.into_iter().peekable();
if let Some(true) = iter
.peek()
.map(move |p| Self::classify(p) == SymbolType::Whitespace)
{
return Err(Error::LeadingWhitespace);
}
let expr = Self::parse_continue(&mut iter);
iter.next()
.map(move |_| Err(Error::TooManyExpressions))
.unwrap_or(expr)
}
fn parse_continue<I>(iter: &mut Peekable<I>) -> Result<E, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: Iterator<Item = T>,
{
match iter.peek() {
Some(peek) => match Self::classify(&peek) {
SymbolType::GroupClose => Err(Error::UnopenedGroup),
SymbolType::GroupOpen => Self::parse_group_expression_continue(iter),
_ => Self::parse_atom_expression_continue(iter),
},
_ => Self::parse_atom_expression_continue(&mut empty().peekable()),
}
}
fn parse_atom<I>(iter: I) -> Result<E::Atom, Self::AtomParseError>
where
I: IntoIterator<Item = T>,
{
let mut iter = iter.into_iter().peekable();
if let Some(peek) = iter.peek() {
match Self::classify(&peek) {
SymbolType::Whitespace => return Err(Error::LeadingWhitespace),
SymbolType::GroupClose => return Err(Error::UnopenedGroup),
SymbolType::GroupOpen => return Err(Error::BadOpenGroup),
_ => {}
}
}
let atom = Self::parse_atom_continue(&mut iter);
iter.next()
.map(move |_| Err(Error::TrailingSymbols))
.unwrap_or_else(|| atom.map_err(Into::into))
}
#[inline]
fn parse_atom_expression<I>(iter: I) -> Result<E, Self::AtomParseError>
where
I: IntoIterator<Item = T>,
{
Self::parse_atom(iter).map(E::from_atom)
}
fn parse_atom_continue<I>(
iter: &mut Peekable<I>,
) -> result::Result<E::Atom, Self::AtomParseError>
where
I: Iterator<Item = T>;
#[inline]
fn parse_atom_expression_continue<I>(
iter: &mut Peekable<I>,
) -> Result<E, Self::AtomParseError>
where
I: Iterator<Item = T>,
{
Self::parse_atom_continue(iter)
.map(E::from_atom)
.map_err(Into::into)
}
fn parse_group<I>(iter: I) -> Result<E::Group, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: IntoIterator<Item = T>,
{
let mut iter = iter.into_iter().peekable();
let group = Self::parse_group_continue(&mut iter);
iter.next()
.map(move |_| Err(Error::TrailingSymbols))
.unwrap_or(group)
}
#[inline]
fn parse_group_expression<I>(iter: I) -> Result<E, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: IntoIterator<Item = T>,
{
Self::parse_group(iter).map(E::from_group)
}
#[inline]
fn parse_group_continue<I>(iter: &mut Peekable<I>) -> Result<E::Group, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: Iterator<Item = T>,
{
parse_group_continue_impl::<_, _, _, E, _>(
iter,
&Self::classify,
&Self::parse_atom_expression_continue,
)
}
fn parse_group_expression_continue<I>(
iter: &mut Peekable<I>,
) -> Result<E, Self::AtomParseError>
where
E::Group: FromIterator<E>,
I: Iterator<Item = T>,
{
Self::parse_group_continue(iter).map(E::from_group)
}
}
fn parse_group_continue_impl<I, C, P, E, AE>(
iter: &mut Peekable<I>,
classify: &C,
parse_atom_expression_continue: &P,
) -> Result<E::Group, AE>
where
I: Iterator,
C: Fn(&I::Item) -> SymbolType,
P: Fn(&mut Peekable<I>) -> Result<E, AE>,
E: Expression,
E::Group: FromIterator<E>,
{
match iter.peek() {
Some(peek) => match classify(&peek) {
SymbolType::Whitespace => Err(Error::LeadingWhitespace),
SymbolType::GroupClose => Err(Error::UnopenedGroup),
SymbolType::GroupOpen => {
let _ = iter.next();
from_fn(parse_group_continue_inner_impl(
iter,
classify,
parse_atom_expression_continue,
))
.collect()
}
_ => Err(Error::BadStartAtom),
},
_ => Err(Error::BadEmptyGroup),
}
}
#[inline]
fn parse_group_continue_inner_impl<'i, I, C, P, E, AE>(
iter: &'i mut Peekable<I>,
classify: &'i C,
parse_atom_expression_continue: &'i P,
) -> impl 'i + FnMut() -> Option<Result<E, AE>>
where
I: Iterator,
C: Fn(&I::Item) -> SymbolType,
P: Fn(&mut Peekable<I>) -> Result<E, AE>,
E: Expression,
E::Group: FromIterator<E>,
{
move || loop {
match iter.peek() {
Some(peek) => match classify(&peek) {
SymbolType::Whitespace => {
let _ = iter.next();
}
SymbolType::GroupClose => {
let _ = iter.next();
return None;
}
SymbolType::GroupOpen => {
return Some(
parse_group_continue_impl(
iter,
classify,
parse_atom_expression_continue,
)
.map(E::from_group),
);
}
_ => return Some(parse_atom_expression_continue(iter)),
},
_ => return Some(Err(Error::OpenGroup)),
}
}
}
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct FromCharacters(());
impl FromCharacters {
#[inline]
fn is_quote(c: &char) -> bool {
*c == '"'
}
#[inline]
fn classify_char(c: &char) -> SymbolType {
match c {
'(' => SymbolType::GroupOpen,
')' => SymbolType::GroupClose,
_ => {
if c.is_whitespace() {
SymbolType::Whitespace
} else {
SymbolType::Other
}
}
}
}
#[inline]
fn parse_atom_continue_inner<'i, I>(
iter: &'i mut Peekable<I>,
inside_quote: &'i mut bool,
) -> impl 'i + FnMut() -> Option<char>
where
I: Iterator<Item = char>,
{
move || match iter.peek() {
Some(peek) => {
if *inside_quote {
if Self::is_quote(&peek) {
*inside_quote = false;
}
} else {
match Self::classify_char(&peek) {
SymbolType::Other => {
if Self::is_quote(&peek) {
*inside_quote = true;
}
}
_ => return None,
}
}
iter.next()
}
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum FromCharactersParseError {
MissingClosingQuote,
}
impl<E> Parser<char, E> for FromCharacters
where
E: Expression,
E::Atom: FromIterator<char>,
{
type AtomParseError = FromCharactersParseError;
#[inline]
fn classify(term: &char) -> SymbolType {
Self::classify_char(term)
}
#[inline]
fn parse_atom_continue<I>(
iter: &mut Peekable<I>,
) -> result::Result<E::Atom, Self::AtomParseError>
where
I: Iterator<Item = char>,
{
let mut inside_quote = false;
let atom = from_fn(Self::parse_atom_continue_inner(iter, &mut inside_quote)).collect();
if inside_quote {
Err(Self::AtomParseError::MissingClosingQuote)
} else {
Ok(atom)
}
}
}
#[inline]
pub fn from_chars<I, E>(iter: I) -> Result<E, FromCharactersParseError>
where
I: IntoIterator<Item = char>,
E: Expression,
E::Atom: FromIterator<char>,
E::Group: FromIterator<E>,
{
FromCharacters::parse(iter)
}
#[inline]
pub fn from_str<S, E>(s: S) -> Result<E, FromCharactersParseError>
where
S: AsRef<str>,
E: Expression,
E::Atom: FromIterator<char>,
E::Group: FromIterator<E>,
{
from_chars(s.as_ref().chars())
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn from_chars_as_group<I, E>(iter: I) -> Result<E::Group, FromCharactersParseError>
where
I: IntoIterator<Item = char>,
E: Expression,
E::Atom: FromIterator<char>,
E::Group: FromIterator<E>,
{
from_chars(Some('(').into_iter().chain(iter).chain(Some(')'))).map(E::unwrap_group)
}
#[cfg(not(feature = "no-panic"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "no-panic"))))]
#[inline]
#[track_caller]
pub fn from_str_as_group<S, E>(s: S) -> Result<E::Group, FromCharactersParseError>
where
S: AsRef<str>,
E: Expression,
E::Atom: FromIterator<char>,
E::Group: FromIterator<E>,
{
from_chars_as_group::<_, E>(s.as_ref().chars())
}
}
#[cfg(feature = "shape")]
#[cfg_attr(docsrs, doc(cfg(feature = "shape")))]
pub mod shape {
use {
super::*,
core::convert::{TryFrom, TryInto},
};
pub trait Matcher<E>
where
E: Expression,
{
type Error;
fn matches_atom(atom: &E::Atom) -> Result<(), Self::Error>;
fn matches_group(group: GroupRef<E>) -> Result<(), Self::Error>;
#[inline]
fn matches(expr: &E) -> Result<(), Self::Error> {
match expr.cases() {
ExprRef::Atom(atom) => Self::matches_atom(atom),
ExprRef::Group(group) => Self::matches_group(group),
}
}
}
pub trait Shape<E>: Matcher<E>
where
E: Expression,
Self: Into<Expr<E>> + TryFrom<Expr<E>, Error = <Self as Matcher<E>>::Error>,
{
#[inline]
fn parse_atom(atom: E::Atom) -> Result<Self, <Self as Matcher<E>>::Error> {
Expr::Atom(atom).try_into()
}
#[inline]
fn parse_group(group: E::Group) -> Result<Self, <Self as Matcher<E>>::Error> {
Expr::Group(group).try_into()
}
#[inline]
fn parse_expr(expr: E) -> Result<Self, <Self as Matcher<E>>::Error> {
expr.into().try_into()
}
}
}
#[cfg(feature = "pattern")]
#[cfg_attr(docsrs, doc(cfg(feature = "pattern")))]
pub mod pattern {
use super::*;
pub trait Pattern<E>
where
E: Expression,
{
fn matches_atom(&self, atom: &E::Atom) -> bool;
fn matches_group(&self, group: GroupRef<E>) -> bool;
#[inline]
fn matches(&self, expr: &E) -> bool {
match expr.cases() {
ExprRef::Atom(atom) => self.matches_atom(atom),
ExprRef::Group(group) => self.matches_group(group),
}
}
}
pub trait PatternMut<E>
where
E: Expression,
{
fn matches_atom(&mut self, atom: &E::Atom) -> bool;
fn matches_group(&mut self, group: GroupRef<E>) -> bool;
#[inline]
fn matches(&mut self, expr: &E) -> bool {
match expr.cases() {
ExprRef::Atom(atom) => self.matches_atom(atom),
ExprRef::Group(group) => self.matches_group(group),
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct EqualExpressionPattern<'p, P>(&'p P)
where
P: Expression;
impl<'p, P> EqualExpressionPattern<'p, P>
where
P: Expression,
{
#[inline]
pub(crate) fn new(pattern: &'p P) -> Self {
Self(pattern)
}
}
impl<'p, P, E> Pattern<E> for EqualExpressionPattern<'p, P>
where
E: Expression,
P: Expression,
P::Atom: PartialEq<E::Atom>,
{
#[inline]
fn matches_atom(&self, atom: &E::Atom) -> bool {
self.0.atom().map_or(false, |a| a == atom)
}
#[inline]
fn matches_group(&self, group: GroupRef<E>) -> bool {
self.0
.group()
.map_or(false, move |g| ExprRef::<P>::eq_groups::<E>(&g, &group))
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SubExpressionPattern<'p, P>(&'p P)
where
P: Expression;
impl<'p, P> SubExpressionPattern<'p, P>
where
P: 'p + Expression,
{
#[inline]
pub(crate) fn new(pattern: &'p P) -> Self {
Self(pattern)
}
#[inline]
fn matches_atom<E>(pattern: &ExprRef<'_, P>, atom: &E::Atom) -> bool
where
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match pattern.atom_ref() {
Some(pattern_atom) => pattern_atom == atom,
_ => false,
}
}
fn matches_group<E>(pattern: &ExprRef<P>, group: GroupRef<E>) -> bool
where
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match pattern.group_ref() {
Some(pattern_group) => {
group
.iter()
.any(move |e| Self::matches(&pattern, e.cases()))
|| ExprRef::<P>::eq_groups::<E>(&pattern_group, &group)
}
_ => group
.iter()
.any(move |e| Self::matches(&pattern, e.cases())),
}
}
#[inline]
fn matches<E>(pattern: &ExprRef<'_, P>, expr: ExprRef<'_, E>) -> bool
where
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match expr {
ExprRef::Atom(atom) => Self::matches_atom::<E>(pattern, atom),
ExprRef::Group(group) => Self::matches_group::<E>(pattern, group),
}
}
}
impl<'p, P, E> Pattern<E> for SubExpressionPattern<'p, P>
where
E: Expression,
P: Expression,
P::Atom: PartialEq<E::Atom>,
{
#[inline]
fn matches_atom(&self, atom: &E::Atom) -> bool {
Self::matches_atom::<E>(&self.0.cases(), atom)
}
#[inline]
fn matches_group(&self, group: GroupRef<E>) -> bool {
Self::matches_group::<E>(&self.0.cases(), group)
}
#[inline]
fn matches(&self, expr: &E) -> bool {
Self::matches(&self.0.cases(), expr.cases())
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct WildCardPattern<'p, W, P>(W, &'p P)
where
P: Expression,
W: FnMut(&P::Atom) -> bool;
impl<'p, W, P> WildCardPattern<'p, W, P>
where
P: 'p + Expression,
W: FnMut(&P::Atom) -> bool,
{
#[inline]
pub(crate) fn new(is_wildcard: W, pattern: &'p P) -> Self {
Self(is_wildcard, pattern)
}
#[inline]
fn matches_atom<F, E>(is_wildcard: F, pattern: &ExprRef<'_, P>, atom: &E::Atom) -> bool
where
F: FnOnce(&P::Atom) -> bool,
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match pattern.atom_ref() {
Some(pattern_atom) => is_wildcard(pattern_atom) || pattern_atom == atom,
_ => false,
}
}
fn matches_group<F, E>(mut is_wildcard: F, pattern: &ExprRef<P>, group: GroupRef<E>) -> bool
where
F: FnMut(&P::Atom) -> bool,
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match pattern {
ExprRef::Atom(pattern_atom) if is_wildcard(pattern_atom) => true,
ExprRef::Atom(_) => group
.iter()
.any(move |e| Self::matches(&mut is_wildcard, pattern, e.cases())),
ExprRef::Group(pattern_group) => {
group
.iter()
.any(|e| Self::matches(&mut is_wildcard, pattern, e.cases()))
|| util::eq_by(pattern_group.iter(), group.iter(), |p, e| {
Self::wildcard_equality(&mut is_wildcard, &p.cases(), &e.cases())
})
}
}
}
#[inline]
fn matches<F, E>(is_wildcard: F, pattern: &ExprRef<'_, P>, expr: ExprRef<'_, E>) -> bool
where
F: FnMut(&P::Atom) -> bool,
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match expr {
ExprRef::Atom(atom) => Self::matches_atom::<_, E>(is_wildcard, pattern, atom),
ExprRef::Group(group) => Self::matches_group::<_, E>(is_wildcard, pattern, group),
}
}
fn wildcard_equality<F, E>(
is_wildcard: &mut F,
pattern: &ExprRef<'_, P>,
expr: &ExprRef<'_, E>,
) -> bool
where
F: FnMut(&P::Atom) -> bool,
E: Expression,
P::Atom: PartialEq<E::Atom>,
{
match pattern {
ExprRef::Atom(pattern_atom) => {
is_wildcard(pattern_atom)
|| expr.atom_ref().map_or(false, move |a| *pattern_atom == a)
}
ExprRef::Group(pattern_group) => match expr.group_ref() {
Some(group) => util::eq_by(pattern_group.iter(), group.iter(), move |p, e| {
Self::wildcard_equality(is_wildcard, &p.cases(), &e.cases())
}),
_ => false,
},
}
}
}
impl<'p, W, P, E> Pattern<E> for WildCardPattern<'p, W, P>
where
E: Expression,
W: Fn(&P::Atom) -> bool,
P: Expression,
P::Atom: PartialEq<E::Atom>,
{
#[inline]
fn matches_atom(&self, atom: &E::Atom) -> bool {
Self::matches_atom::<_, E>(&self.0, &self.1.cases(), atom)
}
#[inline]
fn matches_group(&self, group: GroupRef<E>) -> bool {
Self::matches_group::<_, E>(&self.0, &self.1.cases(), group)
}
#[inline]
fn matches(&self, expr: &E) -> bool {
Self::matches(&self.0, &self.1.cases(), expr.cases())
}
}
impl<'p, W, P, E> PatternMut<E> for WildCardPattern<'p, W, P>
where
E: Expression,
W: FnMut(&P::Atom) -> bool,
P: Expression,
P::Atom: PartialEq<E::Atom>,
{
#[inline]
fn matches_atom(&mut self, atom: &E::Atom) -> bool {
Self::matches_atom::<_, E>(&mut self.0, &self.1.cases(), atom)
}
#[inline]
fn matches_group(&mut self, group: GroupRef<E>) -> bool {
Self::matches_group::<_, E>(&mut self.0, &self.1.cases(), group)
}
#[inline]
fn matches(&mut self, expr: &E) -> bool {
Self::matches(&mut self.0, &self.1.cases(), expr.cases())
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum BasicShape {
Atom,
Group,
Expr,
}
impl Default for BasicShape {
#[inline]
fn default() -> Self {
Self::Expr
}
}
impl BasicShape {
#[inline]
pub fn matches_atom(&self) -> bool {
matches!(self, Self::Expr | Self::Atom)
}
#[inline]
pub fn matches_group(&self) -> bool {
matches!(self, Self::Expr | Self::Group)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct BasicShapePattern<'p, P>(&'p P)
where
P: Expression<Atom = BasicShape>;
impl<'p, P> BasicShapePattern<'p, P>
where
P: 'p + Expression<Atom = BasicShape>,
{
#[inline]
pub(crate) fn new(pattern: &'p P) -> Self {
Self(pattern)
}
#[inline]
fn matches_atom<E>(pattern: ExprRef<'_, P>, atom: &E::Atom) -> bool
where
E: Expression,
{
let _ = atom;
pattern.atom().map_or(false, BasicShape::matches_atom)
}
fn matches_group<E>(pattern: ExprRef<P>, group: GroupRef<E>) -> bool
where
E: Expression,
{
match pattern.cases() {
ExprRef::Atom(pattern_atom) => pattern_atom.matches_group(),
ExprRef::Group(pattern_group) => {
util::eq_by(pattern_group.iter(), group.iter(), move |p, e| {
Self::matches(p.cases(), e.cases())
})
}
}
}
#[inline]
fn matches<E>(pattern: ExprRef<'_, P>, expr: ExprRef<'_, E>) -> bool
where
E: Expression,
{
match expr {
ExprRef::Atom(atom) => Self::matches_atom::<E>(pattern, atom),
ExprRef::Group(group) => Self::matches_group::<E>(pattern, group),
}
}
}
impl<'p, P, E> Pattern<E> for BasicShapePattern<'p, P>
where
E: Expression,
P: Expression<Atom = BasicShape>,
{
#[inline]
fn matches_atom(&self, atom: &E::Atom) -> bool {
Self::matches_atom::<E>(self.0.cases(), atom)
}
#[inline]
fn matches_group(&self, group: GroupRef<E>) -> bool {
Self::matches_group::<E>(self.0.cases(), group)
}
#[inline]
fn matches(&self, expr: &E) -> bool {
Self::matches(self.0.cases(), expr.cases())
}
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub mod vec {
use {
super::*,
alloc::{string::String, vec::Vec},
};
pub type StringExpr = Expr<String>;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum Expr<A = ()> {
Atom(A),
Group(Vec<Self>),
}
impl<A> Expression for Expr<A> {
type Atom = A;
type Group = Vec<Self>;
#[inline]
fn cases(&self) -> ExprRef<Self> {
match self {
Self::Atom(atom) => ExprRef::Atom(atom),
Self::Group(group) => ExprRef::Group(group),
}
}
#[inline]
fn from_atom(atom: <Self as Expression>::Atom) -> Self {
Self::Atom(atom)
}
#[inline]
fn from_group(group: <Self as Expression>::Group) -> Self {
Self::Group(group)
}
}
impl<A> From<Expr<A>> for crate::Expr<Expr<A>> {
#[inline]
fn from(expr: Expr<A>) -> Self {
match expr {
Expr::Atom(atom) => Self::Atom(atom),
Expr::Group(group) => Self::Group(group),
}
}
}
impl<A> Default for Expr<A> {
#[inline]
fn default() -> Self {
Self::empty()
}
}
#[cfg(feature = "parse")]
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
impl<A> FromStr for Expr<A>
where
A: FromIterator<char>,
{
type Err = parse::Error<parse::FromCharactersParseError>;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Expression::from_str(s)
}
}
#[cfg(feature = "multi")]
#[cfg_attr(docsrs, doc(cfg(feature = "multi")))]
pub mod multi {
use super::*;
pub type StringMultiExpr<G = ()> = MultiExpr<String, G>;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum MultiExpr<A = (), G = ()> {
Atom(A),
Group(Vec<Self>, G),
}
impl<A, G> Expression for MultiExpr<A, G> {
type Atom = A;
type Group = (Vec<Self>, G);
#[inline]
fn cases(&self) -> ExprRef<Self> {
match self {
Self::Atom(atom) => ExprRef::Atom(atom),
Self::Group(group, group_type) => ExprRef::Group((group, group_type)),
}
}
#[inline]
fn from_atom(atom: <Self as Expression>::Atom) -> Self {
Self::Atom(atom)
}
#[inline]
fn from_group(group: <Self as Expression>::Group) -> Self {
Self::Group(group.0, group.1)
}
}
impl<A, G> From<MultiExpr<A, G>> for crate::Expr<MultiExpr<A, G>> {
#[inline]
fn from(expr: MultiExpr<A, G>) -> Self {
match expr {
MultiExpr::Atom(atom) => Self::Atom(atom),
MultiExpr::Group(group, group_type) => Self::Group((group, group_type)),
}
}
}
impl<A, G> FromIterator<MultiExpr<A, G>> for (Vec<MultiExpr<A, G>>, G)
where
G: Default,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = MultiExpr<A, G>>,
{
(iter.into_iter().collect(), Default::default())
}
}
impl<A, G> Default for MultiExpr<A, G>
where
G: Default,
{
#[inline]
fn default() -> Self {
Self::empty()
}
}
impl<A, G> GroupReference<MultiExpr<A, G>> for (&Vec<MultiExpr<A, G>>, &G) {
type Item<'e>
where
A: 'e,
G: 'e,
= &'e MultiExpr<A, G>;
type Iter<'e>
where
A: 'e,
G: 'e,
= slice::Iter<'e, MultiExpr<A, G>>;
fn iter(&self) -> Self::Iter<'_> {
todo!()
}
}
impl<A, G> Group<MultiExpr<A, G>> for (Vec<MultiExpr<A, G>>, G) {
type Ref<'e>
where
Self: 'e,
= (&'e Vec<MultiExpr<A, G>>, &'e G);
fn reference(&self) -> Self::Ref<'_> {
(&self.0, &self.1)
}
}
}
}
#[cfg(feature = "buffered")]
#[cfg_attr(docsrs, doc(cfg(feature = "buffered")))]
pub mod buffered {
use {super::*, alloc::vec::Vec};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Expr<T, LengthIndex = usize, ShapeIndex = usize> {
atoms: Vec<T>,
lengths: Vec<LengthIndex>,
shape: Vec<ShapeIndex>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExprGroup<T> {
inner: Expr<T>,
}
pub struct ExprGroupReference<'e, T> {
_marker: core::marker::PhantomData<&'e T>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExprView<'t, T> {
base: &'t Expr<T>,
index: usize,
}
pub struct ExprViewIterator<'t, T> {
_base: &'t Expr<T>,
index: usize,
}
impl<'t, T> ExprViewIterator<'t, T> {
fn _new(base: &'t Expr<T>) -> Self {
Self {
_base: base,
index: 0,
}
}
}
impl<'t, T> Iterator for ExprViewIterator<'t, T> {
type Item = ExprView<'t, T>;
fn next(&mut self) -> Option<Self::Item> {
self.index += 1;
todo!()
}
fn size_hint(&self) -> (usize, Option<usize>) {
todo!()
}
}
impl<T> ExactSizeIterator for ExprViewIterator<'_, T> {}
impl<T> Expression for Expr<T> {
type Atom = Vec<T>;
type Group = ExprGroup<T>;
fn cases(&self) -> ExprRef<Self> {
todo!()
}
fn from_atom(atom: <Self as Expression>::Atom) -> Self {
Self {
atoms: atom,
lengths: Vec::default(),
shape: Vec::default(),
}
}
fn from_group(group: <Self as Expression>::Group) -> Self {
group.inner
}
}
impl<'e, T> From<&'e Expr<T>> for ExprView<'e, T> {
fn from(expr: &'e Expr<T>) -> Self {
let _ = expr;
todo!()
}
}
impl<'e, T> Reference<'e, Expr<T>> for ExprView<'e, T> {
fn cases(self) -> ExprRef<'e, Expr<T>> {
todo!()
}
}
impl<T> GroupReference<Expr<T>> for ExprGroupReference<'_, T> {
type Item<'e>
where
T: 'e,
= ExprView<'e, T>;
type Iter<'e>
where
T: 'e,
= ExprViewIterator<'e, T>;
fn iter(&self) -> Self::Iter<'_> {
todo!()
}
}
impl<T> Group<Expr<T>> for ExprGroup<T> {
type Ref<'e>
where
T: 'e,
= ExprGroupReference<'e, T>;
fn reference(&self) -> Self::Ref<'_> {
todo!()
}
}
impl<T> From<Expr<T>> for crate::Expr<Expr<T>> {
#[inline]
fn from(expr: Expr<T>) -> Self {
let _ = expr;
todo!()
}
}
}