From a34a30238e0aa9d7c4585caef59a4da6b8737f16 Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Sat, 16 Mar 2024 21:07:05 +0100 Subject: [PATCH] feat: rc-zip-tokio: Re-use cursor if it's at the right offset already (#71) * feat: rc-zip-tokio: Re-use cursor if it's at the right offset already cf. #61 * feat: rc-zip: Re-use cursor if it's at the right offset --- rc-zip-sync/src/read_zip.rs | 31 +++++++++++++++++++++++++++++-- rc-zip-tokio/src/read_zip.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/rc-zip-sync/src/read_zip.rs b/rc-zip-sync/src/read_zip.rs index a9679d5..ad1447a 100644 --- a/rc-zip-sync/src/read_zip.rs +++ b/rc-zip-sync/src/read_zip.rs @@ -40,13 +40,40 @@ where type File = F; fn read_zip_with_size(&self, size: u64) -> Result, Error> { - trace!(%size, "read_zip_with_size"); + struct CursorState<'a, F: HasCursor + 'a> { + cursor: ::Cursor<'a>, + offset: u64, + } + let mut cstate: Option> = None; + let mut fsm = ArchiveFsm::new(size); loop { if let Some(offset) = fsm.wants_read() { trace!(%offset, "read_zip_with_size: wants_read, space len = {}", fsm.space().len()); - match self.cursor_at(offset).read(fsm.space()) { + + let mut cstate_next = match cstate.take() { + Some(cstate) => { + if cstate.offset == offset { + // all good, re-using + cstate + } else { + CursorState { + cursor: self.cursor_at(offset), + offset, + } + } + } + None => CursorState { + cursor: self.cursor_at(offset), + offset, + }, + }; + + match cstate_next.cursor.read(fsm.space()) { Ok(read_bytes) => { + cstate_next.offset += read_bytes as u64; + cstate = Some(cstate_next); + trace!(%read_bytes, "read_zip_with_size: read"); if read_bytes == 0 { return Err(Error::IO(std::io::ErrorKind::UnexpectedEof.into())); diff --git a/rc-zip-tokio/src/read_zip.rs b/rc-zip-tokio/src/read_zip.rs index f64dae6..5111d0b 100644 --- a/rc-zip-tokio/src/read_zip.rs +++ b/rc-zip-tokio/src/read_zip.rs @@ -46,11 +46,41 @@ where type File = F; async fn read_zip_with_size(&self, size: u64) -> Result, Error> { + struct CursorState<'a, F: HasCursor + 'a> { + cursor: ::Cursor<'a>, + offset: u64, + } + let mut cstate: Option> = None; + let mut fsm = ArchiveFsm::new(size); loop { if let Some(offset) = fsm.wants_read() { - match self.cursor_at(offset).read(fsm.space()).await { + trace!(%offset, "read_zip_with_size: wants_read, space len = {}", fsm.space().len()); + + let mut cstate_next = match cstate.take() { + Some(cstate) => { + if cstate.offset == offset { + // all good, re-using + cstate + } else { + CursorState { + cursor: self.cursor_at(offset), + offset, + } + } + } + None => CursorState { + cursor: self.cursor_at(offset), + offset, + }, + }; + + match cstate_next.cursor.read(fsm.space()).await { Ok(read_bytes) => { + cstate_next.offset += read_bytes as u64; + cstate = Some(cstate_next); + + trace!(%read_bytes, "read_zip_with_size: read"); if read_bytes == 0 { return Err(Error::IO(io::ErrorKind::UnexpectedEof.into())); }