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::fs;
8use crate::io;
9use crate::path::{Ancestors, Components, Display, Iter, PathBuf, StripPrefixError};
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 pub async fn metadata(&self) -> io::Result<fs::Metadata> {
588 fs::metadata(self).await
589 }
590
591 /// Reads the metadata of a file or directory without following symbolic links.
592 ///
593 /// This is an alias to [`fs::symlink_metadata`].
594 ///
595 /// [`fs::symlink_metadata`]: ../fs/fn.symlink_metadata.html
596 ///
597 /// # Examples
598 ///
599 /// ```no_run
600 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
601 /// #
602 /// use async_std::path::Path;
603 ///
604 /// let path = Path::new("/Minas/tirith");
605 /// let metadata = path.symlink_metadata().await?;
606 /// println!("{:?}", metadata.file_type());
607 /// #
608 /// # Ok(()) }) }
609 /// ```
610 pub async fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
611 fs::symlink_metadata(self).await
612 }
613
614 /// Returns the canonical form of a path.
615 ///
616 /// The returned path is in absolute form with all intermediate components normalized and
617 /// symbolic links resolved.
618 ///
619 /// This is an alias to [`fs::canonicalize`].
620 ///
621 /// [`fs::canonicalize`]: ../fs/fn.canonicalize.html
622 ///
623 /// # Examples
624 ///
625 /// ```no_run
626 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
627 /// #
628 /// use async_std::path::{Path, PathBuf};
629 ///
630 /// let path = Path::new("/foo/test/../test/bar.rs");
631 /// assert_eq!(path.canonicalize().await?, PathBuf::from("/foo/test/bar.rs"));
632 /// #
633 /// # Ok(()) }) }
634 /// ```
635 pub async fn canonicalize(&self) -> io::Result<PathBuf> {
636 fs::canonicalize(self).await
637 }
638
639 /// Reads a symbolic link, returning the file that the link points to.
640 ///
641 /// This is an alias to [`fs::read_link`].
642 ///
643 /// [`fs::read_link`]: ../fs/fn.read_link.html
644 ///
645 /// # Examples
646 ///
647 /// ```no_run
648 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
649 /// #
650 /// use async_std::path::Path;
651 ///
652 /// let path = Path::new("/laputa/sky_castle.rs");
653 /// let path_link = path.read_link().await?;
654 /// #
655 /// # Ok(()) }) }
656 /// ```
657 pub async fn read_link(&self) -> io::Result<PathBuf> {
658 fs::read_link(self).await
659 }
660
661 /// Returns a stream over the entries within a directory.
662 ///
663 /// The stream will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. New
664 /// errors may be encountered after an iterator is initially constructed.
665 ///
666 /// This is an alias to [`fs::read_dir`].
667 ///
668 /// [`io::Result`]: ../io/type.Result.html
669 /// [`DirEntry`]: ../fs/struct.DirEntry.html
670 /// [`fs::read_dir`]: ../fs/fn.read_dir.html
671 ///
672 /// # Examples
673 ///
674 /// ```no_run
675 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
676 /// #
677 /// use async_std::fs;
678 /// use async_std::path::Path;
679 /// use async_std::prelude::*;
680 ///
681 /// let path = Path::new("/laputa");
682 /// let mut dir = fs::read_dir(&path).await?;
683 ///
684 /// while let Some(res) = dir.next().await {
685 /// let entry = res?;
686 /// println!("{}", entry.file_name().to_string_lossy());
687 /// }
688 /// #
689 /// # Ok(()) }) }
690 /// ```
691 pub async fn read_dir(&self) -> io::Result<fs::ReadDir> {
692 fs::read_dir(self).await
693 }
694
695 /// Returns `true` if the path points at an existing entity.
696 ///
697 /// This function will traverse symbolic links to query information about the
698 /// destination file. In case of broken symbolic links this will return `false`.
699 ///
700 /// If you cannot access the directory containing the file, e.g., because of a
701 /// permission error, this will return `false`.
702 ///
703 /// # Examples
704 ///
705 /// ```no_run
706 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
707 /// #
708 /// use async_std::path::Path;
709 /// assert_eq!(Path::new("does_not_exist.txt").exists().await, false);
710 /// #
711 /// # Ok(()) }) }
712 /// ```
713 ///
714 /// # See Also
715 ///
716 /// This is a convenience function that coerces errors to false. If you want to
717 /// check errors, call [fs::metadata].
718 ///
719 /// [fs::metadata]: ../fs/fn.metadata.html
720 pub async fn exists(&self) -> bool {
721 fs::metadata(self).await.is_ok()
722 }
723
724 /// Returns `true` if the path exists on disk and is pointing at a regular file.
725 ///
726 /// This function will traverse symbolic links to query information about the
727 /// destination file. In case of broken symbolic links this will return `false`.
728 ///
729 /// If you cannot access the directory containing the file, e.g., because of a
730 /// permission error, this will return `false`.
731 ///
732 /// # Examples
733 ///
734 /// ```no_run
735 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
736 /// #
737 /// use async_std::path::Path;
738 /// assert_eq!(Path::new("./is_a_directory/").is_file().await, false);
739 /// assert_eq!(Path::new("a_file.txt").is_file().await, true);
740 /// #
741 /// # Ok(()) }) }
742 /// ```
743 ///
744 /// # See Also
745 ///
746 /// This is a convenience function that coerces errors to false. If you want to
747 /// check errors, call [fs::metadata] and handle its Result. Then call
748 /// [fs::Metadata::is_file] if it was Ok.
749 ///
750 /// [fs::metadata]: ../fs/fn.metadata.html
751 /// [fs::Metadata::is_file]: ../fs/struct.Metadata.html#method.is_file
752 pub async fn is_file(&self) -> bool {
753 fs::metadata(self)
754 .await
755 .map(|m| m.is_file())
756 .unwrap_or(false)
757 }
758
759 /// Returns `true` if the path exists on disk and is pointing at a directory.
760 ///
761 /// This function will traverse symbolic links to query information about the
762 /// destination file. In case of broken symbolic links this will return `false`.
763 ///
764 /// If you cannot access the directory containing the file, e.g., because of a
765 /// permission error, this will return `false`.
766 ///
767 /// # Examples
768 ///
769 /// ```no_run
770 /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
771 /// #
772 /// use async_std::path::Path;
773 ///
774 /// assert_eq!(Path::new("./is_a_directory/").is_dir().await, true);
775 /// assert_eq!(Path::new("a_file.txt").is_dir().await, false);
776 /// #
777 /// # Ok(()) }) }
778 /// ```
779 ///
780 /// # See Also
781 ///
782 /// This is a convenience function that coerces errors to false. If you want to
783 /// check errors, call [fs::metadata] and handle its Result. Then call
784 /// [fs::Metadata::is_dir] if it was Ok.
785 ///
786 /// [fs::metadata]: ../fs/fn.metadata.html
787 /// [fs::Metadata::is_dir]: ../fs/struct.Metadata.html#method.is_dir
788 pub async fn is_dir(&self) -> bool {
789 fs::metadata(self)
790 .await
791 .map(|m| m.is_dir())
792 .unwrap_or(false)
793 }
794
795 /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
796 /// allocating.
797 ///
798 /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
799 /// [`PathBuf`]: struct.PathBuf.html
800 ///
801 /// # Examples
802 ///
803 /// ```
804 /// use async_std::path::Path;
805 ///
806 /// let path: Box<Path> = Path::new("foo.txt").into();
807 /// let path_buf = path.into_path_buf();
808 /// ```
809 pub fn into_path_buf(self: Box<Path>) -> PathBuf {
810 let rw = Box::into_raw(self) as *mut std::path::Path;
811 let inner = unsafe { Box::from_raw(rw) };
812 inner.into_path_buf().into()
813 }
814}
815
816impl From<&Path> for Box<Path> {
817 fn from(path: &Path) -> Box<Path> {
818 let boxed: Box<std::path::Path> = path.inner.into();
819 let rw = Box::into_raw(boxed) as *mut Path;
820 unsafe { Box::from_raw(rw) }
821 }
822}
823
824impl From<&Path> for Arc<Path> {
825 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
826 #[inline]
827 fn from(s: &Path) -> Arc<Path> {
828 let arc: Arc<OsStr> = Arc::from(s.as_os_str());
829 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
830 }
831}
832
833impl From<&Path> for Rc<Path> {
834 #[inline]
835 fn from(s: &Path) -> Rc<Path> {
836 let rc: Rc<OsStr> = Rc::from(s.as_os_str());
837 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
838 }
839}
840
841impl ToOwned for Path {
842 type Owned = PathBuf;
843
844 fn to_owned(&self) -> PathBuf {
845 self.to_path_buf()
846 }
847}
848
849impl AsRef<OsStr> for Path {
850 fn as_ref(&self) -> &OsStr {
851 self.inner.as_ref()
852 }
853}
854
855impl AsRef<Path> for Path {
856 fn as_ref(&self) -> &Path {
857 self
858 }
859}
860
861impl AsRef<Path> for OsStr {
862 fn as_ref(&self) -> &Path {
863 Path::new(self)
864 }
865}
866
867impl<'a> From<&'a Path> for Cow<'a, Path> {
868 #[inline]
869 fn from(s: &'a Path) -> Cow<'a, Path> {
870 Cow::Borrowed(s)
871 }
872}
873
874impl AsRef<Path> for Cow<'_, OsStr> {
875 fn as_ref(&self) -> &Path {
876 Path::new(self)
877 }
878}
879
880impl AsRef<Path> for OsString {
881 fn as_ref(&self) -> &Path {
882 Path::new(self)
883 }
884}
885
886impl AsRef<Path> for str {
887 fn as_ref(&self) -> &Path {
888 Path::new(self)
889 }
890}
891
892impl AsRef<Path> for String {
893 fn as_ref(&self) -> &Path {
894 Path::new(self)
895 }
896}
897
898impl AsRef<Path> for PathBuf {
899 fn as_ref(&self) -> &Path {
900 self
901 }
902}
903
904impl<'a> IntoIterator for &'a PathBuf {
905 type Item = &'a OsStr;
906 type IntoIter = Iter<'a>;
907
908 fn into_iter(self) -> Iter<'a> {
909 self.iter()
910 }
911}
912
913impl<'a> IntoIterator for &'a Path {
914 type Item = &'a OsStr;
915 type IntoIter = Iter<'a>;
916
917 fn into_iter(self) -> Iter<'a> {
918 self.iter()
919 }
920}
921
922macro_rules! impl_cmp {
923 ($lhs:ty, $rhs: ty) => {
924 impl<'a, 'b> PartialEq<$rhs> for $lhs {
925 #[inline]
926 fn eq(&self, other: &$rhs) -> bool {
927 <Path as PartialEq>::eq(self, other)
928 }
929 }
930
931 impl<'a, 'b> PartialEq<$lhs> for $rhs {
932 #[inline]
933 fn eq(&self, other: &$lhs) -> bool {
934 <Path as PartialEq>::eq(self, other)
935 }
936 }
937
938 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
939 #[inline]
940 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
941 <Path as PartialOrd>::partial_cmp(self, other)
942 }
943 }
944
945 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
946 #[inline]
947 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
948 <Path as PartialOrd>::partial_cmp(self, other)
949 }
950 }
951 };
952}
953
954impl_cmp!(PathBuf, Path);
955impl_cmp!(PathBuf, &'a Path);
956impl_cmp!(Cow<'a, Path>, Path);
957impl_cmp!(Cow<'a, Path>, &'b Path);
958impl_cmp!(Cow<'a, Path>, PathBuf);
959
960macro_rules! impl_cmp_os_str {
961 ($lhs:ty, $rhs: ty) => {
962 impl<'a, 'b> PartialEq<$rhs> for $lhs {
963 #[inline]
964 fn eq(&self, other: &$rhs) -> bool {
965 <Path as PartialEq>::eq(self, other.as_ref())
966 }
967 }
968
969 impl<'a, 'b> PartialEq<$lhs> for $rhs {
970 #[inline]
971 fn eq(&self, other: &$lhs) -> bool {
972 <Path as PartialEq>::eq(self.as_ref(), other)
973 }
974 }
975
976 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
977 #[inline]
978 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
979 <Path as PartialOrd>::partial_cmp(self, other.as_ref())
980 }
981 }
982
983 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
984 #[inline]
985 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
986 <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
987 }
988 }
989 };
990}
991
992impl_cmp_os_str!(PathBuf, OsStr);
993impl_cmp_os_str!(PathBuf, &'a OsStr);
994impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
995impl_cmp_os_str!(PathBuf, OsString);
996impl_cmp_os_str!(Path, OsStr);
997impl_cmp_os_str!(Path, &'a OsStr);
998impl_cmp_os_str!(Path, Cow<'a, OsStr>);
999impl_cmp_os_str!(Path, OsString);
1000impl_cmp_os_str!(&'a Path, OsStr);
1001impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
1002impl_cmp_os_str!(&'a Path, OsString);
1003
1004impl<'a> From<&'a std::path::Path> for &'a Path {
1005 fn from(path: &'a std::path::Path) -> &'a Path {
1006 &Path::new(path.as_os_str())
1007 }
1008}
1009
1010impl<'a> Into<&'a std::path::Path> for &'a Path {
1011 fn into(self) -> &'a std::path::Path {
1012 std::path::Path::new(&self.inner)
1013 }
1014}
1015
1016impl AsRef<std::path::Path> for Path {
1017 fn as_ref(&self) -> &std::path::Path {
1018 self.into()
1019 }
1020}
1021
1022impl AsRef<Path> for std::path::Path {
1023 fn as_ref(&self) -> &Path {
1024 self.into()
1025 }
1026}
1027
1028impl AsRef<Path> for std::path::PathBuf {
1029 fn as_ref(&self) -> &Path {
1030 let p: &std::path::Path = self.as_ref();
1031 p.into()
1032 }
1033}