@@ -567,6 +567,65 @@ impl EncodingRef {
567567
568568////////////////////////////////////////////////////////////////////////////////////////////////////
569569
570+ /// A direct stream to the underlying [`Reader`]s reader which updates
571+ /// [`Reader::buffer_position()`] when read from it.
572+ #[ derive( Debug ) ]
573+ #[ must_use = "streams do nothing unless read or polled" ]
574+ pub struct BinaryStream < ' r , R > {
575+ inner : & ' r mut R ,
576+ offset : & ' r mut u64 ,
577+ }
578+
579+ impl < ' r , R > BinaryStream < ' r , R > {
580+ /// Returns current position in bytes in the original source.
581+ #[ inline]
582+ pub const fn offset ( & self ) -> u64 {
583+ * self . offset
584+ }
585+
586+ /// Gets a reference to the underlying reader.
587+ #[ inline]
588+ pub const fn get_ref ( & self ) -> & R {
589+ self . inner
590+ }
591+
592+ /// Gets a mutable reference to the underlying reader.
593+ #[ inline]
594+ pub fn get_mut ( & mut self ) -> & mut R {
595+ self . inner
596+ }
597+ }
598+
599+ impl < ' r , R > io:: Read for BinaryStream < ' r , R >
600+ where
601+ R : io:: Read ,
602+ {
603+ #[ inline]
604+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
605+ let amt = self . inner . read ( buf) ?;
606+ * self . offset += amt as u64 ;
607+ Ok ( amt)
608+ }
609+ }
610+
611+ impl < ' r , R > io:: BufRead for BinaryStream < ' r , R >
612+ where
613+ R : io:: BufRead ,
614+ {
615+ #[ inline]
616+ fn fill_buf ( & mut self ) -> io:: Result < & [ u8 ] > {
617+ self . inner . fill_buf ( )
618+ }
619+
620+ #[ inline]
621+ fn consume ( & mut self , amt : usize ) {
622+ self . inner . consume ( amt) ;
623+ * self . offset += amt as u64 ;
624+ }
625+ }
626+
627+ ////////////////////////////////////////////////////////////////////////////////////////////////////
628+
570629/// A low level encoding-agnostic XML event reader.
571630///
572631/// Consumes bytes and streams XML [`Event`]s.
@@ -759,6 +818,60 @@ impl<R> Reader<R> {
759818 pub const fn decoder ( & self ) -> Decoder {
760819 self . state . decoder ( )
761820 }
821+
822+ /// Get the direct access to the underlying reader, but tracks the amount of
823+ /// read data and update [`Reader::buffer_position()`] accordingly.
824+ ///
825+ /// # Example
826+ ///
827+ /// This example demonstrates, how it is possible to read embedded binary data.
828+ /// Such XML documents are exist in the wild.
829+ ///
830+ /// ```
831+ /// # use pretty_assertions::assert_eq;
832+ /// use std::io::{BufRead, Read};
833+ /// use quick_xml::events::{BytesEnd, BytesStart, Event};
834+ /// use quick_xml::reader::Reader;
835+ ///
836+ /// let mut reader = Reader::from_str("<tag>binary << data&></tag>");
837+ /// // ^ ^ ^ ^
838+ /// // 0 5 21 27
839+ ///
840+ /// assert_eq!(
841+ /// (reader.read_event().unwrap(), reader.buffer_position()),
842+ /// // 5 - end of the `<tag>`
843+ /// (Event::Start(BytesStart::new("tag")), 5)
844+ /// );
845+ ///
846+ /// // Reading directly from underlying reader will not update position
847+ /// // let mut inner = reader.get_mut();
848+ ///
849+ /// // Reading from the stream() advances position
850+ /// let mut inner = reader.stream();
851+ ///
852+ /// // Read binary data. We somehow should known its size
853+ /// let mut binary = [0u8; 16];
854+ /// inner.read_exact(&mut binary).unwrap();
855+ /// assert_eq!(&binary, b"binary << data&>");
856+ /// // 21 - end of the `binary << data&>`
857+ /// assert_eq!(inner.offset(), 21);
858+ /// assert_eq!(reader.buffer_position(), 21);
859+ ///
860+ /// assert_eq!(
861+ /// (reader.read_event().unwrap(), reader.buffer_position()),
862+ /// // 27 - end of the `</tag>`
863+ /// (Event::End(BytesEnd::new("tag")), 27)
864+ /// );
865+ ///
866+ /// assert_eq!(reader.read_event().unwrap(), Event::Eof);
867+ /// ```
868+ #[ inline]
869+ pub fn stream ( & mut self ) -> BinaryStream < R > {
870+ BinaryStream {
871+ inner : & mut self . reader ,
872+ offset : & mut self . state . offset ,
873+ }
874+ }
762875}
763876
764877/// Private sync reading methods
0 commit comments