Skip to content

Commit c3278f6

Browse files
committed
Add Dir::open(_file) and some trait impls
1 parent beeb8e3 commit c3278f6

File tree

13 files changed

+889
-95
lines changed

13 files changed

+889
-95
lines changed

library/std/src/fs.rs

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,33 @@ pub enum TryLockError {
153153
WouldBlock,
154154
}
155155

156+
/// An object providing access to a directory on the filesystem.
157+
///
158+
/// Files are automatically closed when they go out of scope. Errors detected
159+
/// on closing are ignored by the implementation of `Drop`.
160+
///
161+
/// # Examples
162+
///
163+
/// Opens a directory and then a file inside it.
164+
///
165+
/// ```no_run
166+
/// #![feature(dirfd)]
167+
/// use std::{fs::Dir, io::Read};
168+
///
169+
/// fn main() -> std::io::Result<()> {
170+
/// let dir = Dir::new("foo")?;
171+
/// let mut file = dir.open("bar.txt")?;
172+
/// let mut s = String::new();
173+
/// file.read_to_string(&mut s)?;
174+
/// println!("{}", s);
175+
/// Ok(())
176+
/// }
177+
/// ```
178+
#[unstable(feature = "dirfd", issue = "120426")]
179+
pub struct Dir {
180+
inner: fs_imp::Dir,
181+
}
182+
156183
/// Metadata information about a file.
157184
///
158185
/// This structure is returned from the [`metadata`] or
@@ -1474,6 +1501,89 @@ impl Seek for Arc<File> {
14741501
}
14751502
}
14761503

1504+
impl Dir {
1505+
/// Attempts to open a directory at `path` in read-only mode.
1506+
///
1507+
/// See [`new_with`] for more options.
1508+
///
1509+
/// # Errors
1510+
///
1511+
/// This function will return an error if `path` does not point to an existing directory.
1512+
/// Other errors may also be returned according to [`OpenOptions::open`].
1513+
///
1514+
/// # Examples
1515+
///
1516+
/// ```no_run
1517+
/// #![feature(dirfd)]
1518+
/// use std::{fs::Dir, io::Read};
1519+
///
1520+
/// fn main() -> std::io::Result<()> {
1521+
/// let dir = Dir::new("foo")?;
1522+
/// let mut f = dir.open("bar.txt")?;
1523+
/// let mut data = vec![];
1524+
/// f.read_to_end(&mut data)?;
1525+
/// Ok(())
1526+
/// }
1527+
/// ```
1528+
///
1529+
/// [`new_with`]: Dir::new_with
1530+
#[unstable(feature = "dirfd", issue = "120426")]
1531+
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
1532+
fs_imp::Dir::open(path).map(|inner| Self { inner })
1533+
}
1534+
1535+
///
1536+
/// Attempts to open a file in read-only mode relative to this directory.
1537+
///
1538+
/// # Errors
1539+
///
1540+
/// This function will return an error if `path` does not point to an existing file.
1541+
/// Other errors may also be returned according to [`OpenOptions::open`].
1542+
///
1543+
/// # Examples
1544+
///
1545+
/// ```no_run
1546+
/// #![feature(dirfd)]
1547+
/// use std::{fs::Dir, io::Read};
1548+
///
1549+
/// fn main() -> std::io::Result<()> {
1550+
/// let dir = Dir::new("foo")?;
1551+
/// let mut f = dir.open("bar.txt")?;
1552+
/// let mut data = vec![];
1553+
/// f.read_to_end(&mut data)?;
1554+
/// Ok(())
1555+
/// }
1556+
/// ```
1557+
#[unstable(feature = "dirfd", issue = "120426")]
1558+
pub fn open_file<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
1559+
self.inner.open_file(path).map(|f| File { inner: f })
1560+
}
1561+
}
1562+
1563+
impl AsInner<fs_imp::Dir> for Dir {
1564+
#[inline]
1565+
fn as_inner(&self) -> &fs_imp::Dir {
1566+
&self.inner
1567+
}
1568+
}
1569+
impl FromInner<fs_imp::Dir> for Dir {
1570+
fn from_inner(f: fs_imp::Dir) -> File {
1571+
Dir { inner: f }
1572+
}
1573+
}
1574+
impl IntoInner<fs_imp::Dir> for Dir {
1575+
fn into_inner(self) -> fs_imp::Dir {
1576+
self.inner
1577+
}
1578+
}
1579+
1580+
#[unstable(feature = "dirfd", issue = "120426")]
1581+
impl fmt::Debug for Dir {
1582+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1583+
self.inner.fmt(f)
1584+
}
1585+
}
1586+
14771587
impl OpenOptions {
14781588
/// Creates a blank new set of options ready for configuration.
14791589
///
@@ -2440,6 +2550,178 @@ impl DirEntry {
24402550
pub fn file_name(&self) -> OsString {
24412551
self.0.file_name()
24422552
}
2553+
2554+
/// Attempts to open the file represented by `self` in read-only mode.
2555+
///
2556+
/// # Errors
2557+
///
2558+
/// This function will error whenever [`File::open`] would error, including when `self`
2559+
/// represents a directory.
2560+
///
2561+
/// # Examples
2562+
///
2563+
/// ```no_run
2564+
/// #![feature(dirfd)]
2565+
/// use std::{fs, io::read_to_string};
2566+
///
2567+
/// if let Ok(entries) = fs::read_dir(".") {
2568+
/// for entry in entries {
2569+
/// if let Ok(entry) = entry {
2570+
/// // Here, `entry` is a `DirEntry`.
2571+
/// if let Ok(file) = entry.open_file() && let Ok(text) = read_to_string(file) {
2572+
/// println!("{}", text);
2573+
/// }
2574+
/// }
2575+
/// }
2576+
/// }
2577+
/// ```
2578+
#[unstable(feature = "dirfd", issue = "120426")]
2579+
pub fn open_file(&self) -> io::Result<File> {
2580+
self.0.open_file().map(|inner| File { inner })
2581+
}
2582+
2583+
/// Attempts to open the file represented by `self` with the options specified by `opts`.
2584+
///
2585+
/// # Errors
2586+
///
2587+
/// This function will error whenever [`OpenOptions::open`] would error, including when `self`
2588+
/// represents a directory.
2589+
///
2590+
/// # Examples
2591+
///
2592+
/// ```no_run
2593+
/// #![feature(dirfd)]
2594+
/// use std::{fs, io::Write};
2595+
///
2596+
/// if let Ok(entries) = fs::read_dir(".") {
2597+
/// for entry in entries {
2598+
/// if let Ok(entry) = entry {
2599+
/// // Here, `entry` is a `DirEntry`.
2600+
/// if let Ok(mut file) = entry.open_file_with(fs::OpenOptions::new().write(true)) {
2601+
/// let _ = file.write(b"foo");
2602+
/// }
2603+
/// }
2604+
/// }
2605+
/// }
2606+
/// ```
2607+
#[unstable(feature = "dirfd", issue = "120426")]
2608+
pub fn open_file_with(&self, opts: &OpenOptions) -> io::Result<File> {
2609+
self.0.open_file_with(&opts.0).map(|inner| File { inner })
2610+
}
2611+
2612+
/// Attempts to open the directory represented by `self` in read-only mode.
2613+
///
2614+
/// # Errors
2615+
///
2616+
/// This function will error whenever [`Dir::new`] would error, including when `self`
2617+
/// represents a file.
2618+
///
2619+
/// # Examples
2620+
///
2621+
/// ```no_run
2622+
/// #![feature(dirfd)]
2623+
/// use std::{fs, io::read_to_string};
2624+
///
2625+
/// if let Ok(entries) = fs::read_dir(".") {
2626+
/// for entry in entries {
2627+
/// if let Ok(entry) = entry {
2628+
/// // Here, `entry` is a `DirEntry`.
2629+
/// if let Ok(dir) = entry.open_dir() && let Ok(file) = dir.open("foo") && let Ok(text) = read_to_string(file) {
2630+
/// println!("{}", text);
2631+
/// }
2632+
/// }
2633+
/// }
2634+
/// }
2635+
/// ```
2636+
#[unstable(feature = "dirfd", issue = "120426")]
2637+
pub fn open_dir(&self) -> io::Result<Dir> {
2638+
self.0.open_dir().map(|inner| Dir { inner })
2639+
}
2640+
2641+
/// Attempts to open the directory represented by `self` with the options specified by `opts`.
2642+
///
2643+
/// # Errors
2644+
///
2645+
/// This function will error whenever [`Dir::new_with`] would error, including when `self`
2646+
/// represents a file.
2647+
///
2648+
/// # Examples
2649+
///
2650+
/// ```no_run
2651+
/// #![feature(dirfd)]
2652+
/// use std::fs;
2653+
///
2654+
/// if let Ok(entries) = fs::read_dir(".") {
2655+
/// for entry in entries {
2656+
/// if let Ok(entry) = entry {
2657+
/// // Here, `entry` is a `DirEntry`.
2658+
/// if let Ok(dir) = entry.open_dir_with(fs::OpenOptions::new().write(true)) {
2659+
/// let _ = dir.remove_file("foo");
2660+
/// }
2661+
/// }
2662+
/// }
2663+
/// }
2664+
/// ```
2665+
#[unstable(feature = "dirfd", issue = "120426")]
2666+
pub fn open_dir_with(&self, opts: &OpenOptions) -> io::Result<Dir> {
2667+
self.0.open_dir_with(&opts.0).map(|inner| Dir { inner })
2668+
}
2669+
2670+
/// Attempts to remove the file represented by `self`.
2671+
///
2672+
/// # Errors
2673+
///
2674+
/// This function will return an error whenever [`remove_file`] would error.
2675+
///
2676+
/// # Examples
2677+
///
2678+
/// ```no_run
2679+
/// #![feature(dirfd)]
2680+
/// use std::fs;
2681+
///
2682+
/// if let Ok(entries) = fs::read_dir(".") {
2683+
/// for entry in entries {
2684+
/// if let Ok(entry) = entry {
2685+
/// // Here, `entry` is a `DirEntry`.
2686+
/// if let Ok(ty) = entry.file_type() && ty.is_file() {
2687+
/// let _ = entry.remove_file();
2688+
/// }
2689+
/// }
2690+
/// }
2691+
/// }
2692+
/// ```
2693+
#[unstable(feature = "dirfd", issue = "120426")]
2694+
pub fn remove_file(&self) -> io::Result<()> {
2695+
self.0.remove_file()
2696+
}
2697+
2698+
/// Attempts to remove the directory represented by `self`.
2699+
///
2700+
/// # Errors
2701+
///
2702+
/// This function will return an error whenever [`remove_dir`] would error.
2703+
///
2704+
/// # Examples
2705+
///
2706+
/// ```no_run
2707+
/// #![feature(dirfd)]
2708+
/// use std::fs;
2709+
///
2710+
/// if let Ok(entries) = fs::read_dir(".") {
2711+
/// for entry in entries {
2712+
/// if let Ok(entry) = entry {
2713+
/// // Here, `entry` is a `DirEntry`.
2714+
/// if let Ok(ty) = entry.file_type() && ty.is_dir() {
2715+
/// let _ = entry.remove_dir();
2716+
/// }
2717+
/// }
2718+
/// }
2719+
/// }
2720+
/// ```
2721+
#[unstable(feature = "dirfd", issue = "120426")]
2722+
pub fn remove_dir(&self) -> io::Result<()> {
2723+
self.0.remove_dir()
2724+
}
24432725
}
24442726

24452727
#[stable(feature = "dir_entry_debug", since = "1.13.0")]

0 commit comments

Comments
 (0)