From 1a0df21bf720706321e3fdeac147005e0631b750 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 11 Jul 2024 14:40:59 -0400 Subject: [PATCH] [draft] Add borrowing for fs_utf8::Dir I'd like to start using `fs_utf8::Dir`, but not in a "big bang" fashion where I wholesale convert the entire codebase. It feels normal and natural to have a non-utf8 `Dir` instance and maybe sometimes just want to "view" it as utf8. At an efficiency level, having to create a new owned fd for this feels unnecessary. This sketches out an implementation where we can also support borrowing an existing fd. This doesn't compile, but before I do a lot more typing on this - consider it an RFC. Is this a good direction? --- cap-std/src/fs_utf8/dir.rs | 46 ++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/cap-std/src/fs_utf8/dir.rs b/cap-std/src/fs_utf8/dir.rs index 410027e9..87854f3d 100644 --- a/cap-std/src/fs_utf8/dir.rs +++ b/cap-std/src/fs_utf8/dir.rs @@ -11,6 +11,7 @@ use io_lifetimes::AsFilelike; use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; +use std::ops::Deref; use std::{fmt, fs, io}; #[cfg(windows)] use { @@ -21,6 +22,28 @@ use { std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, }; +enum DirImpl<'a> { + Owned(crate::fs::Dir), + Borrowed(&'a crate::fs::Dir), +} + +impl<'a> Deref for DirImpl<'a> { + type Target = crate::fs::Dir; + + fn deref(&self) -> &Self::Target { + match self { + DirImpl::Owned(d) => d, + DirImpl::Borrowed(d) => d, + } + } +} + +impl<'a> From for DirImpl<'a> { + fn from(value: crate::fs::Dir) -> Self { + Self::Owned(value) + } +} + /// A reference to an open directory on a filesystem. /// /// This does not directly correspond to anything in `std`, however its methods @@ -31,11 +54,11 @@ use { /// absolute paths don't interoperate well with the capability model. /// /// [functions in `std::fs`]: https://doc.rust-lang.org/std/fs/index.html#functions -pub struct Dir { - cap_std: crate::fs::Dir, +pub struct Dir<'a> { + cap_std: DirImpl<'a>, } -impl Dir { +impl<'a> Dir<'a> { /// Constructs a new instance of `Self` from the given [`std::fs::File`]. /// /// To prevent race conditions on Windows, the file must be opened without @@ -51,7 +74,16 @@ impl Dir { /// Constructs a new instance of `Self` from the given `cap_std::fs::Dir`. #[inline] pub fn from_cap_std(cap_std: crate::fs::Dir) -> Self { - Self { cap_std } + Self { + cap_std: cap_std.into(), + } + } + + #[inline] + pub fn borrow_cap_std(cap_std: &crate::fs::Dir) -> Self { + Self { + cap_std: DirImpl::Borrowed(cap_std), + } } /// Return a view of this directory as a [`cap_std::fs::Dir`]. This @@ -838,3 +870,9 @@ impl fmt::Debug for Dir { self.cap_std.fmt(f) } } + +impl From<&crate::fs::Dir> for Dir { + fn from(value: &crate::fs::Dir) -> Self { + Self::borrow_cap_std(value) + } +}