Trait derive_visitor::Visitor

source ·
pub trait Visitor {
    // Required method
    fn visit(&mut self, item: &dyn Any, event: Event);
}
Expand description

An interface for visiting arbitrary data structures.

A visitor receives items that implement Any, and can use dynamic dispatch to downcast them to particular types that it is interested in. In the classical visitor pattern, a Visitor has a set of separate methods to deal with each particular item type. This behavior can be implemented automatically using derive.

§Derivable

This trait can be derived for any struct or enum. By default, the derived implementation does nothing. You need to explicitly specify what item types and / or events your visitor is interested in, using top-level attribute:

#[derive(Visitor)]
#[visitor(Directory, File)]
struct NameValidator {
    errors: Vec<InvalidNameError>,
}

impl NameValidator {
    fn enter_directory(&mut self, item: &Directory) {
        // ...your logic here
    }
    fn exit_directory(&mut self, item: &Directory) {
        // ...your logic here
    }
    fn enter_file(&mut self, item: &File) {
        // ...your logic here
    }
    fn exit_file(&mut self, item: &File) {
        // ...your logic here
    }
}

§Visitor functions / closures

If your visitor is only interested in some particular type, you don’t have to declare a struct, you can just create a visitor from a closure or a function, e.g.:

let file_visitor = visitor_fn(|file: &File, event| {
    // ...your logic here
});

See visitor_fn and visitor_enter_fn for more info.

§Macro attributes

If your visitor is only interested in Event::Enter or Event::Exit, you can configure the derived implementation to only call enter / exit, respectively, on a per-type basis:

#[derive(Visitor)]
#[visitor(Directory(enter), File(exit))]
struct NameValidator {
    errors: Vec<InvalidNameError>,
}

impl NameValidator {
    fn enter_directory(&mut self, item: &Directory) {
        // ...your logic here
    }
    fn exit_file(&mut self, item: &File) {
        // ...your logic here
    }
}

You can also provide custom method names for each type / event:

#[derive(Visitor)]
#[visitor(Directory(enter="custom_enter_directory", exit="custom_exit_directory"), File)]
struct NameValidator {
    errors: Vec<InvalidNameError>,
}

impl NameValidator {
    fn custom_enter_directory(&mut self, item: &Directory) {
        // ...your logic here
    }
    fn custom_exit_directory(&mut self, item: &Directory) {
        // ...your logic here
    }
    fn enter_file(&mut self, item: &File) {
        // ...your logic here
    }
    fn exit_file(&mut self, item: &File) {
        // ...your logic here
    }
}

Required Methods§

source

fn visit(&mut self, item: &dyn Any, event: Event)

Implementors§

source§

impl<T: Any, F: FnMut(&T, Event)> Visitor for FnVisitor<T, F>