@@ -145,66 +145,52 @@ impl Document {
145145 pub fn as_elements ( & self ) -> & [ FormatElement ] {
146146 & self . elements
147147 }
148- }
149-
150- pub trait DocumentVisitor {
151- /// Visit an element and optionally return a replacement
152- fn visit_element ( & mut self , element : & FormatElement ) -> Option < FormatElement > ;
153- }
154148
155- /// Applies a visitor to transform elements in the document
156- pub struct ElementTransformer ;
157-
158- impl ElementTransformer {
159- /// Visits a mutable [Document] and replaces its internal elements.
160- pub fn transform_document < V : DocumentVisitor > ( document : & mut Document , visitor : & mut V ) {
161- let elements = std:: mem:: take ( & mut document. elements ) ;
162- document. elements = Self :: transform_elements ( elements, visitor) ;
149+ /// Transforms the document by visiting every element, optionally replacing
150+ /// them.
151+ ///
152+ /// Accepts a `visitor` that will be called to visit each element, and which
153+ /// may optionally return a replacement.
154+ ///
155+ /// Elements that contain nested elements, such as [FormatElement::Interned]
156+ /// and [FormatElement::BestFitting], have the visitor called on their
157+ /// nested elements, but not on the elements themselves.
158+ pub ( crate ) fn transform (
159+ & mut self ,
160+ mut visitor : impl FnMut ( & FormatElement ) -> Option < FormatElement > ,
161+ ) {
162+ transform_elements ( & mut self . elements , & mut visitor) ;
163163 }
164+ }
164165
165- /// Iterates over each element of the document and map each element to a new element. The new element is
166- /// optionally crated using [DocumentVisitor::visit_element]. If no element is returned, the original element is kept.
167- ///
168- /// Nested data structures such as [FormatElement::Interned] and [FormatElement::BestFitting] use recursion and call
169- /// [Self::transform_elements] again.
170- fn transform_elements < V : DocumentVisitor > (
171- elements : Vec < FormatElement > ,
172- visitor : & mut V ,
173- ) -> Vec < FormatElement > {
174- elements
175- . into_iter ( )
176- . map ( |element| {
177- // Transform nested elements first
178- let transformed_element = match element {
179- FormatElement :: Interned ( interned) => {
180- let nested_elements = interned. deref ( ) . to_vec ( ) ;
181- let transformed_nested = Self :: transform_elements ( nested_elements, visitor) ;
182- FormatElement :: Interned ( Interned :: new ( transformed_nested) )
183- }
184- FormatElement :: BestFitting ( best_fitting) => {
185- let variants: Vec < Box < [ FormatElement ] > > = best_fitting
186- . variants ( )
187- . iter ( )
188- . map ( |variant| {
189- Self :: transform_elements ( variant. to_vec ( ) , visitor)
190- . into_boxed_slice ( )
191- } )
192- . collect ( ) ;
193- // SAFETY: Safe because the number of variants is the same after the transformation
194- unsafe {
195- FormatElement :: BestFitting ( BestFittingElement :: from_vec_unchecked (
196- variants,
197- ) )
198- }
199- }
200- other => other,
201- } ;
202- // Then apply a visitor to the element itself
203- visitor
204- . visit_element ( & transformed_element)
205- . unwrap_or ( transformed_element)
206- } )
207- . collect ( )
166+ /// Iterates over each of the given `elements` and optionally replaces each
167+ /// element with a new one.
168+ ///
169+ /// Nested data structures such as [FormatElement::Interned] and
170+ /// [FormatElement::BestFitting] use recursion and call [transform_elements()]
171+ /// again. The visitor is *not* invoked on these elements.
172+ fn transform_elements (
173+ elements : & mut [ FormatElement ] ,
174+ visitor : & mut impl FnMut ( & FormatElement ) -> Option < FormatElement > ,
175+ ) {
176+ for element in elements {
177+ match element {
178+ FormatElement :: Interned ( interned) => {
179+ let mut nested_elements = interned. deref ( ) . to_vec ( ) ;
180+ transform_elements ( & mut nested_elements, visitor) ;
181+ * element = FormatElement :: Interned ( Interned :: new ( nested_elements) ) ;
182+ }
183+ FormatElement :: BestFitting ( best_fitting) => {
184+ for variant in best_fitting. variants_mut ( ) {
185+ transform_elements ( variant, visitor) ;
186+ }
187+ }
188+ _ => {
189+ if let Some ( replacement) = visitor ( element) {
190+ * element = replacement;
191+ }
192+ }
193+ }
208194 }
209195}
210196
0 commit comments