Skip to main content

pddl/
visitor.rs

1//! Visitor traits for traversing PDDL structures.
2//!
3//! **Provisional API.** These traits may change between minor releases
4//! until they have settled. They are exposed primarily to let external
5//! code contribute `Visitor<T, RcDoc>` impls for the `pretty` feature.
6
7/// A visitor.
8pub trait Visitor<T, O> {
9    fn visit(&self, value: &T) -> O;
10}
11
12/// A mutable visitor.
13pub trait VisitorMut<T, O> {
14    fn visit_mut(&mut self, value: &T) -> O;
15}
16
17/// Trait to accept immutable visitors.
18pub trait Accept<V: Visitor<T, O>, T, O> {
19    fn accept(&self, v: &V) -> O;
20}
21
22/// Trait to accept mutable visitors.
23pub trait AcceptMut<V: VisitorMut<T, O>, T, O> {
24    fn accept_mut(&self, v: &mut V) -> O;
25}
26
27/// Automatic implementation for accepting immutable visitors
28/// if the visitor recognizes the target type.
29impl<V, T, O> Accept<V, T, O> for T
30where
31    V: Visitor<T, O>,
32{
33    fn accept(&self, v: &V) -> O {
34        v.visit(self)
35    }
36}
37
38/// Automatic implementation for accepting mutable visitors
39/// if the visitor recognizes the target type.
40impl<V, T, O> AcceptMut<V, T, O> for T
41where
42    V: VisitorMut<T, O>,
43{
44    fn accept_mut(&self, v: &mut V) -> O {
45        v.visit_mut(self)
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    struct Visi(isize);
54    struct Item(i32);
55
56    impl VisitorMut<Item, ()> for Visi {
57        fn visit_mut(&mut self, value: &Item) {
58            self.0 += value.0 as isize;
59        }
60    }
61
62    #[test]
63    fn it_works() {
64        let a = Item(10);
65        let b = Item(7);
66        let mut v = Visi(20);
67
68        a.accept_mut(&mut v);
69        b.accept_mut(&mut v);
70
71        assert_eq!(v.0, 37);
72    }
73}