Skip to content

Commit

Permalink
dir: Add convenience functions for accessing UTF-8 variants (#362)
Browse files Browse the repository at this point in the history
I'd like to make use of the fs_utf8 bits in some of my code,
but doing so is tricky as switching `Dir` types quickly becomes
"infectious" across the codebase and forces a larger conversion
all at once.

Adding these these two convenience APIs on `Dir` (the non-UTF8 version)
I think greatly improve the ergonomics for the common cases
where I may want to *view* an existing `Dir` entries (without
creating a new file descriptor) and iterate over its entries,
and to conveniently open a child dir as a utf-8 version.

There are more methods we could add, but these feel like
a useful start to me.
  • Loading branch information
cgwalters authored Jul 23, 2024
1 parent 076ab49 commit 401a42c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
21 changes: 21 additions & 0 deletions cap-std/src/fs/dir.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#[cfg(target_os = "wasi")]
use crate::fs::OpenOptionsExt;
use crate::fs::{DirBuilder, File, Metadata, OpenOptions, ReadDir};
#[cfg(feature = "fs_utf8")]
use crate::fs_utf8::Dir as DirUtf8;
#[cfg(unix)]
use crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
#[cfg(not(target_os = "wasi"))]
Expand Down Expand Up @@ -109,6 +111,16 @@ impl Dir {
Ok(Self::from_std_file(dir))
}

/// Attempts to open a directory, verifying UTF-8.
///
/// This is equivalent to [`crate::fs_utf8::Dir::open_dir`].
#[inline]
#[cfg(feature = "fs_utf8")]
pub fn open_dir_utf8<P: AsRef<camino::Utf8Path>>(&self, path: P) -> io::Result<DirUtf8> {
let path = crate::fs_utf8::from_utf8(path.as_ref())?;
self.open_dir(path).map(DirUtf8::from_cap_std)
}

/// Creates a new, empty directory at the provided path.
///
/// This corresponds to [`std::fs::create_dir`], but only accesses paths
Expand Down Expand Up @@ -261,6 +273,15 @@ impl Dir {
read_base_dir(&self.std_file).map(|inner| ReadDir { inner })
}

/// Returns an iterator over UTF-8 entries within `self`.
///
/// Equivalent to [`crate::fs_utf8::Dir::read_dir`].
#[inline]
#[cfg(feature = "fs_utf8")]
pub fn entries_utf8(&self) -> io::Result<crate::fs_utf8::ReadDir> {
self.entries().map(crate::fs_utf8::ReadDir::from_cap_std)
}

/// Returns an iterator over the entries within a directory.
///
/// This corresponds to [`std::fs::read_dir`], but only accesses paths
Expand Down
4 changes: 2 additions & 2 deletions cap-std/src/fs_utf8/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ pub use camino;
use camino::{Utf8Path, Utf8PathBuf};

#[cfg(not(feature = "arf_strings"))]
fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<&'a std::path::Path> {
pub(crate) fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<&'a std::path::Path> {
Ok(path.as_std_path())
}

#[cfg(feature = "arf_strings")]
fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<std::path::PathBuf> {
pub(crate) fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<std::path::PathBuf> {
#[cfg(not(windows))]
let path = {
#[cfg(unix)]
Expand Down
13 changes: 13 additions & 0 deletions tests/fs_utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1680,3 +1680,16 @@ fn test_invalid_utf8() {
}
}
}

#[test]
fn from_cap_std() {
let tmpdir = sys_common::io::tmpdir();
let dir = "d1/d2";
check!(tmpdir.create_dir_all(dir));
let d1_entry = tmpdir.entries_utf8().unwrap().next().unwrap().unwrap();
assert_eq!(d1_entry.file_name().unwrap(), "d1");

let d1 = tmpdir.open_dir_utf8("d1").unwrap();
let d2_entry = d1.entries().unwrap().next().unwrap().unwrap();
assert_eq!(d2_entry.file_name().unwrap(), "d2");
}

0 comments on commit 401a42c

Please sign in to comment.