uniplate 0.4.6

Simple, boilerplate-free operations on tree-shaped data types
Documentation
use std::collections::VecDeque;

use super::{Biplate, Uniplate};

pub(super) struct HolesIter<T: Uniplate> {
    children_iter: std::iter::Enumerate<std::collections::vec_deque::IntoIter<T>>,
    children: VecDeque<T>,
    parent: T,
}

impl<T: Uniplate> Iterator for HolesIter<T> {
    type Item = (T, Box<dyn Fn(T) -> T>);

    fn next(&mut self) -> Option<Self::Item> {
        let (i, child) = self.children_iter.next()?;

        let children2 = self.children.clone();
        let parent2 = self.parent.clone();
        let hole = Box::new(move |x: T| {
            let mut children = children2.clone();
            children[i] = x;
            parent2.with_children(children)
        });

        Some((child.clone(), hole))
    }
}

impl<T: Uniplate> HolesIter<T> {
    pub(super) fn new(parent: T) -> HolesIter<T> {
        let children = parent.children();
        let children_iter = children.clone().into_iter().enumerate();

        HolesIter {
            children_iter,
            children,
            parent,
        }
    }
}

pub(super) struct HolesIterBi<T: Uniplate, F: Biplate<T>> {
    children_iter: std::iter::Enumerate<std::collections::vec_deque::IntoIter<T>>,
    children: VecDeque<T>,
    parent: F,
}

impl<T: Uniplate, F: Biplate<T>> Iterator for HolesIterBi<T, F> {
    type Item = (T, Box<dyn Fn(T) -> F>);

    fn next(&mut self) -> Option<Self::Item> {
        let (i, child) = self.children_iter.next()?;

        let children2 = self.children.clone();
        let parent2 = self.parent.clone();
        let hole = Box::new(move |x: T| {
            let mut children = children2.clone();
            children[i] = x;
            parent2.with_children_bi(children)
        });

        Some((child.clone(), hole))
    }
}

impl<T: Uniplate, F: Biplate<T>> HolesIterBi<T, F> {
    pub(super) fn new(parent: F) -> HolesIterBi<T, F> {
        let children = parent.children_bi();
        let children_iter = children.clone().into_iter().enumerate();

        HolesIterBi {
            children_iter,
            children,
            parent,
        }
    }
}