@@ -2581,11 +2581,15 @@ where
2581
2581
/// events, merge them into one string. If there are no such events, returns
2582
2582
/// an empty string.
2583
2583
///
2584
- /// If `allow_start` is `false`, then only text events is consumed, for other
2584
+ /// If `allow_start` is `false`, then only text events are consumed, for other
2585
2585
/// events an error is returned (see table below).
2586
2586
///
2587
- /// If `allow_start` is `true`, then first [`DeEvent::Text`] event is returned
2588
- /// and all other content is skipped until corresponding end tag will be consumed.
2587
+ /// If `allow_start` is `true`, then two or three events are expected:
2588
+ /// - [`DeEvent::Start`];
2589
+ /// - _(optional)_ [`DeEvent::Text`] which content is returned;
2590
+ /// - [`DeEvent::End`]. If text event was missed, an empty string is returned.
2591
+ ///
2592
+ /// Corresponding events are consumed.
2589
2593
///
2590
2594
/// # Handling events
2591
2595
///
@@ -2603,9 +2607,8 @@ where
2603
2607
/// |Event |XML |Handling
2604
2608
/// |------------------|---------------------------|----------------------------------------------------------------------------------
2605
2609
/// |[`DeEvent::Start`]|`<any-tag>...</any-tag>` |Emits [`UnexpectedStart("any-tag")`](DeError::UnexpectedStart)
2606
- /// |[`DeEvent::End`] |`</tag>` |Returns an empty slice, if close tag matched the open one
2607
- /// |[`DeEvent::End`] |`</any-tag>` |Emits [`UnexpectedEnd("any-tag")`](DeError::UnexpectedEnd)
2608
- /// |[`DeEvent::Text`] |`text content` or `<![CDATA[cdata content]]>` (probably mixed)|Returns event content unchanged, consumes events up to `</tag>`
2610
+ /// |[`DeEvent::End`] |`</tag>` |Returns an empty slice. The reader guarantee that tag will match the open one
2611
+ /// |[`DeEvent::Text`] |`text content` or `<![CDATA[cdata content]]>` (probably mixed)|Returns event content unchanged, expects the `</tag>` after that
2609
2612
/// |[`DeEvent::Eof`] | |Emits [`UnexpectedEof`](DeError::UnexpectedEof)
2610
2613
///
2611
2614
/// [`Text`]: Event::Text
@@ -2614,23 +2617,32 @@ where
2614
2617
match self . next ( ) ? {
2615
2618
DeEvent :: Text ( e) => Ok ( e. text ) ,
2616
2619
// allow one nested level
2617
- DeEvent :: Start ( e) if allow_start => match self . next ( ) ? {
2618
- DeEvent :: Text ( t) => {
2619
- self . read_to_end ( e. name ( ) ) ?;
2620
- Ok ( t. text )
2621
- }
2622
- DeEvent :: Start ( s) => Err ( DeError :: UnexpectedStart ( s. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2623
- // We can get End event in case of `<tag></tag>` or `<tag/>` input
2624
- // Return empty text in that case
2625
- DeEvent :: End ( end) if end. name ( ) == e. name ( ) => Ok ( "" . into ( ) ) ,
2626
- DeEvent :: End ( end) => Err ( DeError :: UnexpectedEnd ( end. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2627
- DeEvent :: Eof => Err ( DeError :: UnexpectedEof ) ,
2628
- } ,
2620
+ DeEvent :: Start ( _) if allow_start => self . read_text ( ) ,
2629
2621
DeEvent :: Start ( e) => Err ( DeError :: UnexpectedStart ( e. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2630
2622
DeEvent :: End ( e) => Err ( DeError :: UnexpectedEnd ( e. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2631
2623
DeEvent :: Eof => Err ( DeError :: UnexpectedEof ) ,
2632
2624
}
2633
2625
}
2626
+ /// Consumes one [`DeEvent::Text`] event and ensures that it is followed by the
2627
+ /// [`DeEvent::End`] event.
2628
+ fn read_text ( & mut self ) -> Result < Cow < ' de , str > , DeError > {
2629
+ match self . next ( ) ? {
2630
+ DeEvent :: Text ( e) => match self . next ( ) ? {
2631
+ // The matching tag name is guaranteed by the reader
2632
+ DeEvent :: End ( _) => Ok ( e. text ) ,
2633
+ // SAFETY: Cannot be two consequent Text events, they would be merged into one
2634
+ DeEvent :: Text ( _) => unreachable ! ( ) ,
2635
+ DeEvent :: Start ( e) => Err ( DeError :: UnexpectedStart ( e. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2636
+ DeEvent :: Eof => Err ( DeError :: UnexpectedEof ) ,
2637
+ } ,
2638
+ // We can get End event in case of `<tag></tag>` or `<tag/>` input
2639
+ // Return empty text in that case
2640
+ // The matching tag name is guaranteed by the reader
2641
+ DeEvent :: End ( _) => Ok ( "" . into ( ) ) ,
2642
+ DeEvent :: Start ( s) => Err ( DeError :: UnexpectedStart ( s. name ( ) . as_ref ( ) . to_owned ( ) ) ) ,
2643
+ DeEvent :: Eof => Err ( DeError :: UnexpectedEof ) ,
2644
+ }
2645
+ }
2634
2646
2635
2647
/// Drops all events until event with [name](BytesEnd::name()) `name` won't be
2636
2648
/// dropped. This method should be called after [`Self::next()`]
0 commit comments