1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crate::{Visitable, VisitableMut};

trait AsVisitable<'a> {
    fn to_visitable(self) -> &'a dyn Visitable;
}

impl<'a, T: Visitable> AsVisitable<'a> for &'a T {
    fn to_visitable(self) -> &'a dyn Visitable {
        self
    }
}

trait AsVisitableMut<'a> {
    #[allow(clippy::wrong_self_convention)]
    fn to_visitable_mut(self) -> &'a mut dyn VisitableMut;
}

impl<'a, T: VisitableMut> AsVisitableMut<'a> for &'a mut T {
    fn to_visitable_mut(self) -> &'a mut dyn VisitableMut {
        self
    }
}

// blanket impl that covers a bunch of std containers (Vec, Option)
impl<C: 'static> Visitable for C
where
    for<'a> &'a C: IntoIterator,
    for<'a> <&'a C as IntoIterator>::Item: AsVisitable<'a>,
{
    fn children(&self) -> Vec<&dyn Visitable> {
        self.into_iter()
            .map(AsVisitable::to_visitable)
            .collect::<Vec<_>>()
    }
}

impl<C: 'static> VisitableMut for C
where
    for<'a> &'a mut C: IntoIterator,
    for<'a> <&'a mut C as IntoIterator>::Item: AsVisitableMut<'a>,
{
    fn children_mut(&mut self) -> Vec<&mut dyn VisitableMut> {
        self.into_iter()
            .map(AsVisitableMut::to_visitable_mut)
            .collect::<Vec<_>>()
    }
}

impl<T: Visitable> Visitable for Box<T> {
    fn children(&self) -> Vec<&dyn Visitable> {
        vec![self.as_ref()]
    }
}

impl<T: VisitableMut> VisitableMut for Box<T> {
    fn children_mut(&mut self) -> Vec<&mut dyn VisitableMut> {
        vec![self.as_mut()]
    }
}