#![cfg_attr(not(feature = "walk"), allow(dead_code))]
use std::cmp::{Eq, PartialEq};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
mod kind {
#[derive(Debug)]
pub enum FiltrateKind {}
#[derive(Debug)]
pub enum ResidueKind {}
}
use kind::*;
#[derive(Debug)]
pub struct Product<K, T> {
inner: T,
_phantom: PhantomData<fn() -> K>,
}
impl<K, T> Product<K, T> {
pub(super) fn new(inner: T) -> Self {
Product {
inner,
_phantom: PhantomData,
}
}
pub fn into_inner(self) -> T {
self.inner
}
pub fn map<U, F>(self, f: F) -> Product<K, U>
where
F: FnOnce(T) -> U,
{
Product::new(f(self.into_inner()))
}
pub fn get(&self) -> &T {
&self.inner
}
}
impl<K, T> Product<K, Option<T>> {
pub fn transpose(self) -> Option<Product<K, T>> {
self.inner.map(Product::new)
}
}
impl<K, T, E> Product<K, Result<T, E>> {
pub fn transpose(self) -> Result<Product<K, T>, Product<K, E>> {
self.inner.map(Product::new).map_err(Product::new)
}
}
impl<K, T> AsRef<T> for Product<K, T> {
fn as_ref(&self) -> &T {
self.get()
}
}
impl<K, T> Copy for Product<K, T> where T: Copy {}
impl<K, T> Clone for Product<K, T>
where
T: Clone,
{
fn clone(&self) -> Self {
Product::new(self.inner.clone())
}
}
impl<K, T> Eq for Product<K, T> where T: Eq {}
impl<K, T> Hash for Product<K, T>
where
T: Hash,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.inner.hash(state);
}
}
impl<K, T> PartialEq<Self> for Product<K, T>
where
T: PartialEq<T>,
{
fn eq(&self, other: &Self) -> bool {
self.inner.eq(&other.inner)
}
}
pub type Filtrate<T> = Product<FiltrateKind, T>;
pub type Residue<T> = Product<ResidueKind, T>;
impl<T> Filtrate<T> {
pub fn filter(self) -> Residue<T> {
self.filter_map(From::from)
}
pub fn filter_map<R, F>(self, f: F) -> Residue<R>
where
F: FnOnce(T) -> R,
{
Residue::new(f(self.into_inner()))
}
pub fn filter_node<R>(self) -> Residue<TreeResidue<R>>
where
R: From<T>,
{
self.filter_map_node(From::from)
}
pub fn filter_map_node<R, F>(self, f: F) -> Residue<TreeResidue<R>>
where
F: FnOnce(T) -> R,
{
Residue::new(TreeResidue::Node(f(self.into_inner())))
}
pub fn filter_tree<I, R>(self, cancellation: WalkCancellation<'_, I>) -> Residue<TreeResidue<R>>
where
I: CancelWalk,
R: From<T>,
{
self.filter_map_tree(cancellation, From::from)
}
pub fn filter_map_tree<I, R, F>(
self,
cancellation: WalkCancellation<'_, I>,
f: F,
) -> Residue<TreeResidue<R>>
where
I: CancelWalk,
F: FnOnce(T) -> R,
{
cancellation.cancel_walk_tree();
Residue::new(TreeResidue::Tree(f(self.into_inner())))
}
}
impl<T> AsRef<T> for Residue<TreeResidue<T>> {
fn as_ref(&self) -> &T {
self.get().get()
}
}
pub trait Feed {
type Filtrate;
type Residue;
}
impl<T, R> Feed for (T, R) {
type Filtrate = T;
type Residue = R;
}
pub trait Isomeric: Feed {
type Substituent<'a>
where
Self: 'a;
fn substituent(separation: &Separation<Self>) -> Self::Substituent<'_>;
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Separation<S>
where
S: Feed + ?Sized,
{
Filtrate(Filtrate<S::Filtrate>),
Residue(Residue<S::Residue>),
}
impl<S> Separation<S>
where
S: Feed,
{
fn from_inner_filtrate(filtrate: S::Filtrate) -> Self {
Separation::Filtrate(Filtrate::new(filtrate))
}
fn from_inner_residue(residue: S::Residue) -> Self {
Separation::Residue(Residue::new(residue))
}
pub fn filter_map<F>(self, f: F) -> Self
where
F: FnOnce(S::Filtrate) -> S::Residue,
{
match self {
Separation::Filtrate(filtrate) => {
Separation::from_inner_residue(f(filtrate.into_inner()))
},
separation => separation,
}
}
pub fn map_filtrate<U, F>(self, f: F) -> Separation<(U, S::Residue)>
where
F: FnOnce(S::Filtrate) -> U,
{
match self {
Separation::Filtrate(filtrate) => filtrate.map(f).into(),
Separation::Residue(residue) => residue.into(),
}
}
pub fn map_residue<U, F>(self, f: F) -> Separation<(S::Filtrate, U)>
where
F: FnOnce(S::Residue) -> U,
{
match self {
Separation::Filtrate(filtrate) => filtrate.into(),
Separation::Residue(residue) => residue.map(f).into(),
}
}
pub fn filtrate(self) -> Option<Filtrate<S::Filtrate>> {
match self {
Separation::Filtrate(filtrate) => Some(filtrate),
_ => None,
}
}
pub fn as_filtrate(&self) -> Option<&Filtrate<S::Filtrate>> {
match self {
Separation::Filtrate(filtrate) => Some(filtrate),
_ => None,
}
}
pub fn as_ref(&self) -> Separation<(&S::Filtrate, &S::Residue)> {
match self {
Separation::Filtrate(filtrate) => {
Separation::Filtrate(Filtrate::new(filtrate.as_ref()))
},
Separation::Residue(residue) => Separation::Residue(Residue::new(residue.as_ref())),
}
}
pub fn substituent(&self) -> S::Substituent<'_>
where
S: Isomeric,
{
S::substituent(self)
}
}
impl<T, R, S> Separation<S>
where
S: Feed<Filtrate = T, Residue = TreeResidue<R>>,
{
pub fn filter_map_node<F>(self, f: F) -> Self
where
F: FnOnce(T) -> R,
{
self.filter_map(|filtrate| TreeResidue::Node(f(filtrate)))
}
pub fn filter_map_tree<I, F>(self, cancellation: WalkCancellation<'_, I>, f: F) -> Self
where
I: CancelWalk,
F: FnOnce(T) -> R,
{
match self {
Separation::Filtrate(filtrate) => {
cancellation.cancel_walk_tree();
Separation::from_inner_residue(TreeResidue::Node(f(filtrate.into_inner())))
},
Separation::Residue(residue) => match residue.into_inner() {
TreeResidue::Node(residue) => {
cancellation.cancel_walk_tree();
Separation::from_inner_residue(TreeResidue::Tree(residue))
},
residue => Separation::from_inner_residue(residue),
},
}
}
pub fn filter_tree_by_substituent<I, F>(
self,
cancellation: WalkCancellation<'_, I>,
f: F,
) -> Self
where
S: Isomeric,
R: From<T>,
I: CancelWalk,
F: FnOnce(S::Substituent<'_>) -> Option<TreeResidue<()>>,
{
match f(self.substituent()) {
Some(TreeResidue::Tree(())) => self.filter_map_tree(cancellation, From::from),
Some(TreeResidue::Node(())) => self.filter_map_node(From::from),
_ => self,
}
}
}
impl<T, R> Separation<(Option<T>, R)> {
pub fn transpose_filtrate(self) -> Option<Separation<(T, R)>> {
match self {
Separation::Filtrate(filtrate) => {
filtrate.into_inner().map(Filtrate::new).map(From::from)
},
Separation::Residue(residue) => Some(residue.into()),
}
}
}
impl<T, E, R> Separation<(Result<T, E>, R)> {
pub fn transpose_filtrate(self) -> Result<Separation<(T, R)>, Filtrate<E>> {
match self {
Separation::Filtrate(filtrate) => match filtrate.into_inner() {
Ok(filtrate) => Ok(Filtrate::new(filtrate).into()),
Err(error) => Err(Filtrate::new(error)),
},
Separation::Residue(residue) => Ok(residue.into()),
}
}
}
impl<S> From<Filtrate<S::Filtrate>> for Separation<S>
where
S: Feed,
{
fn from(filtrate: Filtrate<S::Filtrate>) -> Self {
Separation::Filtrate(filtrate)
}
}
impl<S> From<Residue<S::Residue>> for Separation<S>
where
S: Feed,
{
fn from(residue: Residue<S::Residue>) -> Self {
Separation::Residue(residue)
}
}
pub trait SeparatingFilter {
type Feed: Feed;
fn feed(&mut self) -> Option<Separation<Self::Feed>>;
}
impl<I> SeparatingFilter for I
where
I: SeparatingFilterInput,
{
type Feed = <I as SeparatingFilterInput>::Feed;
fn feed(&mut self) -> Option<Separation<Self::Feed>> {
self.next().map(Separation::from_inner_filtrate)
}
}
pub trait SeparatingFilterInput: Iterator {
type Feed: Feed<Filtrate = Self::Item>;
}
pub trait CancelWalk {
fn cancel_walk_tree(&mut self);
}
#[derive(Debug)]
pub struct WalkCancellation<'i, I>(&'i mut I);
impl<'i, I> WalkCancellation<'i, I> {
pub(crate) fn unchecked(tree: &'i mut I) -> Self {
WalkCancellation(tree)
}
}
impl<'i, I> WalkCancellation<'i, I>
where
I: CancelWalk,
{
fn cancel_walk_tree(self) {
self.0.cancel_walk_tree()
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum TreeResidue<T> {
Node(T),
Tree(T),
}
impl<T> TreeResidue<T> {
pub fn map<U, F>(self, f: F) -> TreeResidue<U>
where
F: FnOnce(T) -> U,
{
match self {
TreeResidue::Node(residue) => TreeResidue::Node(f(residue)),
TreeResidue::Tree(residue) => TreeResidue::Tree(f(residue)),
}
}
pub fn as_ref(&self) -> TreeResidue<&T> {
match self {
TreeResidue::Node(residue) => TreeResidue::Node(residue),
TreeResidue::Tree(residue) => TreeResidue::Tree(residue),
}
}
pub fn get(&self) -> &T {
match self {
TreeResidue::Node(residue) | TreeResidue::Tree(residue) => residue,
}
}
}
pub trait HierarchicalIterator:
CancelWalk + Iterator<Item = <Self::Feed as Feed>::Filtrate> + SeparatingFilter
{
fn filter_tree_by_substituent<F>(self, f: F) -> FilterTreeBySubstituent<Self, F>
where
Self: Sized,
Self::Feed: Isomeric,
F: FnMut(<Self::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
FilterTreeBySubstituent { input: self, f }
}
fn filter_map_tree<S, F>(self, f: F) -> FilterMapTree<Self, S, F>
where
Self: Sized,
S: Feed,
F: FnMut(WalkCancellation<Self>, Separation<Self::Feed>) -> Separation<S>,
{
FilterMapTree {
input: self,
f,
_phantom: PhantomData,
}
}
}
impl<R, I> HierarchicalIterator for I
where
I: CancelWalk + Iterator<Item = <Self::Feed as Feed>::Filtrate> + SeparatingFilter,
I::Feed: Feed<Residue = TreeResidue<R>>,
{
}
#[derive(Clone, Debug)]
pub struct FilterTreeBySubstituent<I, F> {
input: I,
f: F,
}
impl<I, F> CancelWalk for FilterTreeBySubstituent<I, F>
where
I: CancelWalk,
{
fn cancel_walk_tree(&mut self) {
self.input.cancel_walk_tree()
}
}
impl<R, I, F> SeparatingFilter for FilterTreeBySubstituent<I, F>
where
R: From<<I::Feed as Feed>::Filtrate>,
I: HierarchicalIterator,
I::Feed: Feed<Residue = TreeResidue<R>> + Isomeric,
F: FnMut(<I::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
type Feed = I::Feed;
fn feed(&mut self) -> Option<Separation<Self::Feed>> {
let separation = self.input.feed();
separation.map(|separation| {
let substituent = separation.substituent();
match (self.f)(substituent) {
None => separation,
Some(residue) => match residue {
TreeResidue::Node(_) => separation.filter_map_node(From::from),
TreeResidue::Tree(_) => {
separation.filter_map_tree(WalkCancellation(self), From::from)
},
},
}
})
}
}
impl<R, I, F> Iterator for FilterTreeBySubstituent<I, F>
where
R: From<<I::Feed as Feed>::Filtrate>,
I: HierarchicalIterator,
I::Feed: Feed<Residue = TreeResidue<R>> + Isomeric,
F: FnMut(<I::Feed as Isomeric>::Substituent<'_>) -> Option<TreeResidue<()>>,
{
type Item = <I::Feed as Feed>::Filtrate;
fn next(&mut self) -> Option<Self::Item> {
filtrate(self)
}
}
#[derive(Clone, Debug)]
pub struct FilterMapTree<I, S, F> {
input: I,
f: F,
_phantom: PhantomData<fn() -> S>,
}
impl<I, S, F> CancelWalk for FilterMapTree<I, S, F>
where
I: CancelWalk,
{
fn cancel_walk_tree(&mut self) {
self.input.cancel_walk_tree()
}
}
impl<R, I, S, F> Iterator for FilterMapTree<I, S, F>
where
I: SeparatingFilter,
I::Feed: Feed<Residue = TreeResidue<R>>,
S: Feed,
F: FnMut(WalkCancellation<I>, Separation<I::Feed>) -> Separation<S>,
{
type Item = <<Self as SeparatingFilter>::Feed as Feed>::Filtrate;
fn next(&mut self) -> Option<Self::Item> {
filtrate(self)
}
}
impl<R, I, S, F> SeparatingFilter for FilterMapTree<I, S, F>
where
I: SeparatingFilter,
I::Feed: Feed<Residue = TreeResidue<R>>,
S: Feed,
F: FnMut(WalkCancellation<I>, Separation<I::Feed>) -> Separation<S>,
{
type Feed = S;
fn feed(&mut self) -> Option<Separation<Self::Feed>> {
let separation = self.input.feed();
separation.map(|separation| (self.f)(WalkCancellation(&mut self.input), separation))
}
}
pub fn filtrate<I>(filter: &mut I) -> Option<<I::Feed as Feed>::Filtrate>
where
I: SeparatingFilter,
{
loop {
if let Some(separation) = filter.feed() {
return match separation.filtrate() {
None => {
continue;
},
Some(filtrate) => Some(filtrate.into_inner()),
};
}
return None;
}
}