Skip to content

Commit 9fce63a

Browse files
committed
Allow usage without Seek: RevReader approach
Implemented my proposal to resolve RustAudio#12 .
1 parent 0910d8d commit 9fce63a

File tree

1 file changed

+192
-28
lines changed

1 file changed

+192
-28
lines changed

src/reading.rs

Lines changed: 192 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
532680
enum UntilPageHeaderReaderMode {
533681
Searching,
534682
FoundWithNeeded(u8),
535-
SeekNeeded(i32),
683+
RevertNeeded(usize),
536684
Found,
537685
}
538686

539687
enum UntilPageHeaderResult {
540688
Eof,
541689
Found,
542690
ReadNeeded,
543-
SeekNeeded,
691+
RevertNeeded,
544692
}
545693

546694
struct 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.
715867
If you desire async functionality, consider enabling the `async` feature
716868
and 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

Comments
 (0)