Trait derive_visitor::Drive
source · pub trait Drive: Any {
// Required method
fn drive<V: Visitor>(&self, visitor: &mut V);
}
Expand description
A data structure that can drive a visitor through itself.
Derive or implement this trait for any type that you want to be able to traverse with a visitor.
Drive
is implemented for most wrapping and collection types from std,
as long as their wrapped / item type implements Drive
.
§Derivable
This trait can be derived for any struct or enum.
By default, the derived implementation will make the visitor enter self
,
then drive it through every field of self
, and finally make it exit self
:
#[derive(Drive)]
struct Directory {
#[drive(skip)]
name: String,
items: Vec<DirectoryItem>,
}
#[derive(Drive)]
enum DirectoryItem {
File(File),
Directory(Directory),
}
#[derive(Drive)]
struct File {
#[drive(skip)]
name: String,
}
§Implementing manually
The following code snippet is roughly equivalent to the implementations that would be derived in the example above:
impl Drive for Directory {
fn drive<V: Visitor>(&self, visitor: &mut V) {
visitor.visit(self, Event::Enter);
self.items.drive(visitor);
visitor.visit(self, Event::Exit);
}
}
impl Drive for DirectoryItem {
fn drive<V: Visitor>(&self, visitor: &mut V) {
visitor.visit(self, Event::Enter);
match self {
Self::File(file) => {
file.drive(visitor);
},
Self::Directory(directory) => {
directory.drive(visitor);
}
}
visitor.visit(self, Event::Exit);
}
}
impl Drive for File {
fn drive<V: Visitor>(&self, visitor: &mut V) {
visitor.visit(self, Event::Enter);
visitor.visit(self, Event::Exit);
}
}
§Macro attributes
The derived implementation of Drive
can be customized using attributes:
§#[drive(skip)]
If applied to a field or an enum variant, the derived implementation won’t drive the visitor through that field / variant.
If applied to a struct or an enum itself, the derived implementation will drive the visitor through the type’s fields / variants, but won’t make it enter or exit the type itself.
§#[drive(with="path")]
Drive a visitor through a field using a custom function.
The function must have the following signature: fn<V: Visitor>(&T, &mut V)
.
In the example below, this attribute is used to customize driving through a Vec:
#[derive(Drive)]
struct Book {
title: String,
#[drive(with="reverse_vec_driver")]
chapters: Vec<Chapter>,
}
fn reverse_vec_driver<T, V: Visitor>(vec: &Vec<T>, visitor: &mut V) {
for item in vec.iter().rev() {
item.drive(visitor);
}
}