async_std/path/path.rs
1use std::borrow::{Cow, ToOwned};
2use std::cmp::Ordering;
3use std::ffi::{OsStr, OsString};
4use std::rc::Rc;
5use std::sync::Arc;
6
7use crate::path::{Ancestors, Components, Display, Iter, PathBuf, StripPrefixError};
8#[cfg(not(target_os = "unknown"))]
9use crate::{fs, io};
10
11/// A slice of a path.
12///
13/// This struct is an async version of [`std::path::Path`].
14///
15/// This type supports a number of operations for inspecting a path, including
16/// breaking the path into its components (separated by `/` on Unix and by either
17/// `/` or `\` on Windows), extracting the file name, determining whether the path
18/// is absolute, and so on.
19///
20/// This is an *unsized* type, meaning that it must always be used behind a
21/// pointer like `&` or `Box`. For an owned version of this type,
22/// see [`PathBuf`].
23///
24/// [`PathBuf`]: struct.PathBuf.html
25/// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
26///
27/// More details about the overall approach can be found in
28/// the [module documentation](index.html).
29///
30/// # Examples
31///
32/// ```
33/// use std::path::Path;
34/// use std::ffi::OsStr;
35///
36/// // Note: this example does work on Windows
37/// let path = Path::new("./foo/bar.txt");
38///
39/// let parent = path.parent();
40/// assert_eq!(parent, Some(Path::new("./foo")));
41///
42/// let file_stem = path.file_stem();
43/// assert_eq!(file_stem, Some(OsStr::new("bar")));
44///
45/// let extension = path.extension();
46/// assert_eq!(extension, Some(OsStr::new("txt")));
47/// ```
48#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
49pub struct Path {
50 inner: std::path::Path,
51}
52
53impl Path {
54 /// Directly wraps a string slice as a `Path` slice.
55 ///
56 /// This is a cost-free conversion.
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use async_std::path::Path;
62 ///
63 /// Path::new("foo.txt");
64 /// ```
65 ///
66 /// You can create `Path`s from `String`s, or even other `Path`s:
67 ///
68 /// ```
69 /// use async_std::path::Path;
70 ///
71 /// let string = String::from("foo.txt");
72 /// let from_string = Path::new(&string);
73 /// let from_path = Path::new(&from_string);
74 /// assert_eq!(from_string, from_path);
75 /// ```
76 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
77 unsafe { &*(std::path::Path::new(s) as *const std::path::Path as *const Path) }
78 }
79
80 /// Returns the underlying [`OsStr`] slice.
81 ///
82 /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
83 ///
84 /// # Examples
85 ///
86 /// ```
87 /// use std::ffi::OsStr;
88 ///
89 /// use async_std::path::Path;
90 ///
91 /// let os_str = Path::new("foo.txt").as_os_str();
92 /// assert_eq!(os_str, OsStr::new("foo.txt"));
93 /// ```
94 pub fn as_os_str(&self) -> &OsStr {
95 self.inner.as_os_str()
96 }
97
98 /// Returns a [`&str`] slice if the `Path` is valid unicode.
99 ///
100 /// This conversion may entail doing a check for UTF-8 validity.
101 /// Note that validation is performed because non-UTF-8 strings are
102 /// perfectly valid for some OS.
103 ///
104 /// [`&str`]: https://doc.rust-lang.org/std/primitive.str.html
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use async_std::path::Path;
110 ///
111 /// let path = Path::new("foo.txt");
112 /// assert_eq!(path.to_str(), Some("foo.txt"));
113 /// ```
114 pub fn to_str(&self) -> Option<&str> {
115 self.inner.to_str()
116 }
117
118 /// Converts a `Path` to a [`Cow<str>`].
119 ///
120 /// Any non-Unicode sequences are replaced with
121 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
122 ///
123 /// [`Cow<str>`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
124 /// [U+FFFD]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
125 ///
126 /// # Examples
127 ///
128 /// Calling `to_string_lossy` on a `Path` with valid unicode:
129 ///
130 /// ```
131 /// use async_std::path::Path;
132 ///
133 /// let path = Path::new("foo.txt");
134 /// assert_eq!(path.to_string_lossy(), "foo.txt");
135 /// ```
136 ///
137 /// Had `path` contained invalid unicode, the `to_string_lossy` call might
138 /// have returned `"fo�.txt"`.
139 pub fn to_string_lossy(&self) -> Cow<'_, str> {
140 self.inner.to_string_lossy()
141 }
142
143 /// Converts a `Path` to an owned [`PathBuf`].
144 ///
145 /// [`PathBuf`]: struct.PathBuf.html
146 ///
147 /// # Examples
148 ///
149 /// ```
150 /// use async_std::path::{Path, PathBuf};
151 ///
152 /// let path_buf = Path::new("foo.txt").to_path_buf();
153 /// assert_eq!(path_buf, PathBuf::from("foo.txt"));
154 /// ```
155 pub fn to_path_buf(&self) -> PathBuf {
156 PathBuf::from(self.inner.to_path_buf())
157 }
158
159 /// Returns `true` if the `Path` is absolute, i.e. if it is independent of
160 /// the current directory.
161 ///
162 /// * On Unix, a path is absolute if it starts with the root, so
163 /// `is_absolute` and [`has_root`] are equivalent.
164 ///
165 /// * On Windows, a path is absolute if it has a prefix and starts with the
166 /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
167 ///
168 /// [`has_root`]: #method.has_root
169 ///
170 /// # Examples
171 ///
172 /// ```
173 /// use async_std::path::Path;
174 ///
175 /// assert!(!Path::new("foo.txt").is_absolute());
176 /// ```
177 pub fn is_absolute(&self) -> bool {
178 self.inner.is_absolute()
179 }
180
181 /// Returns `true` if the `Path` is relative, i.e. not absolute.
182 ///
183 /// See [`is_absolute`]'s documentation for more details.
184 ///
185 /// [`is_absolute`]: #method.is_absolute
186 ///
187 /// # Examples
188 ///
189 /// ```
190 /// use async_std::path::Path;
191 ///
192 /// assert!(Path::new("foo.txt").is_relative());
193 /// ```
194 pub fn is_relative(&self) -> bool {
195 self.inner.is_relative()
196 }
197
198 /// Returns `true` if the `Path` has a root.
199 ///
200 /// * On Unix, a path has a root if it begins with `/`.
201 ///
202 /// * On Windows, a path has a root if it:
203 /// * has no prefix and begins with a separator, e.g. `\windows`
204 /// * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
205 /// * has any non-disk prefix, e.g. `\\server\share`
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// use async_std::path::Path;
211 ///
212 /// assert!(Path::new("/etc/passwd").has_root());
213 /// ```
214 pub fn has_root(&self) -> bool {
215 self.inner.has_root()
216 }
217
218 /// Returns the `Path` without its final component, if there is one.
219 ///
220 /// Returns [`None`] if the path terminates in a root or prefix.
221 ///
222 /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
223 ///
224 /// # Examples
225 ///
226 /// ```
227 /// use async_std::path::Path;
228 ///
229 /// let path = Path::new("/foo/bar");
230 /// let parent = path.parent().unwrap();
231 /// assert_eq!(parent, Path::new("/foo"));
232 ///
233 /// let grand_parent = parent.parent().unwrap();
234 /// assert_eq!(grand_parent, Path::new("/"));
235 /// assert_eq!(grand_parent.parent(), None);
236 /// ```
237 pub fn parent(&self) -> Option<&Path> {
238 self.inner.parent().map(|p| p.into())
239 }
240
241 /// Produces an iterator over `Path` and its ancestors.
242 ///
243 /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
244 /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
245 /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
246 /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
247 /// namely `&self`.
248 ///
249 /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html
250 /// [`parent`]: struct.Path.html#method.parent
251 ///
252 /// # Examples
253 ///
254 /// ```
255 /// use async_std::path::Path;
256 ///
257 /// let mut ancestors = Path::new("/foo/bar").ancestors();
258 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar").into()));
259 /// assert_eq!(ancestors.next(), Some(Path::new("/foo").into()));
260 /// assert_eq!(ancestors.next(), Some(Path::new("/").into()));
261 /// assert_eq!(ancestors.next(), None);
262 /// ```
263 pub fn ancestors(&self) -> Ancestors<'_> {
264 Ancestors { next: Some(&self) }
265 }
266
267 /// Returns the final component of the `Path`, if there is one.
268 ///
269 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
270 /// is the directory name.
271 ///
272 /// Returns [`None`] if the path terminates in `..`.
273 ///
274 /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
275 ///
276 /// # Examples
277 ///
278 /// ```
279 /// use std::ffi::OsStr;
280 ///
281 /// use async_std::path::Path;
282 ///
283 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
284 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
285 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
286 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
287 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
288 /// assert_eq!(None, Path::new("/").file_name());
289 /// ```
290 pub fn file_name(&self) -> Option<&OsStr> {
291 self.inner.file_name()
292 }
293
294 /// Returns a path that becomes `self` when joined onto `base`.
295 ///
296 /// # Errors
297 ///
298 /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
299 /// returns `false`), returns [`Err`].
300 ///
301 /// [`starts_with`]: #method.starts_with
302 /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
303 ///
304 /// # Examples
305 ///
306 /// ```
307 /// use async_std::path::{Path, PathBuf};
308 ///
309 /// let path = Path::new("/test/haha/foo.txt");
310 ///
311 /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
312 /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
313 /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
314 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
315 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
316 /// assert_eq!(path.strip_prefix("test").is_ok(), false);
317 /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
318 ///
319 /// let prefix = PathBuf::from("/test/");
320 /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
321 /// ```
322 pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
323 where
324 P: AsRef<Path>,
325 {
326 Ok(self.inner.strip_prefix(base.as_ref())?.into())
327 }
328
329 /// Determines whether `base` is a prefix of `self`.
330 ///
331 /// Only considers whole path components to match.
332 ///
333 /// # Examples
334 ///
335 /// ```
336 /// use async_std::path::Path;
337 ///
338 /// let path = Path::new("/etc/passwd");
339 ///
340 /// assert!(path.starts_with("/etc"));
341 /// assert!(path.starts_with("/etc/"));
342 /// assert!(path.starts_with("/etc/passwd"));
343 /// assert!(path.starts_with("/etc/passwd/"));
344 ///
345 /// assert!(!path.starts_with("/e"));
346 /// ```
347 pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
348 self.inner.starts_with(base.as_ref())
349 }
350
351 /// Determines whether `child` is a suffix of `self`.
352 ///
353 /// Only considers whole path components to match.
354 ///
355 /// # Examples
356 ///
357 /// ```
358 /// use async_std::path::Path;
359 ///
360 /// let path = Path::new("/etc/passwd");
361 ///
362 /// assert!(path.ends_with("passwd"));
363 /// ```
364 pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
365 self.inner.ends_with(child.as_ref())
366 }
367
368 /// Extracts the stem (non-extension) portion of [`file_name`].
369 ///
370 /// [`file_name`]: struct.Path.html#method.file_name
371 ///
372 /// The stem is:
373 ///
374 /// * [`None`], if there is no file name
375 /// * The entire file name if there is no embedded `.`
376 /// * The entire file name if the file name begins with `.` and has no other `.`s within
377 /// * Otherwise, the portion of the file name before the final `.`
378 ///
379 /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
380 ///
381 /// # Examples
382 ///
383 /// ```
384 /// use async_std::path::Path;
385 ///
386 /// let path = Path::new("foo.rs");
387 ///
388 /// assert_eq!("foo", path.file_stem().unwrap());
389 /// ```
390 pub fn file_stem(&self) -> Option<&OsStr> {
391 self.inner.file_stem()
392 }
393
394 /// Extracts the extension of [`file_name`], if possible.
395 ///
396 /// The extension is:
397 ///
398 /// * [`None`], if there is no file name
399 /// * [`None`], if there is no embedded `.`
400 /// * [`None`], if the file name begins with `.` and has no other `.`s within
401 /// * Otherwise, the portion of the file name after the final `.`
402 ///
403 /// [`file_name`]: struct.Path.html#method.file_name
404 /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
405 ///
406 /// # Examples
407 ///
408 /// ```
409 /// use async_std::path::Path;
410 ///
411 /// let path = Path::new("foo.rs");
412 ///
413 /// assert_eq!("rs", path.extension().unwrap());
414 /// ```
415 pub fn extension(&self) -> Option<&OsStr> {
416 self.inner.extension()
417 }
418
419 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
420 ///
421 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
422 ///
423 /// [`PathBuf`]: struct.PathBuf.html
424 /// [`PathBuf::push`]: struct.PathBuf.html#method.push
425 ///
426 /// # Examples
427 ///
428 /// ```
429 /// use async_std::path::{Path, PathBuf};
430 ///
431 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
432 /// ```
433 pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
434 self.inner.join(path.as_ref()).into()
435 }
436
437 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
438 ///
439 /// See [`PathBuf::set_file_name`] for more details.
440 ///
441 /// [`PathBuf`]: struct.PathBuf.html
442 /// [`PathBuf::set_file_name`]: struct.PathBuf.html#method.set_file_name
443 ///
444 /// # Examples
445 ///
446 /// ```
447 /// use async_std::path::{Path, PathBuf};
448 ///
449 /// let path = Path::new("/tmp/foo.txt");
450 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
451 ///
452 /// let path = Path::new("/tmp");
453 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
454 /// ```
455 pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
456 self.inner.with_file_name(file_name).into()
457 }
458
459 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
460 ///
461 /// See [`PathBuf::set_extension`] for more details.
462 ///
463 /// [`PathBuf`]: struct.PathBuf.html
464 /// [`PathBuf::set_extension`]: struct.PathBuf.html#method.set_extension
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use async_std::path::{Path, PathBuf};
470 ///
471 /// let path = Path::new("foo.rs");
472 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
473 /// ```
474 pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
475 self.inner.with_extension(extension).into()
476 }
477
478 /// Produces an iterator over the [`Component`]s of the path.
479 ///
480 /// When parsing the path, there is a small amount of normalization:
481 ///
482 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
483 /// `a` and `b` as components.
484 ///
485 /// * Occurrences of `.` are normalized away, except if they are at the
486 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
487 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
488 /// an additional [`CurDir`] component.
489 ///
490 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
491 ///
492 /// Note that no other normalization takes place; in particular, `a/c`
493 /// and `a/b/../c` are distinct, to account for the possibility that `b`
494 /// is a symbolic link (so its parent isn't `a`).
495 ///
496 /// [`Component`]: enum.Component.html
497 /// [`CurDir`]: enum.Component.html#variant.CurDir
498 ///
499 /// # Examples
500 ///
501 /// ```
502 /// use std::ffi::OsStr;
503 ///
504 /// use async_std::path::{Path, Component};
505 ///
506 /// let mut components = Path::new("/tmp/foo.txt").components();
507 ///
508 /// assert_eq!(components.next(), Some(Component::RootDir));
509 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
510 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
511 /// assert_eq!(components.next(), None);
512 /// ```
513 pub fn components(&self) -> Components<'_> {
514 Components {
515 inner: self.inner.components(),
516 }
517 }
518
519 /// Produces an iterator over the path's components viewed as [`OsStr`]
520 /// slices.
521 ///
522 /// For more information about the particulars of how the path is separated
523 /// into components, see [`components`].
524 ///
525 /// [`components`]: #method.components
526 /// [`OsStr`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html
527 ///
528 /// # Examples
529 ///
530 /// ```
531 /// use std::ffi::OsStr;
532 ///
533 /// use async_std::path::{self, Path};
534 ///
535 /// let mut it = Path::new("/tmp/foo.txt").iter();
536 /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
537 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
538 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
539 /// assert_eq!(it.next(), None)
540 /// ```
541 pub fn iter(&self) -> Iter<'_> {
542 Iter {
543 inner: self.components(),
544 }
545 }
546
547 /// Returns an object that implements [`Display`] for safely printing paths
548 /// that may contain non-Unicode data.
549 ///
550 /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
551 ///
552 /// # Examples
553 ///
554 /// ```
555 /// use async_std::path::Path;
556 ///
557 /// let path = Path::new("/tmp/foo.rs");
558 ///
559 /// println!("{}", path.display());
560 /// ```
561 pub fn display(&self) -> Display<'_> {
562 self.inner.display()
563 }
564
565 /// Reads the metadata of a file or directory.
566 ///
567 /// This function will traverse symbolic links to query information about the
568 /// destination file.
569 ///
570 /// This is an alias to [`fs::metadata`].
571 ///
572 /// [`fs::metadata`]: ../fs/fn.metadata.html
573 ///
574 /// # Examples
575 ///
576 /// ```no_run
577 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
578 /// #
579 /// use async_std::path::Path;
580 ///
581 /// let path = Path::new("/Minas/tirith");
582 /// let metadata = path.metadata().await?;
583 /// println!("{:?}", metadata.file_type());
584 /// #
585 /// # Ok(()) }) }
586 /// ```
587 #[cfg(not(target_os = "unknown"))]
588 pub async fn metadata(&self) -> io::Result<fs::Metadata> {
589 fs::metadata(self).await
590 }
591
592 /// Reads the metadata of a file or directory without following symbolic links.
593 ///
594 /// This is an alias to [`fs::symlink_metadata`].
595 ///
596 /// [`fs::symlink_metadata`]: ../fs/fn.symlink_metadata.html
597 ///
598 /// # Examples
599 ///
600 /// ```no_run
601 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
602 /// #
603 /// use async_std::path::Path;
604 ///
605 /// let path = Path::new("/Minas/tirith");
606 /// let metadata = path.symlink_metadata().await?;
607 /// println!("{:?}", metadata.file_type());
608 /// #
609 /// # Ok(()) }) }
610 /// ```
611 #[cfg(not(target_os = "unknown"))]
612 pub async fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
613 fs::symlink_metadata(self).await
614 }
615
616 /// Returns the canonical form of a path.
617 ///
618 /// The returned path is in absolute form with all intermediate components normalized and
619 /// symbolic links resolved.
620 ///
621 /// This is an alias to [`fs::canonicalize`].
622 ///
623 /// [`fs::canonicalize`]: ../fs/fn.canonicalize.html
624 ///
625 /// # Examples
626 ///
627 /// ```no_run
628 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
629 /// #
630 /// use async_std::path::{Path, PathBuf};
631 ///
632 /// let path = Path::new("/foo/test/../test/bar.rs");
633 /// assert_eq!(path.canonicalize().await?, PathBuf::from("/foo/test/bar.rs"));
634 /// #
635 /// # Ok(()) }) }
636 /// ```
637 #[cfg(not(target_os = "unknown"))]
638 pub async fn canonicalize(&self) -> io::Result<PathBuf> {
639 fs::canonicalize(self).await
640 }
641
642 /// Reads a symbolic link, returning the file that the link points to.
643 ///
644 /// This is an alias to [`fs::read_link`].
645 ///
646 /// [`fs::read_link`]: ../fs/fn.read_link.html
647 ///
648 /// # Examples
649 ///
650 /// ```no_run
651 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
652 /// #
653 /// use async_std::path::Path;
654 ///
655 /// let path = Path::new("/laputa/sky_castle.rs");
656 /// let path_link = path.read_link().await?;
657 /// #
658 /// # Ok(()) }) }
659 /// ```
660 #[cfg(not(target_os = "unknown"))]
661 pub async fn read_link(&self) -> io::Result<PathBuf> {
662 fs::read_link(self).await
663 }
664
665 /// Returns a stream over the entries within a directory.
666 ///
667 /// The stream will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. New
668 /// errors may be encountered after an iterator is initially constructed.
669 ///
670 /// This is an alias to [`fs::read_dir`].
671 ///
672 /// [`io::Result`]: ../io/type.Result.html
673 /// [`DirEntry`]: ../fs/struct.DirEntry.html
674 /// [`fs::read_dir`]: ../fs/fn.read_dir.html
675 ///
676 /// # Examples
677 ///
678 /// ```no_run
679 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
680 /// #
681 /// use async_std::fs;
682 /// use async_std::path::Path;
683 /// use async_std::prelude::*;
684 ///
685 /// let path = Path::new("/laputa");
686 /// let mut dir = fs::read_dir(&path).await?;
687 ///
688 /// while let Some(res) = dir.next().await {
689 /// let entry = res?;
690 /// println!("{}", entry.file_name().to_string_lossy());
691 /// }
692 /// #
693 /// # Ok(()) }) }
694 /// ```
695 #[cfg(not(target_os = "unknown"))]
696 pub async fn read_dir(&self) -> io::Result<fs::ReadDir> {
697 fs::read_dir(self).await
698 }
699
700 /// Returns `true` if the path points at an existing entity.
701 ///
702 /// This function will traverse symbolic links to query information about the
703 /// destination file. In case of broken symbolic links this will return `false`.
704 ///
705 /// If you cannot access the directory containing the file, e.g., because of a
706 /// permission error, this will return `false`.
707 ///
708 /// # Examples
709 ///
710 /// ```no_run
711 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
712 /// #
713 /// use async_std::path::Path;
714 /// assert_eq!(Path::new("does_not_exist.txt").exists().await, false);
715 /// #
716 /// # Ok(()) }) }
717 /// ```
718 ///
719 /// # See Also
720 ///
721 /// This is a convenience function that coerces errors to false. If you want to
722 /// check errors, call [fs::metadata].
723 ///
724 /// [fs::metadata]: ../fs/fn.metadata.html
725 #[cfg(not(target_os = "unknown"))]
726 pub async fn exists(&self) -> bool {
727 fs::metadata(self).await.is_ok()
728 }
729
730 /// Returns `true` if the path exists on disk and is pointing at a regular file.
731 ///
732 /// This function will traverse symbolic links to query information about the
733 /// destination file. In case of broken symbolic links this will return `false`.
734 ///
735 /// If you cannot access the directory containing the file, e.g., because of a
736 /// permission error, this will return `false`.
737 ///
738 /// # Examples
739 ///
740 /// ```no_run
741 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
742 /// #
743 /// use async_std::path::Path;
744 /// assert_eq!(Path::new("./is_a_directory/").is_file().await, false);
745 /// assert_eq!(Path::new("a_file.txt").is_file().await, true);
746 /// #
747 /// # Ok(()) }) }
748 /// ```
749 ///
750 /// # See Also
751 ///
752 /// This is a convenience function that coerces errors to false. If you want to
753 /// check errors, call [fs::metadata] and handle its Result. Then call
754 /// [fs::Metadata::is_file] if it was Ok.
755 ///
756 /// [fs::metadata]: ../fs/fn.metadata.html
757 /// [fs::Metadata::is_file]: ../fs/struct.Metadata.html#method.is_file
758 #[cfg(not(target_os = "unknown"))]
759 pub async fn is_file(&self) -> bool {
760 fs::metadata(self)
761 .await
762 .map(|m| m.is_file())
763 .unwrap_or(false)
764 }
765
766 /// Returns `true` if the path exists on disk and is pointing at a directory.
767 ///
768 /// This function will traverse symbolic links to query information about the
769 /// destination file. In case of broken symbolic links this will return `false`.
770 ///
771 /// If you cannot access the directory containing the file, e.g., because of a
772 /// permission error, this will return `false`.
773 ///
774 /// # Examples
775 ///
776 /// ```no_run
777 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
778 /// #
779 /// use async_std::path::Path;
780 ///
781 /// assert_eq!(Path::new("./is_a_directory/").is_dir().await, true);
782 /// assert_eq!(Path::new("a_file.txt").is_dir().await, false);
783 /// #
784 /// # Ok(()) }) }
785 /// ```
786 ///
787 /// # See Also
788 ///
789 /// This is a convenience function that coerces errors to false. If you want to
790 /// check errors, call [fs::metadata] and handle its Result. Then call
791 /// [fs::Metadata::is_dir] if it was Ok.
792 ///
793 /// [fs::metadata]: ../fs/fn.metadata.html
794 /// [fs::Metadata::is_dir]: ../fs/struct.Metadata.html#method.is_dir
795 #[cfg(not(target_os = "unknown"))]
796 pub async fn is_dir(&self) -> bool {
797 fs::metadata(self)
798 .await
799 .map(|m| m.is_dir())
800 .unwrap_or(false)
801 }
802
803 /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
804 /// allocating.
805 ///
806 /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
807 /// [`PathBuf`]: struct.PathBuf.html
808 ///
809 /// # Examples
810 ///
811 /// ```
812 /// use async_std::path::Path;
813 ///
814 /// let path: Box<Path> = Path::new("foo.txt").into();
815 /// let path_buf = path.into_path_buf();
816 /// ```
817 pub fn into_path_buf(self: Box<Path>) -> PathBuf {
818 let rw = Box::into_raw(self) as *mut std::path::Path;
819 let inner = unsafe { Box::from_raw(rw) };
820 inner.into_path_buf().into()
821 }
822}
823
824impl From<&Path> for Box<Path> {
825 fn from(path: &Path) -> Box<Path> {
826 let boxed: Box<std::path::Path> = path.inner.into();
827 let rw = Box::into_raw(boxed) as *mut Path;
828 unsafe { Box::from_raw(rw) }
829 }
830}
831
832impl From<&Path> for Arc<Path> {
833 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
834 #[inline]
835 fn from(s: &Path) -> Arc<Path> {
836 let arc: Arc<OsStr> = Arc::from(s.as_os_str());
837 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
838 }
839}
840
841impl From<&Path> for Rc<Path> {
842 #[inline]
843 fn from(s: &Path) -> Rc<Path> {
844 let rc: Rc<OsStr> = Rc::from(s.as_os_str());
845 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
846 }
847}
848
849impl ToOwned for Path {
850 type Owned = PathBuf;
851
852 fn to_owned(&self) -> PathBuf {
853 self.to_path_buf()
854 }
855}
856
857impl AsRef<OsStr> for Path {
858 fn as_ref(&self) -> &OsStr {
859 self.inner.as_ref()
860 }
861}
862
863impl AsRef<Path> for Path {
864 fn as_ref(&self) -> &Path {
865 self
866 }
867}
868
869impl AsRef<Path> for OsStr {
870 fn as_ref(&self) -> &Path {
871 Path::new(self)
872 }
873}
874
875impl<'a> From<&'a Path> for Cow<'a, Path> {
876 #[inline]
877 fn from(s: &'a Path) -> Cow<'a, Path> {
878 Cow::Borrowed(s)
879 }
880}
881
882impl AsRef<Path> for Cow<'_, OsStr> {
883 fn as_ref(&self) -> &Path {
884 Path::new(self)
885 }
886}
887
888impl AsRef<Path> for OsString {
889 fn as_ref(&self) -> &Path {
890 Path::new(self)
891 }
892}
893
894impl AsRef<Path> for str {
895 fn as_ref(&self) -> &Path {
896 Path::new(self)
897 }
898}
899
900impl AsRef<Path> for String {
901 fn as_ref(&self) -> &Path {
902 Path::new(self)
903 }
904}
905
906impl AsRef<Path> for PathBuf {
907 fn as_ref(&self) -> &Path {
908 self
909 }
910}
911
912impl<'a> IntoIterator for &'a PathBuf {
913 type Item = &'a OsStr;
914 type IntoIter = Iter<'a>;
915
916 fn into_iter(self) -> Iter<'a> {
917 self.iter()
918 }
919}
920
921impl<'a> IntoIterator for &'a Path {
922 type Item = &'a OsStr;
923 type IntoIter = Iter<'a>;
924
925 fn into_iter(self) -> Iter<'a> {
926 self.iter()
927 }
928}
929
930macro_rules! impl_cmp {
931 ($lhs:ty, $rhs: ty) => {
932 impl<'a, 'b> PartialEq<$rhs> for $lhs {
933 #[inline]
934 fn eq(&self, other: &$rhs) -> bool {
935 <Path as PartialEq>::eq(self, other)
936 }
937 }
938
939 impl<'a, 'b> PartialEq<$lhs> for $rhs {
940 #[inline]
941 fn eq(&self, other: &$lhs) -> bool {
942 <Path as PartialEq>::eq(self, other)
943 }
944 }
945
946 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
947 #[inline]
948 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
949 <Path as PartialOrd>::partial_cmp(self, other)
950 }
951 }
952
953 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
954 #[inline]
955 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
956 <Path as PartialOrd>::partial_cmp(self, other)
957 }
958 }
959 };
960}
961
962impl_cmp!(PathBuf, Path);
963impl_cmp!(PathBuf, &'a Path);
964impl_cmp!(Cow<'a, Path>, Path);
965impl_cmp!(Cow<'a, Path>, &'b Path);
966impl_cmp!(Cow<'a, Path>, PathBuf);
967
968macro_rules! impl_cmp_os_str {
969 ($lhs:ty, $rhs: ty) => {
970 impl<'a, 'b> PartialEq<$rhs> for $lhs {
971 #[inline]
972 fn eq(&self, other: &$rhs) -> bool {
973 <Path as PartialEq>::eq(self, other.as_ref())
974 }
975 }
976
977 impl<'a, 'b> PartialEq<$lhs> for $rhs {
978 #[inline]
979 fn eq(&self, other: &$lhs) -> bool {
980 <Path as PartialEq>::eq(self.as_ref(), other)
981 }
982 }
983
984 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
985 #[inline]
986 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
987 <Path as PartialOrd>::partial_cmp(self, other.as_ref())
988 }
989 }
990
991 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
992 #[inline]
993 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
994 <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
995 }
996 }
997 };
998}
999
1000impl_cmp_os_str!(PathBuf, OsStr);
1001impl_cmp_os_str!(PathBuf, &'a OsStr);
1002impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
1003impl_cmp_os_str!(PathBuf, OsString);
1004impl_cmp_os_str!(Path, OsStr);
1005impl_cmp_os_str!(Path, &'a OsStr);
1006impl_cmp_os_str!(Path, Cow<'a, OsStr>);
1007impl_cmp_os_str!(Path, OsString);
1008impl_cmp_os_str!(&'a Path, OsStr);
1009impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
1010impl_cmp_os_str!(&'a Path, OsString);
1011
1012impl<'a> From<&'a std::path::Path> for &'a Path {
1013 fn from(path: &'a std::path::Path) -> &'a Path {
1014 &Path::new(path.as_os_str())
1015 }
1016}
1017
1018impl<'a> Into<&'a std::path::Path> for &'a Path {
1019 fn into(self) -> &'a std::path::Path {
1020 std::path::Path::new(&self.inner)
1021 }
1022}
1023
1024impl AsRef<std::path::Path> for Path {
1025 fn as_ref(&self) -> &std::path::Path {
1026 self.into()
1027 }
1028}
1029
1030impl AsRef<Path> for std::path::Path {
1031 fn as_ref(&self) -> &Path {
1032 self.into()
1033 }
1034}
1035
1036impl AsRef<Path> for std::path::PathBuf {
1037 fn as_ref(&self) -> &Path {
1038 let p: &std::path::Path = self.as_ref();
1039 p.into()
1040 }
1041}