From 9f75df043b3035b95e2213bcdee6fc5604efab73 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 3 Jun 2026 20:48:39 +0800 Subject: [PATCH] refactor: split core traversal impls --- traversable/src/impls/mod.rs | 46 ++++ traversable/src/impls/std_container.rs | 202 ++++++++++++++ traversable/src/impls/std_primary.rs | 37 +++ traversable/src/impls/trivial.rs | 56 ++++ traversable/src/impls/tuple.rs | 69 +++++ traversable/src/lib.rs | 349 ------------------------- 6 files changed, 410 insertions(+), 349 deletions(-) create mode 100644 traversable/src/impls/std_container.rs create mode 100644 traversable/src/impls/std_primary.rs create mode 100644 traversable/src/impls/trivial.rs create mode 100644 traversable/src/impls/tuple.rs diff --git a/traversable/src/impls/mod.rs b/traversable/src/impls/mod.rs index 52c9cb1..7397469 100644 --- a/traversable/src/impls/mod.rs +++ b/traversable/src/impls/mod.rs @@ -12,7 +12,53 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[allow(unused_macros)] +macro_rules! blank_traverse_impl { + ( $type:ty ) => { + impl Traversable for $type { + #[inline] + fn traverse(&self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } + } + + impl TraversableMut for $type { + #[inline] + fn traverse_mut(&mut self, _visitor: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } + } + }; +} + +#[allow(unused_macros)] +macro_rules! trivial_traverse_impl { + ( $type:ty ) => { + impl Traversable for $type { + fn traverse(&self, visitor: &mut V) -> ControlFlow { + visitor.enter(self)?; + visitor.leave(self)?; + ControlFlow::Continue(()) + } + } + + impl TraversableMut for $type { + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + visitor.enter_mut(self)?; + visitor.leave_mut(self)?; + ControlFlow::Continue(()) + } + } + }; +} + #[cfg(feature = "ordered-float-5")] mod ordered_float_5; #[cfg(feature = "stacksafe-1")] mod stacksafe_1; +#[cfg(feature = "std")] +mod std_container; +#[cfg(feature = "std")] +mod std_primary; +mod trivial; +mod tuple; diff --git a/traversable/src/impls/std_container.rs b/traversable/src/impls/std_container.rs new file mode 100644 index 0000000..dbdd203 --- /dev/null +++ b/traversable/src/impls/std_container.rs @@ -0,0 +1,202 @@ +// Copyright 2025 FastLabs Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::ops::ControlFlow; +use std::boxed::Box; +use std::cell::Cell; +use std::sync::Arc; +use std::sync::Mutex; +use std::sync::RwLock; + +use crate::Traversable; +use crate::TraversableMut; +use crate::Visitor; +use crate::VisitorMut; + +trait DerefAndTraverse { + fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow; +} + +trait DerefAndTraverseMut { + fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow; +} + +impl DerefAndTraverse for &T { + fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow { + self.traverse(visitor) + } +} + +impl DerefAndTraverseMut for &mut T { + fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow { + self.traverse_mut(visitor) + } +} + +impl DerefAndTraverse for (&TK, &TV) { + fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow { + self.0.traverse(visitor)?; + self.1.traverse(visitor)?; + ControlFlow::Continue(()) + } +} + +impl DerefAndTraverseMut for (TK, &mut TV) { + fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow { + self.1.traverse_mut(visitor) + } +} + +macro_rules! impl_drive_for_into_iterator { + ( $type:ty ; $($generics:tt)+ ) => { + impl< $($generics)+ > Traversable for $type + where + $type: 'static, + for<'a> &'a $type: IntoIterator, + for<'a> <&'a $type as IntoIterator>::Item: DerefAndTraverse, + { + #[allow(for_loops_over_fallibles)] + fn traverse(&self, visitor: &mut V) -> ControlFlow { + for item in self { + item.deref_and_traverse(visitor)?; + } + ControlFlow::Continue(()) + } + } + + impl< $($generics)+ > TraversableMut for $type + where + $type: 'static, + for<'a> &'a mut $type: IntoIterator, + for<'a> <&'a mut $type as IntoIterator>::Item: DerefAndTraverseMut, + { + #[allow(for_loops_over_fallibles)] + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + for item in self { + item.deref_and_traverse_mut(visitor)?; + } + ControlFlow::Continue(()) + } + } + }; +} + +impl_drive_for_into_iterator! { [T] ; T } +impl_drive_for_into_iterator! { [T; N] ; T, const N: usize } +impl_drive_for_into_iterator! { std::vec::Vec ; T } +impl_drive_for_into_iterator! { std::collections::BTreeSet ; T } +impl_drive_for_into_iterator! { std::collections::BinaryHeap ; T } +impl_drive_for_into_iterator! { std::collections::HashSet ; T } +impl_drive_for_into_iterator! { std::collections::LinkedList ; T } +impl_drive_for_into_iterator! { std::collections::VecDeque ; T } +impl_drive_for_into_iterator! { std::collections::BTreeMap ; T, U } +impl_drive_for_into_iterator! { std::collections::HashMap ; T, U } +impl_drive_for_into_iterator! { Option ; T } +impl_drive_for_into_iterator! { Result ; T, U } + +impl Traversable for Box { + fn traverse(&self, visitor: &mut V) -> ControlFlow { + (**self).traverse(visitor) + } +} + +impl TraversableMut for Box { + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + (**self).traverse_mut(visitor) + } +} + +impl Traversable for Arc { + fn traverse(&self, visitor: &mut V) -> ControlFlow { + (**self).traverse(visitor) + } +} + +impl Traversable for Mutex +where + T: Traversable, +{ + fn traverse(&self, visitor: &mut V) -> ControlFlow { + let lock = self.lock().unwrap(); + lock.traverse(visitor) + } +} + +impl TraversableMut for Mutex +where + T: TraversableMut, +{ + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + let lock = self.get_mut().unwrap(); + lock.traverse_mut(visitor) + } +} + +impl Traversable for RwLock +where + T: Traversable, +{ + fn traverse(&self, visitor: &mut V) -> ControlFlow { + let lock = self.read().unwrap(); + lock.traverse(visitor) + } +} + +impl TraversableMut for RwLock +where + T: TraversableMut, +{ + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + let lock = self.get_mut().unwrap(); + lock.traverse_mut(visitor) + } +} + +impl TraversableMut for Arc> +where + T: TraversableMut, +{ + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + let mut lock = self.lock().unwrap(); + lock.traverse_mut(visitor) + } +} + +impl TraversableMut for Arc> +where + T: TraversableMut, +{ + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + let mut lock = self.write().unwrap(); + lock.traverse_mut(visitor) + } +} + +impl Traversable for Cell +where + T: Traversable + Copy, +{ + fn traverse(&self, visitor: &mut V) -> ControlFlow { + self.get().traverse(visitor) + } +} + +impl TraversableMut for Cell +where + T: TraversableMut, +{ + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + self.get_mut().traverse_mut(visitor) + } +} diff --git a/traversable/src/impls/std_primary.rs b/traversable/src/impls/std_primary.rs new file mode 100644 index 0000000..cc9ba39 --- /dev/null +++ b/traversable/src/impls/std_primary.rs @@ -0,0 +1,37 @@ +// Copyright 2025 FastLabs Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::ops::ControlFlow; +use std::string::String; + +use crate::Traversable; +use crate::TraversableMut; +use crate::Visitor; +use crate::VisitorMut; + +#[cfg(not(feature = "traverse-std"))] +macro_rules! std_primary_impl { + ( $type:ty ) => { + blank_traverse_impl!($type); + }; +} + +#[cfg(feature = "traverse-std")] +macro_rules! std_primary_impl { + ( $type:ty ) => { + trivial_traverse_impl!($type); + }; +} + +std_primary_impl!(String); diff --git a/traversable/src/impls/trivial.rs b/traversable/src/impls/trivial.rs new file mode 100644 index 0000000..ec3f37a --- /dev/null +++ b/traversable/src/impls/trivial.rs @@ -0,0 +1,56 @@ +// Copyright 2025 FastLabs Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::ops::ControlFlow; + +use crate::Traversable; +use crate::TraversableMut; +use crate::Visitor; +use crate::VisitorMut; + +#[cfg(not(feature = "traverse-trivial"))] +macro_rules! trivial_impl { + ( $type:ty ) => { + blank_traverse_impl!($type); + }; +} + +#[cfg(feature = "traverse-trivial")] +macro_rules! trivial_impl { + ( $type:ty ) => { + trivial_traverse_impl!($type); + }; +} + +trivial_impl!(()); + +trivial_impl!(u8); +trivial_impl!(u16); +trivial_impl!(u32); +trivial_impl!(u64); +trivial_impl!(u128); +trivial_impl!(usize); + +trivial_impl!(i8); +trivial_impl!(i16); +trivial_impl!(i32); +trivial_impl!(i64); +trivial_impl!(i128); +trivial_impl!(isize); + +trivial_impl!(f32); +trivial_impl!(f64); + +trivial_impl!(char); +trivial_impl!(bool); diff --git a/traversable/src/impls/tuple.rs b/traversable/src/impls/tuple.rs new file mode 100644 index 0000000..62b0d9c --- /dev/null +++ b/traversable/src/impls/tuple.rs @@ -0,0 +1,69 @@ +// Copyright 2025 FastLabs Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::ops::ControlFlow; + +use crate::Traversable; +use crate::TraversableMut; +use crate::Visitor; +use crate::VisitorMut; + +macro_rules! tuple_impl { + ( $( $( $type:ident ),+ => $( $field:tt ),+ )+ ) => { + $( + impl<$( $type ),+> Traversable for ($($type,)+) + where + $( + $type: Traversable + ),+ + { + fn traverse(&self, visitor: &mut V) -> ControlFlow { + $( + self.$field.traverse(visitor)?; + )+ + ControlFlow::Continue(()) + } + } + + impl<$( $type ),+> TraversableMut for ($($type,)+) + where + $( + $type: TraversableMut + ),+ + { + fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { + $( + self.$field.traverse_mut(visitor)?; + )+ + ControlFlow::Continue(()) + } + } + )+ + }; +} + +tuple_impl! { + T0 => 0 + T0, T1 => 0, 1 + T0, T1, T2 => 0, 1, 2 + T0, T1, T2, T3 => 0, 1, 2, 3 + T0, T1, T2, T3, T4 => 0, 1, 2, 3, 4 + T0, T1, T2, T3, T4, T5 => 0, 1, 2, 3, 4, 5 + T0, T1, T2, T3, T4, T5, T6 => 0, 1, 2, 3, 4, 5, 6 + T0, T1, T2, T3, T4, T5, T6, T7 => 0, 1, 2, 3, 4, 5, 6, 7 + T0, T1, T2, T3, T4, T5, T6, T7, T8 => 0, 1, 2, 3, 4, 5, 6, 7, 8 + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +} diff --git a/traversable/src/lib.rs b/traversable/src/lib.rs index cfbf76a..2ea856e 100644 --- a/traversable/src/lib.rs +++ b/traversable/src/lib.rs @@ -408,352 +408,3 @@ pub trait TraversableMut: core::any::Any { /// Traverse the mutable data structure with the given visitor. fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow; } - -#[allow(unused_macros)] -macro_rules! blank_traverse_impl { - ( $type:ty ) => { - impl Traversable for $type { - #[inline] - fn traverse(&self, _visitor: &mut V) -> ControlFlow { - ControlFlow::Continue(()) - } - } - - impl TraversableMut for $type { - #[inline] - fn traverse_mut(&mut self, _visitor: &mut V) -> ControlFlow { - ControlFlow::Continue(()) - } - } - }; -} - -#[allow(unused_macros)] -macro_rules! trivial_traverse_impl { - ( $type:ty ) => { - impl Traversable for $type { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - visitor.enter(self)?; - visitor.leave(self)?; - ControlFlow::Continue(()) - } - } - - impl TraversableMut for $type { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - visitor.enter_mut(self)?; - visitor.leave_mut(self)?; - ControlFlow::Continue(()) - } - } - }; -} - -mod impl_trivial { - use super::*; - - #[cfg(not(feature = "traverse-trivial"))] - macro_rules! trivial_impl { - ( $type:ty ) => { - blank_traverse_impl!($type); - }; - } - - #[cfg(feature = "traverse-trivial")] - macro_rules! trivial_impl { - ( $type:ty ) => { - trivial_traverse_impl!($type); - }; - } - - trivial_impl!(()); - - trivial_impl!(u8); - trivial_impl!(u16); - trivial_impl!(u32); - trivial_impl!(u64); - trivial_impl!(u128); - trivial_impl!(usize); - - trivial_impl!(i8); - trivial_impl!(i16); - trivial_impl!(i32); - trivial_impl!(i64); - trivial_impl!(i128); - trivial_impl!(isize); - - trivial_impl!(f32); - trivial_impl!(f64); - - trivial_impl!(char); - trivial_impl!(bool); -} - -mod impl_tuple { - use super::*; - - macro_rules! tuple_impl { - ( $( $( $type:ident ),+ => $( $field:tt ),+ )+ ) => { - $( - impl<$( $type ),+> Traversable for ($($type,)+) - where - $( - $type: Traversable - ),+ - { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - $( - self.$field.traverse(visitor)?; - )+ - ControlFlow::Continue(()) - } - } - - impl<$( $type ),+> TraversableMut for ($($type,)+) - where - $( - $type: TraversableMut - ),+ - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - $( - self.$field.traverse_mut(visitor)?; - )+ - ControlFlow::Continue(()) - } - } - )+ - }; - } - - tuple_impl! { - T0 => 0 - T0, T1 => 0, 1 - T0, T1, T2 => 0, 1, 2 - T0, T1, T2, T3 => 0, 1, 2, 3 - T0, T1, T2, T3, T4 => 0, 1, 2, 3, 4 - T0, T1, T2, T3, T4, T5 => 0, 1, 2, 3, 4, 5 - T0, T1, T2, T3, T4, T5, T6 => 0, 1, 2, 3, 4, 5, 6 - T0, T1, T2, T3, T4, T5, T6, T7 => 0, 1, 2, 3, 4, 5, 6, 7 - T0, T1, T2, T3, T4, T5, T6, T7, T8 => 0, 1, 2, 3, 4, 5, 6, 7, 8 - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 - T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 => 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 - } -} - -#[cfg(feature = "std")] -mod impl_std_primary { - use std::string::String; - - use super::*; - - #[cfg(not(feature = "traverse-std"))] - macro_rules! std_primary_impl { - ( $type:ty ) => { - blank_traverse_impl!($type); - }; - } - - #[cfg(feature = "traverse-std")] - macro_rules! std_primary_impl { - ( $type:ty ) => { - trivial_traverse_impl!($type); - }; - } - - std_primary_impl!(String); -} - -#[cfg(feature = "std")] -mod impl_std_container { - use std::boxed::Box; - use std::cell::Cell; - use std::sync::Arc; - use std::sync::Mutex; - use std::sync::RwLock; - - use super::*; - - // Helper traits to the generic `IntoIterator` Traversable impl - trait DerefAndTraverse { - fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow; - } - - trait DerefAndTraverseMut { - fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow; - } - - // Most collections iterate over item references, this is the trait impl that handles that case - impl DerefAndTraverse for &T { - fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow { - self.traverse(visitor) - } - } - - impl DerefAndTraverseMut for &mut T { - fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow { - self.traverse_mut(visitor) - } - } - - // Map-like collections iterate over item references pairs - impl DerefAndTraverse for (&TK, &TV) { - fn deref_and_traverse(self, visitor: &mut V) -> ControlFlow { - self.0.traverse(visitor)?; - self.1.traverse(visitor)?; - ControlFlow::Continue(()) - } - } - - // Map-like collections have mutable iterators that allow mutating only the value, not the key - impl DerefAndTraverseMut for (TK, &mut TV) { - fn deref_and_traverse_mut(self, visitor: &mut V) -> ControlFlow { - self.1.traverse_mut(visitor) - } - } - - // Implement Traversal for container types in standard library. - macro_rules! impl_drive_for_into_iterator { - ( $type:ty ; $($generics:tt)+ ) => { - impl< $($generics)+ > Traversable for $type - where - $type: 'static, - for<'a> &'a $type: IntoIterator, - for<'a> <&'a $type as IntoIterator>::Item: DerefAndTraverse, - { - #[allow(for_loops_over_fallibles)] - fn traverse(&self, visitor: &mut V) -> ControlFlow { - for item in self { - item.deref_and_traverse(visitor)?; - } - ControlFlow::Continue(()) - } - } - - impl< $($generics)+ > TraversableMut for $type - where - $type: 'static, - for<'a> &'a mut $type: IntoIterator, - for<'a> <&'a mut $type as IntoIterator>::Item: DerefAndTraverseMut, - { - #[allow(for_loops_over_fallibles)] - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - for item in self { - item.deref_and_traverse_mut(visitor)?; - } - ControlFlow::Continue(()) - } - } - }; - } - - impl_drive_for_into_iterator! { [T] ; T } - impl_drive_for_into_iterator! { [T; N] ; T, const N: usize } - impl_drive_for_into_iterator! { std::vec::Vec ; T } - impl_drive_for_into_iterator! { std::collections::BTreeSet ; T } - impl_drive_for_into_iterator! { std::collections::BinaryHeap ; T } - impl_drive_for_into_iterator! { std::collections::HashSet ; T } - impl_drive_for_into_iterator! { std::collections::LinkedList ; T } - impl_drive_for_into_iterator! { std::collections::VecDeque ; T } - impl_drive_for_into_iterator! { std::collections::BTreeMap ; T, U } - impl_drive_for_into_iterator! { std::collections::HashMap ; T, U } - impl_drive_for_into_iterator! { Option ; T } - impl_drive_for_into_iterator! { Result ; T, U } - - impl Traversable for Box { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - (**self).traverse(visitor) - } - } - - impl TraversableMut for Box { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - (**self).traverse_mut(visitor) - } - } - - impl Traversable for Arc { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - (**self).traverse(visitor) - } - } - - impl Traversable for Mutex - where - T: Traversable, - { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - let lock = self.lock().unwrap(); - lock.traverse(visitor) - } - } - - impl TraversableMut for Mutex - where - T: TraversableMut, - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - let lock = self.get_mut().unwrap(); - lock.traverse_mut(visitor) - } - } - - impl Traversable for RwLock - where - T: Traversable, - { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - let lock = self.read().unwrap(); - lock.traverse(visitor) - } - } - - impl TraversableMut for RwLock - where - T: TraversableMut, - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - let lock = self.get_mut().unwrap(); - lock.traverse_mut(visitor) - } - } - - impl TraversableMut for Arc> - where - T: TraversableMut, - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - let mut lock = self.lock().unwrap(); - lock.traverse_mut(visitor) - } - } - - impl TraversableMut for Arc> - where - T: TraversableMut, - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - let mut lock = self.write().unwrap(); - lock.traverse_mut(visitor) - } - } - - impl Traversable for Cell - where - T: Traversable + Copy, - { - fn traverse(&self, visitor: &mut V) -> ControlFlow { - self.get().traverse(visitor) - } - } - - impl TraversableMut for Cell - where - T: TraversableMut, - { - fn traverse_mut(&mut self, visitor: &mut V) -> ControlFlow { - self.get_mut().traverse_mut(visitor) - } - } -}