Skip to content

Commit 5e6d045

Browse files
committed
Add doctests for read_to_end* family of methods
1 parent db8ee6e commit 5e6d045

File tree

1 file changed

+149
-5
lines changed

1 file changed

+149
-5
lines changed

src/reader.rs

Lines changed: 149 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -607,12 +607,91 @@ impl<R: BufRead> Reader<R> {
607607
}
608608
}
609609

610-
/// Reads until end element is found
610+
/// Reads until end element is found using provided buffer as intermediate
611+
/// storage for events content. This function is supposed to be called after
612+
/// you already read a [`Start`] event.
611613
///
612-
/// Manages nested cases where parent and child elements have the same name
614+
/// Manages nested cases where parent and child elements have the same name.
615+
///
616+
/// If corresponding [`End`] event will not be found, the [`Error::UnexpectedEof`]
617+
/// will be returned. In particularly, that error will be returned if you call
618+
/// this method without consuming the corresponding [`Start`] event first.
619+
///
620+
/// If your reader created from a string slice or byte array slice, it is
621+
/// better to use [`read_to_end()`] method, because it will not copy bytes
622+
/// into intermediate buffer.
623+
///
624+
/// The provided `buf` buffer will be filled only by one event content at time.
625+
/// Before reading of each event the buffer will be cleared. If you know an
626+
/// appropriate size of each event, you can preallocate the buffer to reduce
627+
/// number of reallocations.
628+
///
629+
/// The `end` parameter should contain name of the end element _in the reader
630+
/// encoding_. It is good practice to always get that parameter using
631+
/// [`BytesStart::to_end()`] method.
632+
///
633+
/// The correctness of the skipped events does not checked, if you disabled
634+
/// the [`check_end_names`] option.
635+
///
636+
/// # Namespaces
637+
///
638+
/// While the [`Reader`] does not support namespace resolution, namespaces
639+
/// does not change the algorithm for comparing names. Although the names
640+
/// `a:name` and `b:name` where both prefixes `a` and `b` resolves to the
641+
/// same namespace, are semantically equivalent, `</b:name>` cannot close
642+
/// `<a:name>`, because according to [the specification]
643+
///
644+
/// > The end of every element that begins with a **start-tag** MUST be marked
645+
/// > by an **end-tag** containing a name that echoes the element's type as
646+
/// > given in the **start-tag**
647+
///
648+
/// # Examples
649+
///
650+
/// This example shows, how you can skip XML content after you read the
651+
/// start event.
652+
///
653+
/// ```
654+
/// # use pretty_assertions::assert_eq;
655+
/// use quick_xml::events::{BytesStart, Event};
656+
/// use quick_xml::Reader;
657+
///
658+
/// let mut reader = Reader::from_str(r#"
659+
/// <outer>
660+
/// <inner>
661+
/// <inner></inner>
662+
/// <inner/>
663+
/// <outer></outer>
664+
/// <outer/>
665+
/// </inner>
666+
/// </outer>
667+
/// "#);
668+
/// reader.trim_text(true);
669+
/// let mut buf = Vec::new();
670+
///
671+
/// let start = BytesStart::borrowed_name(b"outer");
672+
/// let end = start.to_end().into_owned();
673+
///
674+
/// // First, we read a start event...
675+
/// assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Start(start));
676+
///
677+
/// //...then, we could skip all events to the corresponding end event.
678+
/// // This call will correctly handle nested <outer> elements.
679+
/// // Note, however, that this method does not handle namespaces.
680+
/// reader.read_to_end_into(end.name(), &mut buf).unwrap();
681+
///
682+
/// // At the end we should get an Eof event, because we ate the whole XML
683+
/// assert_eq!(reader.read_event_into(&mut buf).unwrap(), Event::Eof);
684+
/// ```
685+
///
686+
/// [`Start`]: Event::Start
687+
/// [`End`]: Event::End
688+
/// [`read_to_end()`]: Self::read_to_end
689+
/// [`check_end_names`]: Self::check_end_names
690+
/// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
613691
pub fn read_to_end_into(&mut self, end: QName, buf: &mut Vec<u8>) -> Result<()> {
614692
let mut depth = 0;
615693
loop {
694+
buf.clear();
616695
match self.read_event_into(buf) {
617696
Err(e) => return Err(e),
618697

@@ -629,7 +708,6 @@ impl<R: BufRead> Reader<R> {
629708
}
630709
_ => (),
631710
}
632-
buf.clear();
633711
}
634712
}
635713

@@ -974,9 +1052,75 @@ impl<'a> Reader<&'a [u8]> {
9741052
self.read_event_impl(())
9751053
}
9761054

977-
/// Reads until end element is found
1055+
/// Reads until end element is found. This function is supposed to be called
1056+
/// after you already read a [`Start`] event.
1057+
///
1058+
/// Manages nested cases where parent and child elements have the same name.
1059+
///
1060+
/// If corresponding [`End`] event will not be found, the [`Error::UnexpectedEof`]
1061+
/// will be returned. In particularly, that error will be returned if you call
1062+
/// this method without consuming the corresponding [`Start`] event first.
1063+
///
1064+
/// The `end` parameter should contain name of the end element _in the reader
1065+
/// encoding_. It is good practice to always get that parameter using
1066+
/// [`BytesStart::to_end()`] method.
1067+
///
1068+
/// The correctness of the skipped events does not checked, if you disabled
1069+
/// the [`check_end_names`] option.
1070+
///
1071+
/// # Namespaces
1072+
///
1073+
/// While the [`Reader`] does not support namespace resolution, namespaces
1074+
/// does not change the algorithm for comparing names. Although the names
1075+
/// `a:name` and `b:name` where both prefixes `a` and `b` resolves to the
1076+
/// same namespace, are semantically equivalent, `</b:name>` cannot close
1077+
/// `<a:name>`, because according to [the specification]
1078+
///
1079+
/// > The end of every element that begins with a **start-tag** MUST be marked
1080+
/// > by an **end-tag** containing a name that echoes the element's type as
1081+
/// > given in the **start-tag**
1082+
///
1083+
/// # Examples
1084+
///
1085+
/// This example shows, how you can skip XML content after you read the
1086+
/// start event.
9781087
///
979-
/// Manages nested cases where parent and child elements have the same name
1088+
/// ```
1089+
/// # use pretty_assertions::assert_eq;
1090+
/// use quick_xml::events::{BytesStart, Event};
1091+
/// use quick_xml::Reader;
1092+
///
1093+
/// let mut reader = Reader::from_str(r#"
1094+
/// <outer>
1095+
/// <inner>
1096+
/// <inner></inner>
1097+
/// <inner/>
1098+
/// <outer></outer>
1099+
/// <outer/>
1100+
/// </inner>
1101+
/// </outer>
1102+
/// "#);
1103+
/// reader.trim_text(true);
1104+
///
1105+
/// let start = BytesStart::borrowed_name(b"outer");
1106+
/// let end = start.to_end().into_owned();
1107+
///
1108+
/// // First, we read a start event...
1109+
/// assert_eq!(reader.read_event().unwrap(), Event::Start(start));
1110+
///
1111+
/// //...then, we could skip all events to the corresponding end event.
1112+
/// // This call will correctly handle nested <outer> elements.
1113+
/// // Note, however, that this method does not handle namespaces.
1114+
/// reader.read_to_end(end.name()).unwrap();
1115+
///
1116+
/// // At the end we should get an Eof event, because we ate the whole XML
1117+
/// assert_eq!(reader.read_event().unwrap(), Event::Eof);
1118+
/// ```
1119+
///
1120+
/// [`Start`]: Event::Start
1121+
/// [`End`]: Event::End
1122+
/// [`check_end_names`]: Self::check_end_names
1123+
/// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
9801124
pub fn read_to_end(&mut self, end: QName) -> Result<()> {
9811125
let mut depth = 0;
9821126
loop {

0 commit comments

Comments
 (0)