]> git.proxmox.com Git - pxar.git/commitdiff
Get rid of dyn ReadAt usage
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 13 May 2020 11:53:37 +0000 (13:53 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 13 May 2020 11:53:38 +0000 (13:53 +0200)
It causes auto traits to be lost across await points.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
src/accessor.rs

index 6a3ca88d8f7ef6356005673aa0dc481d331035e8..500806dc3e9eb33822ac1cb1a019570de0c69c37 100644 (file)
@@ -38,50 +38,51 @@ pub trait ReadAt {
     ) -> Poll<io::Result<usize>>;
 }
 
-/// We do not want to bother with actual polling, so we implement `async fn` variants of the above
-/// on `dyn ReadAt`.
-///
-/// The reason why this is not an internal `ReadAtExt` trait like `AsyncReadExt` is simply that
-/// we'd then need to define all the `Future` types they return manually and explicitly. Since we
-/// have no use for them, all we want is the ability to use `async fn`...
-///
-/// The downside is that we need some `(&mut self.input as &mut dyn ReadAt)` casts in the
-/// decoder's code, but that's fine.
-impl<'a> dyn ReadAt + 'a {
-    /// awaitable version of `poll_read_at`.
-    async fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
-        poll_fn(|cx| unsafe { Pin::new_unchecked(self).poll_read_at(cx, buf, offset) }).await
-    }
-
-    /// `read_exact_at` - since that's what we _actually_ want most of the time.
-    async fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
-        while !buf.is_empty() {
-            match self.read_at(buf, offset).await? {
-                0 => io_bail!("unexpected EOF"),
-                got => {
-                    buf = &mut buf[got..];
-                    offset += got as u64;
-                }
+/// awaitable version of `poll_read_at`.
+async fn read_at<T>(input: &T, buf: &mut [u8], offset: u64) -> io::Result<usize>
+where
+    T: ReadAt + ?Sized,
+{
+    poll_fn(|cx| unsafe { Pin::new_unchecked(input).poll_read_at(cx, buf, offset) }).await
+}
+
+/// `read_exact_at` - since that's what we _actually_ want most of the time.
+async fn read_exact_at<T>(input: &T, mut buf: &mut [u8], mut offset: u64) -> io::Result<()>
+where
+    T: ReadAt + ?Sized,
+{
+    while !buf.is_empty() {
+        match read_at(input, buf, offset).await? {
+            0 => io_bail!("unexpected EOF"),
+            got => {
+                buf = &mut buf[got..];
+                offset += got as u64;
             }
         }
-        Ok(())
     }
+    Ok(())
+}
 
-    /// Helper to read into an `Endian`-implementing `struct`.
-    async fn read_entry_at<T: Endian>(&self, offset: u64) -> io::Result<T> {
-        let mut data = MaybeUninit::<T>::uninit();
-        let buf =
-            unsafe { std::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut u8, size_of::<T>()) };
-        self.read_exact_at(buf, offset).await?;
-        Ok(unsafe { data.assume_init().from_le() })
-    }
+/// Helper to read into an `Endian`-implementing `struct`.
+async fn read_entry_at<T, E: Endian>(input: &T, offset: u64) -> io::Result<E>
+where
+    T: ReadAt + ?Sized,
+{
+    let mut data = MaybeUninit::<E>::uninit();
+    let buf =
+        unsafe { std::slice::from_raw_parts_mut(data.as_mut_ptr() as *mut u8, size_of::<E>()) };
+    read_exact_at(input, buf, offset).await?;
+    Ok(unsafe { data.assume_init().from_le() })
+}
 
-    /// Helper to read into an allocated byte vector.
-    async fn read_exact_data_at(&self, size: usize, offset: u64) -> io::Result<Vec<u8>> {
-        let mut data = util::vec_new(size);
-        self.read_exact_at(&mut data[..], offset).await?;
-        Ok(data)
-    }
+/// Helper to read into an allocated byte vector.
+async fn read_exact_data_at<T>(input: &T, size: usize, offset: u64) -> io::Result<Vec<u8>>
+where
+    T: ReadAt + ?Sized,
+{
+    let mut data = util::vec_new(size);
+    read_exact_at(input, &mut data[..], offset).await?;
+    Ok(data)
 }
 
 /// Allow using trait objects for `T: ReadAt`
@@ -296,9 +297,7 @@ impl<T: Clone + ReadAt> DirectoryImpl<T> {
                 data.as_mut_ptr() as *mut u8,
                 len * size_of::<GoodbyeItem>(),
             );
-            (&self.input as &dyn ReadAt)
-                .read_exact_at(slice, self.table_offset())
-                .await?;
+            read_exact_at(&self.input, slice, self.table_offset()).await?;
             drop(slice);
         }
         Ok(Arc::from(data))
@@ -331,13 +330,13 @@ impl<T: Clone + ReadAt> DirectoryImpl<T> {
     }
 
     /// Read the goodbye tail and perform some sanity checks.
-    async fn read_tail_entry(input: &'_ dyn ReadAt, end_offset: u64) -> io::Result<GoodbyeItem> {
+    async fn read_tail_entry(input: &T, end_offset: u64) -> io::Result<GoodbyeItem> {
         if end_offset < (size_of::<GoodbyeItem>() as u64) {
             io_bail!("goodbye tail does not fit");
         }
 
         let tail_offset = end_offset - (size_of::<GoodbyeItem>() as u64);
-        let tail: GoodbyeItem = input.read_entry_at(tail_offset).await?;
+        let tail: GoodbyeItem = read_entry_at(input, tail_offset).await?;
 
         if tail.hash != format::PXAR_GOODBYE_TAIL_MARKER {
             io_bail!("no goodbye tail marker found");
@@ -502,17 +501,17 @@ impl<T: Clone + ReadAt> DirectoryImpl<T> {
     }
 
     async fn read_filename_entry(&self, file_ofs: u64) -> io::Result<(PathBuf, u64)> {
-        let head: format::Header = (&self.input as &dyn ReadAt).read_entry_at(file_ofs).await?;
+        let head: format::Header = read_entry_at(&self.input, file_ofs).await?;
         if head.htype != format::PXAR_FILENAME {
             io_bail!("expected PXAR_FILENAME header, found: {:x}", head.htype);
         }
 
-        let mut path = (&self.input as &dyn ReadAt)
-            .read_exact_data_at(
-                head.content_size() as usize,
-                file_ofs + (size_of_val(&head) as u64),
-            )
-            .await?;
+        let mut path = read_exact_data_at(
+            &self.input,
+            head.content_size() as usize,
+            file_ofs + (size_of_val(&head) as u64),
+        )
+        .await?;
 
         if path.pop() != Some(0) {
             io_bail!("invalid file name (missing terminating zero)");
@@ -702,9 +701,7 @@ impl<T: Clone + ReadAt> FileContentsImpl<T> {
             buf = &mut buf[..(remaining as usize)];
         }
 
-        (&self.input as &dyn ReadAt)
-            .read_at(buf, self.range.start + offset)
-            .await
+        read_at(&self.input, buf, self.range.start + offset).await
     }
 }