}
/// Open a directory handle to the root of the pxar archive.
- pub async fn open_root_ref<'a>(&'a self) -> io::Result<Directory<&'a dyn ReadAt>> {
+ pub async fn open_root_ref(&self) -> io::Result<Directory<&dyn ReadAt>> {
Ok(Directory::new(self.inner.open_root_ref().await?))
}
}
/// Allow opening a directory at a specified offset.
+ ///
+ /// # Safety
+ ///
+ /// This should only be used with offsets known to point to the end of a directory, otherwise
+ /// this usually fails, unless the data otherwise happens to look like a valid directory.
pub async unsafe fn open_dir_at_end(&self, offset: u64) -> io::Result<Directory<T>> {
Ok(Directory::new(self.inner.open_dir_at_end(offset).await?))
}
/// Allow opening a regular file from a specified range.
+ ///
+ /// # Safety
+ ///
+ /// Should only be used with `entry_range_info`s originating from the same archive, otherwise
+ /// the result will be undefined and likely fail (or contain unexpected data).
pub async unsafe fn open_file_at_range(
&self,
entry_range_info: &accessor::EntryRangeInfo,
}
/// Allow opening arbitrary contents from a specific range.
+ ///
+ /// # Safety
+ ///
+ /// This will provide a reader over an arbitrary range of the archive file, so unless this
+ /// comes from a actual file entry data, the contents might not make much sense.
pub unsafe fn open_contents_at_range(&self, range: Range<u64>) -> FileContents<T> {
FileContents {
inner: self.inner.open_contents_at_range(range),
}
/// Get an iterator over the directory's contents.
- pub fn read_dir<'a>(&'a self) -> ReadDir<'a, T> {
+ pub fn read_dir(&self) -> ReadDir<T> {
ReadDir {
inner: self.inner.read_dir(),
}
}
}
+/// File content read future result.
+struct ReadResult {
+ len: usize,
+ buffer: Vec<u8>,
+}
+
/// A reader for file contents.
pub struct FileContents<T> {
inner: accessor::FileContentsImpl<T>,
at: u64,
buffer: Vec<u8>,
- future: Option<Pin<Box<dyn Future<Output = io::Result<(usize, Vec<u8>)>> + 'static>>>,
+ future: Option<Pin<Box<dyn Future<Output = io::Result<ReadResult>> + 'static>>>,
}
// We lose `Send` via the boxed trait object and don't want to force the trait object to
util::scale_read_buffer(&mut buffer, dest.len());
let reader: accessor::FileContentsImpl<T> = this.inner.clone();
let at = this.at;
- let future: Pin<Box<dyn Future<Output = io::Result<(usize, Vec<u8>)>>>> =
+ let future: Pin<Box<dyn Future<Output = io::Result<ReadResult>>>> =
Box::pin(async move {
- let got = reader.read_at(&mut buffer, at).await?;
- io::Result::Ok((got, buffer))
+ let len = reader.read_at(&mut buffer, at).await?;
+ io::Result::Ok(ReadResult { len, buffer })
});
// This future has the lifetime from T. Self also has this lifetime and we
// store this in a pinned self. T maybe a reference with a non-'static life
return Poll::Pending;
}
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
- Poll::Ready(Ok((got, buffer))) => {
+ Poll::Ready(Ok(ReadResult { len: got, buffer })) => {
this.buffer = buffer;
this.at += got as u64;
let len = got.min(dest.len());
self.size
}
- pub async fn open_root_ref<'a>(&'a self) -> io::Result<DirectoryImpl<&'a dyn ReadAt>> {
+ pub async fn open_root_ref(&self) -> io::Result<DirectoryImpl<&dyn ReadAt>> {
DirectoryImpl::open_at_end(
&self.input as &dyn ReadAt,
self.size,
) {
let new_caches = Arc::new(Caches {
gbt_cache: cache,
- ..*self.caches
+ //..*self.caches
});
self.caches = new_caches;
}
len * size_of::<GoodbyeItem>(),
);
read_exact_at(&self.input, slice, self.table_offset()).await?;
- drop(slice);
}
Ok(Arc::from(data))
}
}
}
+ // while clippy is technically right about this, the compiler won't accept it (yet)
+ #[allow(clippy::needless_lifetimes)]
async fn get_cursor<'a>(&'a self, index: usize) -> io::Result<DirEntryImpl<'a, T>> {
let entry = &self.table[index];
let file_goodbye_ofs = entry.offset;
}
}
+/// File content read future result.
+struct ReadResult {
+ len: usize,
+ buffer: Vec<u8>,
+}
+
#[doc(hidden)]
pub struct SeqReadAtAdapter<T> {
input: T,
range: Range<u64>,
buffer: Vec<u8>,
- future: Option<Pin<Box<dyn Future<Output = io::Result<(usize, Vec<u8>)>> + 'static>>>,
+ future: Option<Pin<Box<dyn Future<Output = io::Result<ReadResult>> + 'static>>>,
}
// We lose `Send` via the boxed trait object and don't want to force the trait object to
let reader = &this.input;
let at = this.range.start;
- let future: Pin<Box<dyn Future<Output = io::Result<(usize, Vec<u8>)>>>> =
+ let future: Pin<Box<dyn Future<Output = io::Result<ReadResult>>>> =
Box::pin(async move {
- let got = reader.read_at(&mut buffer, at).await?;
- io::Result::Ok((got, buffer))
+ let len = reader.read_at(&mut buffer, at).await?;
+ io::Result::Ok(ReadResult { len, buffer })
});
// Ditch the self-reference life-time now:
this.future = Some(unsafe { mem::transmute(future) });
return Poll::Pending;
}
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
- Poll::Ready(Ok((got, buffer))) => {
+ Poll::Ready(Ok(ReadResult { len: got, buffer })) => {
this.buffer = buffer;
this.range.start += got as u64;
let len = got.min(dest.len());
}
/// Allow opening a directory at a specified offset.
+ ///
+ /// # Safety
+ ///
+ /// This should only be used with offsets known to point to the end of a directory, otherwise
+ /// this usually fails, unless the data otherwise happens to look like a valid directory.
pub unsafe fn open_dir_at_end(&self, offset: u64) -> io::Result<Directory<T>> {
Ok(Directory::new(poll_result_once(
self.inner.open_dir_at_end(offset),
}
/// Allow opening a regular file from a specified range.
+ ///
+ /// # Safety
+ ///
+ /// Should only be used with `entry_range_info`s originating from the same archive, otherwise
+ /// the result will be undefined and likely fail (or contain unexpected data).
pub unsafe fn open_file_at_range(
&self,
entry_range_info: &accessor::EntryRangeInfo,
}
/// Allow opening arbitrary contents from a specific range.
+ ///
+ /// # Safety
+ ///
+ /// This will provide a reader over an arbitrary range of the archive file, so unless this
+ /// comes from a actual file entry data, the contents might not make much sense.
pub unsafe fn open_contents_at_range(&self, range: Range<u64>) -> FileContents<T> {
FileContents {
inner: self.inner.open_contents_at_range(range),
}
/// Get an iterator over the directory's contents.
- pub fn read_dir<'a>(&'a self) -> ReadDir<'a, T> {
+ pub fn read_dir(&self) -> ReadDir<T> {
ReadDir {
inner: self.inner.read_dir(),
}
Self { inner }
}
+ // I would normally agree with clippy, but this is async and we can at most implement Stream,
+ // which we do with feature flags...
+ #[allow(clippy::should_implement_trait)]
/// If this is a directory entry, get the next item inside the directory.
pub async fn next(&mut self) -> Option<io::Result<Entry>> {
self.inner.next_do().await.transpose()
///
/// As long as streams are poll-based this wrapper is required to turn `async fn next()` into
/// `Stream`'s `poll_next()` interface.
+ #[allow(clippy::type_complexity)] // yeah no
pub struct DecoderStream<T> {
inner: super::Decoder<T>,
future: Option<Pin<Box<dyn Future<Output = Option<io::Result<Entry>>>>>>,
}
}
- pub fn content_reader<'a>(&'a mut self) -> Option<Contents<'a, I>> {
+ pub fn content_reader(&mut self) -> Option<Contents<I>> {
if let State::InPayload { offset } = &mut self.state {
Some(Contents::new(
&mut self.input,
Self { inner }
}
+ // I would normally agree with clippy, but this here is to be consistent with the async
+ // counterpart, and we *do* implement Iterator as well, so that's fine!
+ #[allow(clippy::should_implement_trait)]
/// If this is a directory entry, get the next item inside the directory.
pub fn next(&mut self) -> Option<io::Result<Entry>> {
poll_result_once(self.inner.next_do()).transpose()
fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
let this = unsafe { self.get_unchecked_mut() };
match this.inner.as_mut() {
- None => return Poll::Ready(Ok(())),
+ None => Poll::Ready(Ok(())),
Some(inner) => {
ready!(unsafe { Pin::new_unchecked(inner).poll_close(cx) })?;
this.inner = None;
fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
let this = unsafe { self.get_unchecked_mut() };
match this.inner.as_mut() {
- None => return Poll::Ready(Ok(())),
+ None => Poll::Ready(Ok(())),
Some(inner) => {
ready!(unsafe { Pin::new_unchecked(inner).poll_shutdown(cx) })?;
this.inner = None;
entry_offset,
files_offset,
file_offset: Some(file_offset),
- file_hash: file_hash,
+ file_hash,
..Default::default()
},
parent: Some(&mut self.state),
seq_write_pxar_struct_entry(
&mut self.output,
format::PXAR_QUOTA_PROJID,
- quota_project_id.clone(),
+ *quota_project_id,
)
.await
}
let file_type = meta.file_type();
let mode = this.mode;
- let this = if file_type.is_dir() {
+ if file_type.is_dir() {
this.mode(mode | mode::IFDIR)
} else if file_type.is_symlink() {
this.mode(mode | mode::IFLNK)
} else {
this.mode(mode | mode::IFREG)
- };
-
- this
+ }
}
}
impl From<&std::fs::Metadata> for Metadata {
fn from(meta: &std::fs::Metadata) -> Metadata {
- let this = Self::from(Stat::from(meta));
-
- // FIXME: fill the remaining metadata
-
- this
+ // NOTE: fill the remaining metadata via feature flags?
+ Self::from(Stat::from(meta))
}
}
/// Convenience method to get just the file name portion of the current path.
#[inline]
pub fn file_name(&self) -> &OsStr {
- self.path.file_name().unwrap_or(OsStr::new(""))
+ self.path.file_name().unwrap_or_else(|| OsStr::new(""))
}
/// Get the file metadata.