@@ -528,19 +528,167 @@ impl BasePacketReader {
528528 }
529529}
530530
531+ // TODO replace 'a with GAT as soon as they are stabilized
532+ // (https://github.com/rust-lang/rust/issues/44265)
533+
534+ /// A trait for [Read] implementations that allow reversible reads to a buffer.
535+ /// After such a read, the reader's position can be reverted as with [Seek],
536+ /// however only as long as it is still within the bounds of the previous
537+ /// reversible read call. As such, this trait is to be viewed as a subset of
538+ /// [Seek]. The lifetime `'a` is that of the reference passed to the object in
539+ /// [RevRead::rev_read] in order to support depending [RevRead::Buf] on that
540+ /// lifetime.
541+ ///
542+ /// Usually, you will not need to implement this yourself. Instead, you can
543+ /// rely either on the blanket implementation provided for all type that
544+ /// implement [Read] and [Seek] or use the [RevReader] to wrap a type that only
545+ /// implements [Read].
546+ pub trait RevRead < ' a > : Read {
547+
548+ /// The type of buffer returned by this reversible reader.
549+ type Buf : AsRef < [ u8 ] > ;
550+
551+ /// Executes a reversible read hat returns a buffer with data read from the
552+ /// current position in the reader. The buffer must be larger than 28 bytes
553+ /// in size, but it does not have to be completely filled with data from
554+ /// the reader. The second return value indicates the actual numbe of bytes
555+ /// read from the reader.
556+ ///
557+ /// # Arguments
558+ ///
559+ /// * `amount`: An upper bound on the number of bytes that should be read
560+ /// from the reader. This does not have to be an upper bound on the size of
561+ /// the returned buffer.
562+ ///
563+ /// # Errors
564+ ///
565+ /// If reading fails according to [Read::read].
566+ fn rev_read ( & ' a mut self , amount : usize ) -> io:: Result < ( Self :: Buf , usize ) > ;
567+
568+ /// Reverts the previous execution of [RevRead::rev_read] by some amount,
569+ /// i.e. the next read will yield previous data of that size again as if
570+ /// [Seek::seek] was called with [SeekFrom::Current] of `-amount`. It is a
571+ /// prerequisite to this function that the previous operation was
572+ /// [RevRead::rev_read] and that that returned at least one byte of data,
573+ /// otherwise reverting may or may not work.
574+ ///
575+ /// # Arguments
576+ ///
577+ /// * `amount`: The number of bytes by which to revert the previous read.
578+ ///
579+ /// # Errors
580+ ///
581+ /// If reverting by the given amount is unsupported given the current
582+ /// situation.
583+ fn revert ( & mut self , amount : usize ) -> io:: Result < ( ) > ;
584+ }
585+
586+ // The array's size is freely choosable, but must be > 27.
587+ const REV_READ_BUF_SIZE : usize = 1024 ;
588+
589+ impl < ' a , R : Read + Seek > RevRead < ' a > for R {
590+ type Buf = [ u8 ; REV_READ_BUF_SIZE ] ;
591+
592+ fn rev_read ( & ' a mut self , amount : usize ) -> io:: Result < ( Self :: Buf , usize ) > {
593+ let amount = amount. min ( REV_READ_BUF_SIZE ) ;
594+ let mut buf = [ 0 ; REV_READ_BUF_SIZE ] ;
595+ let count = self . read ( & mut buf[ ..amount] ) ?;
596+
597+ Ok ( ( buf, count) )
598+ }
599+
600+ fn revert ( & mut self , amount : usize ) -> io:: Result < ( ) > {
601+ self . seek ( SeekFrom :: Current ( -( amount as i64 ) ) ) ?;
602+
603+ Ok ( ( ) )
604+ }
605+ }
606+
607+ /// A reversible reader that wraps around a type implementing [Read] and offers
608+ /// a [RevRead] implementation by storing read data in a local buffer. Use this
609+ /// if you want to use the [PacketReader] with a type that does not implement
610+ /// [Seek].
611+ pub struct RevReader < R > {
612+ /// The underlying reader.
613+ read : R ,
614+ /// The buffer used to store the result of a [RevRead::rev_read] call.
615+ buf : Box < [ u8 ; REV_READ_BUF_SIZE ] > ,
616+ /// The number of bytes in the buffer that are valid.
617+ buf_len : usize ,
618+ /// The index of the next byte that should be read from the buffer.
619+ buf_idx : usize
620+ }
621+
622+ impl < R > RevReader < R > {
623+
624+ /// Creates a new reversible reader that wraps around the given `read`.
625+ /// Note in order for the [RevRead] implementation to hold, `read` must
626+ /// implement [Read].
627+ pub fn new ( read : R ) -> RevReader < R > {
628+ RevReader {
629+ read,
630+ buf : Box :: new ( [ 0 ; REV_READ_BUF_SIZE ] ) ,
631+ buf_len : 0 ,
632+ buf_idx : 0
633+ }
634+ }
635+ }
636+
637+ impl < R : Read > Read for RevReader < R > {
638+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
639+ if self . buf_idx < self . buf_len {
640+ // We are still within reverted amount => copy from internal buffer
641+ let read_len = ( self . buf_len - self . buf_idx ) . min ( buf. len ( ) ) ;
642+ let read_data = & self . buf [ self . buf_idx ..( self . buf_idx + read_len) ] ;
643+
644+ ( & mut buf[ ..read_len] ) . copy_from_slice ( read_data) ;
645+ self . buf_idx += read_len;
646+ Ok ( read_len)
647+ }
648+ else {
649+ // Invalidate the buffer
650+ self . buf_len = 0 ;
651+ self . read . read ( buf)
652+ }
653+ }
654+ }
655+
656+ impl < ' a , R : Read > RevRead < ' a > for RevReader < R > {
657+ type Buf = & ' a [ u8 ] ;
658+
659+ fn rev_read ( & ' a mut self , amount : usize ) -> io:: Result < ( Self :: Buf , usize ) > {
660+ let amount = amount. min ( self . buf . len ( ) ) ;
661+ let buf = & mut self . buf [ ..amount] ;
662+ let count = self . read . read ( buf) ?;
663+
664+ self . buf_len = count;
665+ self . buf_idx = count;
666+ Ok ( ( & * self . buf , count) )
667+ }
668+
669+ fn revert ( & mut self , amount : usize ) -> io:: Result < ( ) > {
670+ if amount > self . buf_idx || self . buf_len == 0 {
671+ return Err ( io:: Error :: new ( ErrorKind :: Other , "invalid revert" ) ) ;
672+ }
673+
674+ self . buf_idx -= amount;
675+ Ok ( ( ) )
676+ }
677+ }
678+
531679#[ derive( Clone , Copy ) ]
532680enum UntilPageHeaderReaderMode {
533681 Searching ,
534682 FoundWithNeeded ( u8 ) ,
535- SeekNeeded ( i32 ) ,
683+ RevertNeeded ( usize ) ,
536684 Found ,
537685}
538686
539687enum UntilPageHeaderResult {
540688 Eof ,
541689 Found ,
542690 ReadNeeded ,
543- SeekNeeded ,
691+ RevertNeeded ,
544692}
545693
546694struct UntilPageHeaderReader {
@@ -583,27 +731,28 @@ impl UntilPageHeaderReader {
583731 /// return Ok(true) if the full header has been read and can be extracted with
584732 ///
585733 /// or return Ok(false) if the
586- pub fn do_read < R : Read > ( & mut self , mut rdr : R )
587- -> Result < UntilPageHeaderResult , OggReadError > {
734+ pub fn do_read < R > ( & mut self , rdr : & mut R )
735+ -> Result < UntilPageHeaderResult , OggReadError >
736+ where
737+ for < ' a > R : RevRead < ' a >
738+ {
588739 use self :: UntilPageHeaderReaderMode :: * ;
589740 use self :: UntilPageHeaderResult as Res ;
590- // The array's size is freely choosable, but must be > 27,
591- // and must well fit into an i32 (needs to be stored in SeekNeeded)
592- let mut buf : [ u8 ; 1024 ] = [ 0 ; 1024 ] ;
593-
594- let rd_len = tri ! ( rdr. read( if self . read_amount < 27 {
741+ let rd_amount = if self . read_amount < 27 {
595742 // This is an optimisation for the most likely case:
596743 // the next page directly follows the current read position.
597744 // Then it would be a waste to read more than the needed amount.
598- & mut buf [ 0 .. 27 - self . read_amount]
745+ 27 - self . read_amount
599746 } else {
600747 match self . mode {
601- Searching => & mut buf ,
602- FoundWithNeeded ( amount) => & mut buf [ 0 .. amount as usize ] ,
603- SeekNeeded ( _) => return Ok ( Res :: SeekNeeded ) ,
748+ Searching => usize :: MAX ,
749+ FoundWithNeeded ( amount) => amount as usize ,
750+ RevertNeeded ( _) => return Ok ( Res :: RevertNeeded ) ,
604751 Found => return Ok ( Res :: Found ) ,
605752 }
606- } ) ) ;
753+ } ;
754+ let ( buf, rd_len) = tri ! ( rdr. rev_read( rd_amount) ) ;
755+ let buf = buf. as_ref ( ) ;
607756
608757 if rd_len == 0 {
609758 // Reached EOF. This means we're in one of these cases:
@@ -678,18 +827,21 @@ impl UntilPageHeaderReader {
678827 // Seek back so that we are at the position
679828 // right after the header.
680829
681- self . mode = SeekNeeded ( needed as i32 - fnd_buf. len ( ) as i32 ) ;
682- return Ok ( Res :: SeekNeeded ) ;
830+ self . mode = RevertNeeded ( fnd_buf. len ( ) - needed ) ;
831+ return Ok ( Res :: RevertNeeded ) ;
683832 }
684833 }
685- pub fn do_seek < S : Seek > ( & mut self , mut skr : S )
686- -> Result < UntilPageHeaderResult , OggReadError > {
834+ pub fn do_revert < R > ( & mut self , rdr : & mut R )
835+ -> Result < UntilPageHeaderResult , OggReadError >
836+ where
837+ for < ' a > R : RevRead < ' a >
838+ {
687839 use self :: UntilPageHeaderReaderMode :: * ;
688840 use self :: UntilPageHeaderResult as Res ;
689841 match self . mode {
690842 Searching | FoundWithNeeded ( _) => Ok ( Res :: ReadNeeded ) ,
691- SeekNeeded ( offs ) => {
692- tri ! ( skr . seek ( SeekFrom :: Current ( offs as i64 ) ) ) ;
843+ RevertNeeded ( amount ) => {
844+ tri ! ( rdr . revert ( amount ) ) ;
693845 self . mode = Found ;
694846 Ok ( Res :: Found )
695847 } ,
@@ -715,15 +867,21 @@ consistent when it encounters the `WouldBlock` error kind.
715867If you desire async functionality, consider enabling the `async` feature
716868and look into the async module.
717869*/
718- pub struct PacketReader < T : io:: Read + io:: Seek > {
870+ pub struct PacketReader < T >
871+ where
872+ for < ' a > T : RevRead < ' a >
873+ {
719874 rdr : T ,
720875
721876 base_pck_rdr : BasePacketReader ,
722877
723878 read_some_pg : bool
724879}
725880
726- impl < T : io:: Read + io:: Seek > PacketReader < T > {
881+ impl < T > PacketReader < T >
882+ where
883+ for < ' a > T : RevRead < ' a >
884+ {
727885 /// Constructs a new `PacketReader` with a given `Read`.
728886 pub fn new ( rdr : T ) -> PacketReader < T > {
729887 PacketReader { rdr, base_pck_rdr : BasePacketReader :: new ( ) , read_some_pg : false }
@@ -785,7 +943,7 @@ impl<T :io::Read + io::Seek> PacketReader<T> {
785943 break
786944 } ,
787945 ReadNeeded => tri ! ( r. do_read( & mut self . rdr) ) ,
788- SeekNeeded => tri ! ( r. do_seek ( & mut self . rdr) )
946+ RevertNeeded => tri ! ( r. do_revert ( & mut self . rdr) )
789947 }
790948 }
791949 Ok ( Some ( r. into_header ( ) ) )
@@ -815,6 +973,17 @@ impl<T :io::Read + io::Seek> PacketReader<T> {
815973 Ok ( Some ( tri ! ( pg_prs. parse_packet_data( packet_data) ) ) )
816974 }
817975
976+ /// Resets the internal state by deleting all
977+ /// unread packets.
978+ pub fn delete_unread_packets ( & mut self ) {
979+ self . base_pck_rdr . update_after_seek ( ) ;
980+ }
981+ }
982+
983+ impl < T > PacketReader < T >
984+ where
985+ for < ' a > T : RevRead < ' a > + io:: Seek
986+ {
818987 /// Seeks the underlying reader
819988 ///
820989 /// Seeks the reader that this PacketReader bases on by the specified
@@ -1015,11 +1184,6 @@ impl<T :io::Read + io::Seek> PacketReader<T> {
10151184 }
10161185 }
10171186 }
1018- /// Resets the internal state by deleting all
1019- /// unread packets.
1020- pub fn delete_unread_packets ( & mut self ) {
1021- self . base_pck_rdr . update_after_seek ( ) ;
1022- }
10231187}
10241188
10251189// util function
0 commit comments