Skip to content

Commit

Permalink
Implement Drive for concrete container types (#17)
Browse files Browse the repository at this point in the history
* Implement Drive for concrete container types

* Bump 0.4.0
  • Loading branch information
andylokandy authored May 26, 2024
1 parent 39dc342 commit b9e9841
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 31 deletions.
2 changes: 1 addition & 1 deletion derive-visitor-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "derive-visitor-macros"
description = "Macros for derive-visitor package"
categories = ["development-tools"]
version = "0.3.0"
version = "0.4.0"
authors = ["Kit Isaev <[email protected]>"]
license = "MIT"
documentation = "https://docs.rs/derive-visitor"
Expand Down
4 changes: 2 additions & 2 deletions derive-visitor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "derive-visitor"
description = "Derive visitor pattern for arbitrary data structures"
categories = ["development-tools"]
version = "0.3.0"
version = "0.4.0"
authors = ["Kit Isaev <[email protected]>"]
license = "MIT"
edition = "2018"
Expand All @@ -13,7 +13,7 @@ keywords = ["visitor", "derive", "macro"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
derive-visitor-macros = { version = "0.3.0", path = "../derive-visitor-macros" }
derive-visitor-macros = { version = "0.4.0", path = "../derive-visitor-macros" }

[features]
std-types-drive = []
68 changes: 40 additions & 28 deletions derive-visitor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ pub enum Event {
Exit,
}

/// A data structure that can drive a [visitor](Visitor) through iself.
/// A data structure that can drive a [visitor](Visitor) through itself.
///
/// Derive or implement this trait for any type that you want to be able to
/// traverse with a visitor.
Expand Down Expand Up @@ -531,38 +531,50 @@ impl<TK, TV: DriveMut> DerefAndDriveMut for (TK, &mut TV) {
}
}

// The following should be able to handle almost all container types:
// array, BTreeMap, BTreeSet, BinaryHeap, slice, HashMap, HashSet, LinkedList, Vec, VecDeque
//
// It even handles Option, since it has a trivial IntoIterator impl.
impl<T> Drive for T
where
T: 'static,
// HRTB, because this needs to be true for late-bound lifetimes,
// as both &self and &visitor have anonymous lifetimes.
for<'a> &'a T: IntoIterator,
for<'a> <&'a T as IntoIterator>::Item: DerefAndDrive,
{
fn drive<V: Visitor>(&self, visitor: &mut V) {
for item in self {
item.deref_and_drive(visitor);
// Implement Drive and DriveMut for container types in standard library.
macro_rules! impl_drive_for_into_iterator {
( $type:ty ; $($generics:tt)+ ) => {
impl< $($generics)+ > Drive for $type
where
$type: 'static,
for<'a> &'a $type: IntoIterator,
for<'a> <&'a $type as IntoIterator>::Item: DerefAndDrive,
{
fn drive<V: Visitor>(&self, visitor: &mut V) {
for item in self {
item.deref_and_drive(visitor);
}
}
}
}
}

impl<T> DriveMut for T
where
T: 'static,
for<'a> &'a mut T: IntoIterator,
for<'a> <&'a mut T as IntoIterator>::Item: DerefAndDriveMut,
{
fn drive_mut<V: VisitorMut>(&mut self, visitor: &mut V) {
for item in self {
item.deref_and_drive_mut(visitor);
impl< $($generics)+ > DriveMut for $type
where
$type: 'static,
for<'a> &'a mut $type: IntoIterator,
for<'a> <&'a mut $type as IntoIterator>::Item: DerefAndDriveMut,
{
fn drive_mut<V: VisitorMut>(&mut self, visitor: &mut V) {
for item in self {
item.deref_and_drive_mut(visitor);
}
}
}
}
};
}

impl_drive_for_into_iterator! { [T] ; T }
impl_drive_for_into_iterator! { Vec<T> ; T }
impl_drive_for_into_iterator! { std::collections::BTreeSet<T> ; T }
impl_drive_for_into_iterator! { std::collections::BinaryHeap<T> ; T }
impl_drive_for_into_iterator! { std::collections::HashSet<T> ; T }
impl_drive_for_into_iterator! { std::collections::LinkedList<T> ; T }
impl_drive_for_into_iterator! { std::collections::VecDeque<T> ; T }
impl_drive_for_into_iterator! { Option<T> ; T }
impl_drive_for_into_iterator! { Result<T, U> ; T, U }
impl_drive_for_into_iterator! { std::collections::BTreeMap<T, U> ; T, U }
impl_drive_for_into_iterator! { std::collections::HashMap<T, U> ; T, U }
impl_drive_for_into_iterator! { [T; N] ; T, const N: usize }

impl<T> Drive for Box<T>
where
T: Drive,
Expand Down

0 comments on commit b9e9841

Please sign in to comment.