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
}
}