|
16 | 16 |
|
17 | 17 | use core::any::Any; |
18 | 18 | use core::marker::PhantomData; |
| 19 | +use core::ops::ControlFlow; |
19 | 20 |
|
20 | 21 | use crate::Visitor; |
21 | 22 | use crate::VisitorMut; |
22 | 23 |
|
23 | 24 | /// Type returned by `make_visitor` factories. |
24 | | -pub struct FnVisitor<T, F1, F2> { |
| 25 | +pub struct FnVisitor<T, B, F1, F2> { |
25 | 26 | enter: F1, |
26 | 27 | leave: F2, |
27 | | - m: PhantomData<T>, |
| 28 | + marker_type: PhantomData<T>, |
| 29 | + marker_break: PhantomData<B>, |
28 | 30 | } |
29 | 31 |
|
30 | | -impl<T: Any, F1: FnMut(&T), F2: FnMut(&T)> Visitor for FnVisitor<T, F1, F2> { |
31 | | - fn enter(&mut self, this: &dyn Any) { |
| 32 | +impl<T, B, F1, F2> Visitor for FnVisitor<T, B, F1, F2> |
| 33 | +where |
| 34 | + T: Any, |
| 35 | + F1: FnMut(&T) -> ControlFlow<B>, |
| 36 | + F2: FnMut(&T) -> ControlFlow<B>, |
| 37 | +{ |
| 38 | + type Break = B; |
| 39 | + |
| 40 | + fn enter(&mut self, this: &dyn Any) -> ControlFlow<Self::Break> { |
32 | 41 | if let Some(item) = this.downcast_ref::<T>() { |
33 | | - (self.enter)(item); |
| 42 | + (self.enter)(item)?; |
34 | 43 | } |
| 44 | + ControlFlow::Continue(()) |
35 | 45 | } |
36 | 46 |
|
37 | | - fn leave(&mut self, this: &dyn Any) { |
| 47 | + fn leave(&mut self, this: &dyn Any) -> ControlFlow<Self::Break> { |
38 | 48 | if let Some(item) = this.downcast_ref::<T>() { |
39 | | - (self.leave)(item); |
| 49 | + (self.leave)(item)?; |
40 | 50 | } |
| 51 | + ControlFlow::Continue(()) |
41 | 52 | } |
42 | 53 | } |
43 | 54 |
|
44 | | -impl<T: Any, F1: FnMut(&mut T), F2: FnMut(&mut T)> VisitorMut for FnVisitor<T, F1, F2> { |
45 | | - fn enter_mut(&mut self, this: &mut dyn Any) { |
| 55 | +impl<T, B, F1, F2> VisitorMut for FnVisitor<T, B, F1, F2> |
| 56 | +where |
| 57 | + T: Any, |
| 58 | + F1: FnMut(&mut T) -> ControlFlow<B>, |
| 59 | + F2: FnMut(&mut T) -> ControlFlow<B>, |
| 60 | +{ |
| 61 | + type Break = B; |
| 62 | + |
| 63 | + fn enter_mut(&mut self, this: &mut dyn Any) -> ControlFlow<Self::Break> { |
46 | 64 | if let Some(item) = this.downcast_mut::<T>() { |
47 | | - (self.enter)(item); |
| 65 | + (self.enter)(item)?; |
48 | 66 | } |
| 67 | + ControlFlow::Continue(()) |
49 | 68 | } |
50 | 69 |
|
51 | | - fn leave_mut(&mut self, this: &mut dyn Any) { |
| 70 | + fn leave_mut(&mut self, this: &mut dyn Any) -> ControlFlow<Self::Break> { |
52 | 71 | if let Some(item) = this.downcast_mut::<T>() { |
53 | | - (self.leave)(item); |
| 72 | + (self.leave)(item)?; |
54 | 73 | } |
| 74 | + ControlFlow::Continue(()) |
55 | 75 | } |
56 | 76 | } |
57 | 77 |
|
| 78 | +type DefaultVisitFn<T, B> = fn(&T) -> ControlFlow<B>; |
| 79 | +type DefaultVisitFnMut<T, B> = fn(&mut T) -> ControlFlow<B>; |
| 80 | + |
58 | 81 | /// Create a visitor that only visits items of a specific type from a function or a closure. |
59 | | -pub fn make_visitor<T, F1: FnMut(&T), F2: FnMut(&T)>(enter: F1, leave: F2) -> FnVisitor<T, F1, F2> { |
| 82 | +pub fn make_visitor<T, B, F1, F2>(enter: F1, leave: F2) -> FnVisitor<T, B, F1, F2> |
| 83 | +where |
| 84 | + T: Any, |
| 85 | + F1: FnMut(&T) -> ControlFlow<B>, |
| 86 | + F2: FnMut(&T) -> ControlFlow<B>, |
| 87 | +{ |
60 | 88 | FnVisitor { |
61 | 89 | enter, |
62 | 90 | leave, |
63 | | - m: PhantomData, |
| 91 | + marker_type: PhantomData, |
| 92 | + marker_break: PhantomData, |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +/// Similar to [`make_visitor`], but the closure will only be called on entering. |
| 97 | +pub fn make_visitor_enter<T, B, F>(enter: F) -> FnVisitor<T, B, F, DefaultVisitFn<T, B>> |
| 98 | +where |
| 99 | + T: Any, |
| 100 | + F: FnMut(&T) -> ControlFlow<B>, |
| 101 | +{ |
| 102 | + FnVisitor { |
| 103 | + enter, |
| 104 | + leave: |_| ControlFlow::Continue(()), |
| 105 | + marker_type: PhantomData, |
| 106 | + marker_break: PhantomData, |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +/// Similar to [`make_visitor`], but the closure will only be called on leaving. |
| 111 | +pub fn make_visitor_leave<T, B, F>(leave: F) -> FnVisitor<T, B, DefaultVisitFn<T, B>, F> |
| 112 | +where |
| 113 | + T: Any, |
| 114 | + F: FnMut(&T) -> ControlFlow<B>, |
| 115 | +{ |
| 116 | + FnVisitor { |
| 117 | + enter: |_| ControlFlow::Continue(()), |
| 118 | + leave, |
| 119 | + marker_type: PhantomData, |
| 120 | + marker_break: PhantomData, |
64 | 121 | } |
65 | 122 | } |
66 | 123 |
|
67 | 124 | /// Create a visitor that only visits mutable items of a specific type from a function or a closure. |
68 | | -pub fn make_visitor_mut<T, F1: FnMut(&mut T), F2: FnMut(&mut T)>( |
69 | | - enter: F1, |
70 | | - leave: F2, |
71 | | -) -> FnVisitor<T, F1, F2> { |
| 125 | +pub fn make_visitor_mut<T, B, F1, F2>(enter: F1, leave: F2) -> FnVisitor<T, B, F1, F2> |
| 126 | +where |
| 127 | + T: Any, |
| 128 | + F1: FnMut(&mut T) -> ControlFlow<B>, |
| 129 | + F2: FnMut(&mut T) -> ControlFlow<B>, |
| 130 | +{ |
| 131 | + FnVisitor { |
| 132 | + enter, |
| 133 | + leave, |
| 134 | + marker_type: PhantomData, |
| 135 | + marker_break: PhantomData, |
| 136 | + } |
| 137 | +} |
| 138 | + |
| 139 | +/// Similar to [`make_visitor_mut`], but the closure will only be called on entering. |
| 140 | +pub fn make_visitor_enter_mut<T, B, F>(enter: F) -> FnVisitor<T, B, F, DefaultVisitFnMut<T, B>> |
| 141 | +where |
| 142 | + T: Any, |
| 143 | + F: FnMut(&mut T) -> ControlFlow<B>, |
| 144 | +{ |
72 | 145 | FnVisitor { |
73 | 146 | enter, |
| 147 | + leave: |_| ControlFlow::Continue(()), |
| 148 | + marker_type: PhantomData, |
| 149 | + marker_break: PhantomData, |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +/// Similar to [`make_visitor_mut`], but the closure will only be called on leaving. |
| 154 | +pub fn make_visitor_leave_mut<T, B, F>(leave: F) -> FnVisitor<T, B, DefaultVisitFnMut<T, B>, F> |
| 155 | +where |
| 156 | + T: Any, |
| 157 | + F: FnMut(&mut T) -> ControlFlow<B>, |
| 158 | +{ |
| 159 | + FnVisitor { |
| 160 | + enter: |_| ControlFlow::Continue(()), |
74 | 161 | leave, |
75 | | - m: PhantomData, |
| 162 | + marker_type: PhantomData, |
| 163 | + marker_break: PhantomData, |
76 | 164 | } |
77 | 165 | } |
0 commit comments