nu_path/path.rs
1use crate::form::{
2 Absolute, Any, Canonical, IsAbsolute, MaybeRelative, PathCast, PathForm, PathJoin, PathPush,
3 PathSet, Relative,
4};
5use ref_cast::{RefCastCustom, ref_cast_custom};
6use std::{
7 borrow::{Borrow, Cow},
8 cmp::Ordering,
9 collections::TryReserveError,
10 convert::Infallible,
11 ffi::{OsStr, OsString},
12 fmt, fs,
13 hash::{Hash, Hasher},
14 io,
15 iter::FusedIterator,
16 marker::PhantomData,
17 ops::{Deref, DerefMut},
18 path::StripPrefixError,
19 rc::Rc,
20 str::FromStr,
21 sync::Arc,
22};
23
24/// A wrapper around [`std::path::Path`] with extra invariants determined by its `Form`.
25///
26/// The possible path forms are [`Any`], [`Relative`], [`Absolute`], or [`Canonical`].
27/// To learn more, view the documentation on [`PathForm`] or any of the individual forms.
28///
29/// There are also several type aliases available, corresponding to each [`PathForm`]:
30/// - [`RelativePath`] (same as [`Path<Relative>`])
31/// - [`AbsolutePath`] (same as [`Path<Absolute>`])
32/// - [`CanonicalPath`] (same as [`Path<Canonical>`])
33///
34/// If the `Form` is not specified, then it defaults to [`Any`], so [`Path`] and [`Path<Any>`]
35/// are one in the same.
36///
37/// # Converting to [`std::path`] types
38///
39/// [`Path`]s with form [`Any`] cannot be easily referenced as a [`std::path::Path`] by design.
40/// Other Nushell crates need to account for the emulated current working directory
41/// before passing a path to functions in [`std`] or other third party crates.
42/// You can [`join`](Path::join) a [`Path`] onto an [`AbsolutePath`] or a [`CanonicalPath`].
43/// This will return an [`AbsolutePathBuf`] which can be easily referenced as a [`std::path::Path`].
44/// If you really mean it, you can instead use [`as_relative_std_path`](Path::as_relative_std_path)
45/// to get the underlying [`std::path::Path`] from a [`Path`].
46/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
47/// the path which is almost always incorrect behavior. Extra care is needed to ensure that this
48/// is not the case after using [`as_relative_std_path`](Path::as_relative_std_path).
49#[derive(RefCastCustom)]
50#[repr(transparent)]
51pub struct Path<Form = Any> {
52 _form: PhantomData<Form>,
53 inner: std::path::Path,
54}
55
56/// A path that is strictly relative.
57///
58/// I.e., this path is guaranteed to never be absolute.
59///
60/// [`RelativePath`]s cannot be easily converted into a [`std::path::Path`] by design.
61/// Other Nushell crates need to account for the emulated current working directory
62/// before passing a path to functions in [`std`] or other third party crates.
63/// You can [`join`](Path::join) a [`RelativePath`] onto an [`AbsolutePath`] or a [`CanonicalPath`].
64/// This will return an [`AbsolutePathBuf`] which can be referenced as a [`std::path::Path`].
65/// If you really mean it, you can use [`as_relative_std_path`](RelativePath::as_relative_std_path)
66/// to get the underlying [`std::path::Path`] from a [`RelativePath`].
67/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
68/// the path which is almost always incorrect behavior. Extra care is needed to ensure that this
69/// is not the case after using [`as_relative_std_path`](RelativePath::as_relative_std_path).
70///
71/// # Examples
72///
73/// [`RelativePath`]s can be created by using [`try_relative`](Path::try_relative)
74/// on a [`Path`], by using [`try_new`](Path::try_new), or by using
75/// [`strip_prefix`](Path::strip_prefix) on a [`Path`] of any form.
76///
77/// ```
78/// use nu_path::{Path, RelativePath};
79///
80/// let path1 = Path::new("foo.txt");
81/// let path1 = path1.try_relative().unwrap();
82///
83/// let path2 = RelativePath::try_new("foo.txt").unwrap();
84///
85/// let path3 = Path::new("/prefix/foo.txt").strip_prefix("/prefix").unwrap();
86///
87/// assert_eq!(path1, path2);
88/// assert_eq!(path2, path3);
89/// ```
90///
91/// You can also use `RelativePath::try_from` or `try_into`.
92/// This supports attempted conversions from [`Path`] as well as types in [`std::path`].
93///
94/// ```
95/// use nu_path::{Path, RelativePath};
96///
97/// let path1 = Path::new("foo.txt");
98/// let path1: &RelativePath = path1.try_into().unwrap();
99///
100/// let path2 = std::path::Path::new("foo.txt");
101/// let path2: &RelativePath = path2.try_into().unwrap();
102///
103/// assert_eq!(path1, path2)
104/// ```
105pub type RelativePath = Path<Relative>;
106
107/// A path that is strictly absolute.
108///
109/// I.e., this path is guaranteed to never be relative.
110///
111/// # Examples
112///
113/// [`AbsolutePath`]s can be created by using [`try_absolute`](Path::try_absolute) on a [`Path`]
114/// or by using [`try_new`](AbsolutePath::try_new).
115///
116#[cfg_attr(not(windows), doc = "```")]
117#[cfg_attr(windows, doc = "```no_run")]
118/// use nu_path::{AbsolutePath, Path};
119///
120/// let path1 = Path::new("/foo").try_absolute().unwrap();
121/// let path2 = AbsolutePath::try_new("/foo").unwrap();
122///
123/// assert_eq!(path1, path2);
124/// ```
125///
126/// You can also use `AbsolutePath::try_from` or `try_into`.
127/// This supports attempted conversions from [`Path`] as well as types in [`std::path`].
128///
129#[cfg_attr(not(windows), doc = "```")]
130#[cfg_attr(windows, doc = "```no_run")]
131/// use nu_path::{AbsolutePath, Path};
132///
133/// let path1 = Path::new("/foo");
134/// let path1: &AbsolutePath = path1.try_into().unwrap();
135///
136/// let path2 = std::path::Path::new("/foo");
137/// let path2: &AbsolutePath = path2.try_into().unwrap();
138///
139/// assert_eq!(path1, path2)
140/// ```
141pub type AbsolutePath = Path<Absolute>;
142
143/// An absolute, canonical path.
144///
145/// # Examples
146///
147/// [`CanonicalPath`]s can only be created by using [`canonicalize`](Path::canonicalize) on
148/// an [`AbsolutePath`]. References to [`CanonicalPath`]s can be converted to
149/// [`AbsolutePath`] references using `as_ref`, [`cast`](Path::cast),
150/// or [`as_absolute`](CanonicalPath::as_absolute).
151///
152/// ```no_run
153/// use nu_path::AbsolutePath;
154///
155/// let path = AbsolutePath::try_new("/foo").unwrap();
156///
157/// let canonical = path.canonicalize().expect("canonicalization failed");
158///
159/// assert_eq!(path, canonical.as_absolute());
160/// ```
161pub type CanonicalPath = Path<Canonical>;
162
163impl<Form: PathForm> Path<Form> {
164 /// Create a new path of any form without validating invariants.
165 #[inline]
166 fn new_unchecked<P: AsRef<OsStr> + ?Sized>(path: &P) -> &Self {
167 #[ref_cast_custom]
168 fn ref_cast<Form: PathForm>(path: &std::path::Path) -> &Path<Form>;
169
170 debug_assert!(Form::invariants_satisfied(path));
171 ref_cast(std::path::Path::new(path))
172 }
173
174 /// Attempt to create a new [`Path`] from a reference of another type.
175 ///
176 /// This is a convenience method instead of having to use `try_into` with a type annotation.
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// use nu_path::{AbsolutePath, RelativePath};
182 ///
183 /// assert!(AbsolutePath::try_new("foo.txt").is_err());
184 /// assert!(RelativePath::try_new("foo.txt").is_ok());
185 /// ```
186 #[inline]
187 pub fn try_new<'a, T>(path: &'a T) -> Result<&'a Self, <&'a T as TryInto<&'a Self>>::Error>
188 where
189 T: ?Sized,
190 &'a T: TryInto<&'a Self>,
191 {
192 path.try_into()
193 }
194
195 /// Returns the underlying [`OsStr`] slice.
196 ///
197 /// # Examples
198 ///
199 /// ```
200 /// use nu_path::Path;
201 ///
202 /// let os_str = Path::new("foo.txt").as_os_str();
203 /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
204 /// ```
205 #[must_use]
206 #[inline]
207 pub fn as_os_str(&self) -> &OsStr {
208 self.inner.as_os_str()
209 }
210
211 /// Returns a [`str`] slice if the [`Path`] is valid unicode.
212 ///
213 /// # Examples
214 ///
215 /// ```
216 /// use nu_path::Path;
217 ///
218 /// let path = Path::new("foo.txt");
219 /// assert_eq!(path.to_str(), Some("foo.txt"));
220 /// ```
221 #[inline]
222 pub fn to_str(&self) -> Option<&str> {
223 self.inner.to_str()
224 }
225
226 /// Converts a [`Path`] to a `Cow<str>`.
227 ///
228 /// Any non-Unicode sequences are replaced with `U+FFFD REPLACEMENT CHARACTER`.
229 ///
230 /// # Examples
231 ///
232 /// Calling `to_string_lossy` on a [`Path`] with valid unicode:
233 ///
234 /// ```
235 /// use nu_path::Path;
236 ///
237 /// let path = Path::new("foo.txt");
238 /// assert_eq!(path.to_string_lossy(), "foo.txt");
239 /// ```
240 ///
241 /// Had `path` contained invalid unicode, the `to_string_lossy` call might have returned
242 /// `"fo�.txt"`.
243 #[inline]
244 pub fn to_string_lossy(&self) -> Cow<'_, str> {
245 self.inner.to_string_lossy()
246 }
247
248 /// Converts a [`Path`] to an owned [`PathBuf`].
249 ///
250 /// # Examples
251 ///
252 /// ```
253 /// use nu_path::{Path, PathBuf};
254 ///
255 /// let path_buf = Path::new("foo.txt").to_path_buf();
256 /// assert_eq!(path_buf, PathBuf::from("foo.txt"));
257 /// ```
258 #[inline]
259 pub fn to_path_buf(&self) -> PathBuf<Form> {
260 PathBuf::new_unchecked(self.inner.to_path_buf())
261 }
262
263 /// Returns the [`Path`] without its final component, if there is one.
264 ///
265 /// This means it returns `Some("")` for relative paths with one component.
266 ///
267 /// Returns [`None`] if the path terminates in a root or prefix, or if it's
268 /// the empty string.
269 ///
270 /// # Examples
271 ///
272 /// ```
273 /// use nu_path::Path;
274 ///
275 /// let path = Path::new("/foo/bar");
276 /// let parent = path.parent().unwrap();
277 /// assert_eq!(parent, Path::new("/foo"));
278 ///
279 /// let grand_parent = parent.parent().unwrap();
280 /// assert_eq!(grand_parent, Path::new("/"));
281 /// assert_eq!(grand_parent.parent(), None);
282 ///
283 /// let relative_path = Path::new("foo/bar");
284 /// let parent = relative_path.parent();
285 /// assert_eq!(parent, Some(Path::new("foo")));
286 /// let grand_parent = parent.and_then(Path::parent);
287 /// assert_eq!(grand_parent, Some(Path::new("")));
288 /// let great_grand_parent = grand_parent.and_then(Path::parent);
289 /// assert_eq!(great_grand_parent, None);
290 /// ```
291 #[must_use]
292 #[inline]
293 pub fn parent(&self) -> Option<&Self> {
294 self.inner.parent().map(Self::new_unchecked)
295 }
296
297 /// Produces an iterator over a [`Path`] and its ancestors.
298 ///
299 /// The iterator will yield the [`Path`] that is returned if the [`parent`](Path::parent) method
300 /// is used zero or more times. That means, the iterator will yield `&self`,
301 /// `&self.parent().unwrap()`, `&self.parent().unwrap().parent().unwrap()` and so on.
302 /// If the [`parent`](Path::parent) method returns [`None`], the iterator will do likewise.
303 /// The iterator will always yield at least one value, namely `&self`.
304 ///
305 /// # Examples
306 ///
307 /// ```
308 /// use nu_path::Path;
309 ///
310 /// let mut ancestors = Path::new("/foo/bar").ancestors();
311 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
312 /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
313 /// assert_eq!(ancestors.next(), Some(Path::new("/")));
314 /// assert_eq!(ancestors.next(), None);
315 ///
316 /// let mut ancestors = Path::new("../foo/bar").ancestors();
317 /// assert_eq!(ancestors.next(), Some(Path::new("../foo/bar")));
318 /// assert_eq!(ancestors.next(), Some(Path::new("../foo")));
319 /// assert_eq!(ancestors.next(), Some(Path::new("..")));
320 /// assert_eq!(ancestors.next(), Some(Path::new("")));
321 /// assert_eq!(ancestors.next(), None);
322 /// ```
323 #[inline]
324 pub fn ancestors(&self) -> Ancestors<'_, Form> {
325 Ancestors {
326 _form: PhantomData,
327 inner: self.inner.ancestors(),
328 }
329 }
330
331 /// Returns the final component of a [`Path`], if there is one.
332 ///
333 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
334 /// is the directory name.
335 ///
336 /// Returns [`None`] if the path terminates in `..`.
337 ///
338 /// # Examples
339 ///
340 /// ```
341 /// use nu_path::Path;
342 /// use std::ffi::OsStr;
343 ///
344 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
345 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
346 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
347 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
348 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
349 /// assert_eq!(None, Path::new("/").file_name());
350 /// ```
351 #[must_use]
352 #[inline]
353 pub fn file_name(&self) -> Option<&OsStr> {
354 self.inner.file_name()
355 }
356
357 /// Returns a relative path that, when joined onto `base`, yields `self`.
358 ///
359 /// # Examples
360 ///
361 /// ```
362 /// use nu_path::{Path, PathBuf};
363 ///
364 /// let path = Path::new("/test/haha/foo.txt");
365 ///
366 /// assert_eq!(path.strip_prefix("/").unwrap(), Path::new("test/haha/foo.txt"));
367 /// assert_eq!(path.strip_prefix("/test").unwrap(), Path::new("haha/foo.txt"));
368 /// assert_eq!(path.strip_prefix("/test/").unwrap(), Path::new("haha/foo.txt"));
369 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt").unwrap(), Path::new(""));
370 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/").unwrap(), Path::new(""));
371 ///
372 /// assert!(path.strip_prefix("test").is_err());
373 /// assert!(path.strip_prefix("/haha").is_err());
374 ///
375 /// let prefix = PathBuf::from("/test/");
376 /// assert_eq!(path.strip_prefix(prefix).unwrap(), Path::new("haha/foo.txt"));
377 /// ```
378 #[inline]
379 pub fn strip_prefix(&self, base: impl AsRef<Path>) -> Result<&RelativePath, StripPrefixError> {
380 self.inner
381 .strip_prefix(&base.as_ref().inner)
382 .map(RelativePath::new_unchecked)
383 }
384
385 /// Determines whether `base` is a prefix of `self`.
386 ///
387 /// Only considers whole path components to match.
388 ///
389 /// # Examples
390 ///
391 /// ```
392 /// use nu_path::Path;
393 ///
394 /// let path = Path::new("/etc/passwd");
395 ///
396 /// assert!(path.starts_with("/etc"));
397 /// assert!(path.starts_with("/etc/"));
398 /// assert!(path.starts_with("/etc/passwd"));
399 /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
400 /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
401 ///
402 /// assert!(!path.starts_with("/e"));
403 /// assert!(!path.starts_with("/etc/passwd.txt"));
404 ///
405 /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
406 /// ```
407 #[must_use]
408 #[inline]
409 pub fn starts_with(&self, base: impl AsRef<Path>) -> bool {
410 self.inner.starts_with(&base.as_ref().inner)
411 }
412
413 /// Determines whether `child` is a suffix of `self`.
414 ///
415 /// Only considers whole path components to match.
416 ///
417 /// # Examples
418 ///
419 /// ```
420 /// use nu_path::Path;
421 ///
422 /// let path = Path::new("/etc/resolv.conf");
423 ///
424 /// assert!(path.ends_with("resolv.conf"));
425 /// assert!(path.ends_with("etc/resolv.conf"));
426 /// assert!(path.ends_with("/etc/resolv.conf"));
427 ///
428 /// assert!(!path.ends_with("/resolv.conf"));
429 /// assert!(!path.ends_with("conf")); // use .extension() instead
430 /// ```
431 #[must_use]
432 #[inline]
433 pub fn ends_with(&self, child: impl AsRef<Path>) -> bool {
434 self.inner.ends_with(&child.as_ref().inner)
435 }
436
437 /// Extracts the stem (non-extension) portion of [`self.file_name`](Path::file_name).
438 ///
439 /// The stem is:
440 ///
441 /// * [`None`], if there is no file name;
442 /// * The entire file name if there is no embedded `.`;
443 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
444 /// * Otherwise, the portion of the file name before the final `.`
445 ///
446 /// # Examples
447 ///
448 /// ```
449 /// use nu_path::Path;
450 ///
451 /// assert_eq!("foo", Path::new("foo.rs").file_stem().unwrap());
452 /// assert_eq!("foo.tar", Path::new("foo.tar.gz").file_stem().unwrap());
453 /// ```
454 #[must_use]
455 #[inline]
456 pub fn file_stem(&self) -> Option<&OsStr> {
457 self.inner.file_stem()
458 }
459
460 /// Extracts the extension (without the leading dot) of [`self.file_name`](Path::file_name),
461 /// if possible.
462 ///
463 /// The extension is:
464 ///
465 /// * [`None`], if there is no file name;
466 /// * [`None`], if there is no embedded `.`;
467 /// * [`None`], if the file name begins with `.` and has no other `.`s within;
468 /// * Otherwise, the portion of the file name after the final `.`
469 ///
470 /// # Examples
471 ///
472 /// ```
473 /// use nu_path::Path;
474 ///
475 /// assert_eq!("rs", Path::new("foo.rs").extension().unwrap());
476 /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
477 /// ```
478 #[must_use]
479 #[inline]
480 pub fn extension(&self) -> Option<&OsStr> {
481 self.inner.extension()
482 }
483
484 /// Produces an iterator over the [`Component`](std::path::Component)s of the path.
485 ///
486 /// When parsing the path, there is a small amount of normalization:
487 ///
488 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
489 /// `a` and `b` as components.
490 ///
491 /// * Occurrences of `.` are normalized away, except if they are at the
492 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
493 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
494 /// an additional [`CurDir`](std::path::Component) component.
495 ///
496 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
497 ///
498 /// Note that no other normalization takes place; in particular, `a/c`
499 /// and `a/b/../c` are distinct, to account for the possibility that `b`
500 /// is a symbolic link (so its parent isn't `a`).
501 ///
502 /// # Examples
503 ///
504 /// ```
505 /// use nu_path::Path;
506 /// use std::path::Component;
507 /// use std::ffi::OsStr;
508 ///
509 /// let mut components = Path::new("/tmp/foo.txt").components();
510 ///
511 /// assert_eq!(components.next(), Some(Component::RootDir));
512 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
513 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
514 /// assert_eq!(components.next(), None)
515 /// ```
516 #[inline]
517 pub fn components(&self) -> std::path::Components<'_> {
518 self.inner.components()
519 }
520
521 /// Produces an iterator over the path's components viewed as [`OsStr`] slices.
522 ///
523 /// For more information about the particulars of how the path is separated into components,
524 /// see [`components`](Path::components).
525 ///
526 /// # Examples
527 ///
528 /// ```
529 /// use nu_path::Path;
530 /// use std::ffi::OsStr;
531 ///
532 /// let mut it = Path::new("/tmp/foo.txt").iter();
533 /// assert_eq!(it.next(), Some(OsStr::new(&std::path::MAIN_SEPARATOR.to_string())));
534 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
535 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
536 /// assert_eq!(it.next(), None)
537 /// ```
538 #[inline]
539 pub fn iter(&self) -> std::path::Iter<'_> {
540 self.inner.iter()
541 }
542
543 /// Returns an object that implements [`Display`](fmt::Display) for safely printing paths
544 /// that may contain non-Unicode data. This may perform lossy conversion,
545 /// depending on the platform. If you would like an implementation which escapes the path
546 /// please use [`Debug`](fmt::Debug) instead.
547 ///
548 /// # Examples
549 ///
550 /// ```
551 /// use nu_path::Path;
552 ///
553 /// let path = Path::new("/tmp/foo.rs");
554 ///
555 /// println!("{}", path.display());
556 /// ```
557 #[inline]
558 pub fn display(&self) -> std::path::Display<'_> {
559 self.inner.display()
560 }
561
562 /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or allocating.
563 #[inline]
564 pub fn into_path_buf(self: Box<Self>) -> PathBuf<Form> {
565 // Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
566 let ptr = Box::into_raw(self) as *mut std::path::Path;
567 let boxed = unsafe { Box::from_raw(ptr) };
568 PathBuf::new_unchecked(boxed.into_path_buf())
569 }
570
571 /// Returns a reference to the same [`Path`] in a different form.
572 ///
573 /// [`PathForm`]s can be converted to one another based on [`PathCast`] implementations.
574 /// Namely, the following form conversions are possible:
575 /// - [`Relative`], [`Absolute`], or [`Canonical`] into [`Any`].
576 /// - [`Canonical`] into [`Absolute`].
577 /// - Any form into itself.
578 ///
579 /// # Examples
580 ///
581 /// ```
582 /// use nu_path::{Path, RelativePath};
583 ///
584 /// let relative = RelativePath::try_new("test.txt").unwrap();
585 /// let p: &Path = relative.cast();
586 /// assert_eq!(p, relative);
587 /// ```
588 #[inline]
589 pub fn cast<To>(&self) -> &Path<To>
590 where
591 To: PathForm,
592 Form: PathCast<To>,
593 {
594 Path::new_unchecked(self)
595 }
596
597 /// Returns a reference to a path with its form as [`Any`].
598 ///
599 /// # Examples
600 ///
601 /// ```
602 /// use nu_path::{Path, RelativePath};
603 ///
604 /// let p = RelativePath::try_new("test.txt").unwrap();
605 /// assert_eq!(Path::new("test.txt"), p.as_any());
606 /// ```
607 #[inline]
608 pub fn as_any(&self) -> &Path {
609 Path::new_unchecked(self)
610 }
611}
612
613impl Path {
614 /// Create a new [`Path`] by wrapping a string slice.
615 ///
616 /// This is a cost-free conversion.
617 ///
618 /// # Examples
619 ///
620 /// ```
621 /// use nu_path::Path;
622 ///
623 /// Path::new("foo.txt");
624 /// ```
625 ///
626 /// You can create [`Path`]s from [`String`]s, or even other [`Path`]s:
627 ///
628 /// ```
629 /// use nu_path::Path;
630 ///
631 /// let string = String::from("foo.txt");
632 /// let from_string = Path::new(&string);
633 /// let from_path = Path::new(&from_string);
634 /// assert_eq!(from_string, from_path);
635 /// ```
636 #[inline]
637 pub fn new<P: AsRef<OsStr> + ?Sized>(path: &P) -> &Self {
638 Self::new_unchecked(path)
639 }
640
641 /// Returns a mutable reference to the underlying [`OsStr`] slice.
642 ///
643 /// # Examples
644 ///
645 /// ```
646 /// use nu_path::{Path, PathBuf};
647 ///
648 /// let mut path = PathBuf::from("Foo.TXT");
649 ///
650 /// assert_ne!(path, Path::new("foo.txt"));
651 ///
652 /// path.as_mut_os_str().make_ascii_lowercase();
653 /// assert_eq!(path, Path::new("foo.txt"));
654 /// ```
655 #[must_use]
656 #[inline]
657 pub fn as_mut_os_str(&mut self) -> &mut OsStr {
658 self.inner.as_mut_os_str()
659 }
660
661 /// Returns `true` if the [`Path`] is absolute, i.e., if it is independent of
662 /// the current directory.
663 ///
664 /// * On Unix, a path is absolute if it starts with the root,
665 /// so [`is_absolute`](Path::is_absolute) and [`has_root`](Path::has_root) are equivalent.
666 ///
667 /// * On Windows, a path is absolute if it has a prefix and starts with the root:
668 /// `c:\windows` is absolute, while `c:temp` and `\temp` are not.
669 ///
670 /// # Examples
671 ///
672 /// ```
673 /// use nu_path::Path;
674 ///
675 /// assert!(!Path::new("foo.txt").is_absolute());
676 /// ```
677 #[must_use]
678 #[inline]
679 pub fn is_absolute(&self) -> bool {
680 self.inner.is_absolute()
681 }
682
683 // Returns `true` if the [`Path`] is relative, i.e., not absolute.
684 ///
685 /// See [`is_absolute`](Path::is_absolute)'s documentation for more details.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// use nu_path::Path;
691 ///
692 /// assert!(Path::new("foo.txt").is_relative());
693 /// ```
694 #[must_use]
695 #[inline]
696 pub fn is_relative(&self) -> bool {
697 self.inner.is_relative()
698 }
699
700 /// Returns an `Ok` [`AbsolutePath`] if the [`Path`] is absolute.
701 /// Otherwise, returns an `Err` [`RelativePath`].
702 ///
703 /// # Examples
704 ///
705 /// ```
706 /// use nu_path::Path;
707 ///
708 /// assert!(Path::new("test.txt").try_absolute().is_err());
709 /// ```
710 #[inline]
711 pub fn try_absolute(&self) -> Result<&AbsolutePath, &RelativePath> {
712 if self.is_absolute() {
713 Ok(AbsolutePath::new_unchecked(&self.inner))
714 } else {
715 Err(RelativePath::new_unchecked(&self.inner))
716 }
717 }
718
719 /// Returns an `Ok` [`RelativePath`] if the [`Path`] is relative.
720 /// Otherwise, returns an `Err` [`AbsolutePath`].
721 ///
722 /// # Examples
723 ///
724 /// ```
725 /// use nu_path::Path;
726 ///
727 /// assert!(Path::new("test.txt").try_relative().is_ok());
728 /// ```
729 #[inline]
730 pub fn try_relative(&self) -> Result<&RelativePath, &AbsolutePath> {
731 if self.is_relative() {
732 Ok(RelativePath::new_unchecked(&self.inner))
733 } else {
734 Err(AbsolutePath::new_unchecked(&self.inner))
735 }
736 }
737}
738
739impl<Form: PathJoin> Path<Form> {
740 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
741 ///
742 /// If `path` is absolute, it replaces the current path.
743 ///
744 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
745 ///
746 /// # Examples
747 ///
748 /// ```
749 /// use nu_path::{Path, PathBuf};
750 ///
751 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
752 /// assert_eq!(Path::new("/etc").join("/bin/sh"), PathBuf::from("/bin/sh"));
753 /// ```
754 #[must_use]
755 #[inline]
756 pub fn join(&self, path: impl AsRef<Path>) -> PathBuf<Form::Output> {
757 PathBuf::new_unchecked(self.inner.join(&path.as_ref().inner))
758 }
759}
760
761impl<Form: PathSet> Path<Form> {
762 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
763 ///
764 /// See [`PathBuf::set_file_name`] for more details.
765 ///
766 /// # Examples
767 ///
768 /// ```
769 /// use nu_path::{Path, PathBuf};
770 ///
771 /// let path = Path::new("/tmp/foo.png");
772 /// assert_eq!(path.with_file_name("bar"), PathBuf::from("/tmp/bar"));
773 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
774 ///
775 /// let path = Path::new("/tmp");
776 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
777 /// ```
778 #[inline]
779 pub fn with_file_name(&self, file_name: impl AsRef<OsStr>) -> PathBuf<Form> {
780 PathBuf::new_unchecked(self.inner.with_file_name(file_name))
781 }
782
783 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
784 ///
785 /// See [`PathBuf::set_extension`] for more details.
786 ///
787 /// # Examples
788 ///
789 /// ```
790 /// use nu_path::{Path, PathBuf};
791 ///
792 /// let path = Path::new("foo.rs");
793 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
794 ///
795 /// let path = Path::new("foo.tar.gz");
796 /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
797 /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
798 /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
799 /// ```
800 #[inline]
801 pub fn with_extension(&self, extension: impl AsRef<OsStr>) -> PathBuf<Form> {
802 PathBuf::new_unchecked(self.inner.with_extension(extension))
803 }
804}
805
806impl<Form: MaybeRelative> Path<Form> {
807 /// Returns the, potentially relative, underlying [`std::path::Path`].
808 ///
809 /// # Note
810 ///
811 /// Caution should be taken when using this function. Nushell keeps track of an emulated current
812 /// working directory, and using the [`std::path::Path`] returned from this method will likely
813 /// use [`std::env::current_dir`] to resolve the path instead of using the emulated current
814 /// working directory.
815 ///
816 /// Instead, you should probably join this path onto the emulated current working directory.
817 /// Any [`AbsolutePath`] or [`CanonicalPath`] will also suffice.
818 ///
819 /// # Examples
820 ///
821 /// ```
822 /// use nu_path::Path;
823 ///
824 /// let p = Path::new("test.txt");
825 /// assert_eq!(std::path::Path::new("test.txt"), p.as_relative_std_path());
826 /// ```
827 #[inline]
828 pub fn as_relative_std_path(&self) -> &std::path::Path {
829 &self.inner
830 }
831
832 // Returns `true` if the [`Path`] has a root.
833 ///
834 /// * On Unix, a path has a root if it begins with `/`.
835 ///
836 /// * On Windows, a path has a root if it:
837 /// * has no prefix and begins with a separator, e.g., `\windows`
838 /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
839 /// * has any non-disk prefix, e.g., `\\server\share`
840 ///
841 /// # Examples
842 ///
843 /// ```
844 /// use nu_path::Path;
845 ///
846 /// assert!(Path::new("/etc/passwd").has_root());
847 /// ```
848 #[must_use]
849 #[inline]
850 pub fn has_root(&self) -> bool {
851 self.inner.has_root()
852 }
853}
854
855impl<Form: IsAbsolute> Path<Form> {
856 /// Returns the underlying [`std::path::Path`].
857 ///
858 /// # Examples
859 ///
860 #[cfg_attr(not(windows), doc = "```")]
861 #[cfg_attr(windows, doc = "```no_run")]
862 /// use nu_path::AbsolutePath;
863 ///
864 /// let p = AbsolutePath::try_new("/test").unwrap();
865 /// assert_eq!(std::path::Path::new("/test"), p.as_std_path());
866 /// ```
867 #[inline]
868 pub fn as_std_path(&self) -> &std::path::Path {
869 &self.inner
870 }
871
872 /// Converts a [`Path`] to an owned [`std::path::PathBuf`].
873 ///
874 /// # Examples
875 ///
876 #[cfg_attr(not(windows), doc = "```")]
877 #[cfg_attr(windows, doc = "```no_run")]
878 /// use nu_path::AbsolutePath;
879 ///
880 /// let path = AbsolutePath::try_new("/foo").unwrap();
881 /// assert_eq!(path.to_std_path_buf(), std::path::PathBuf::from("/foo"));
882 /// ```
883 #[inline]
884 pub fn to_std_path_buf(&self) -> std::path::PathBuf {
885 self.inner.to_path_buf()
886 }
887
888 /// Queries the file system to get information about a file, directory, etc.
889 ///
890 /// This function will traverse symbolic links to query information about the destination file.
891 ///
892 /// This is an alias to [`std::fs::metadata`].
893 ///
894 /// # Examples
895 ///
896 /// ```no_run
897 /// use nu_path::AbsolutePath;
898 ///
899 /// let path = AbsolutePath::try_new("/Minas/tirith").unwrap();
900 /// let metadata = path.metadata().expect("metadata call failed");
901 /// println!("{:?}", metadata.file_type());
902 /// ```
903 #[inline]
904 pub fn metadata(&self) -> io::Result<fs::Metadata> {
905 self.inner.metadata()
906 }
907
908 /// Returns an iterator over the entries within a directory.
909 ///
910 /// The iterator will yield instances of <code>[io::Result]<[fs::DirEntry]></code>.
911 /// New errors may be encountered after an iterator is initially constructed.
912 ///
913 /// This is an alias to [`std::fs::read_dir`].
914 ///
915 /// # Examples
916 ///
917 /// ```no_run
918 /// use nu_path::AbsolutePath;
919 ///
920 /// let path = AbsolutePath::try_new("/laputa").unwrap();
921 /// for entry in path.read_dir().expect("read_dir call failed") {
922 /// if let Ok(entry) = entry {
923 /// println!("{:?}", entry.path());
924 /// }
925 /// }
926 /// ```
927 #[inline]
928 pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
929 self.inner.read_dir()
930 }
931
932 /// Returns `true` if the path points at an existing entity.
933 ///
934 /// Warning: this method may be error-prone, consider using [`try_exists`](Path::try_exists)
935 /// instead! It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs.
936 ///
937 /// This function will traverse symbolic links to query information about the destination file.
938 ///
939 /// If you cannot access the metadata of the file, e.g. because of a permission error
940 /// or broken symbolic links, this will return `false`.
941 ///
942 /// # Examples
943 ///
944 /// ```no_run
945 /// use nu_path::AbsolutePath;
946 ///
947 /// let path = AbsolutePath::try_new("/does_not_exist").unwrap();
948 /// assert!(!path.exists());
949 /// ```
950 #[must_use]
951 #[inline]
952 pub fn exists(&self) -> bool {
953 self.inner.exists()
954 }
955
956 /// Returns `true` if the path exists on disk and is pointing at a regular file.
957 ///
958 /// This function will traverse symbolic links to query information about the destination file.
959 ///
960 /// If you cannot access the metadata of the file, e.g. because of a permission error
961 /// or broken symbolic links, this will return `false`.
962 ///
963 /// # Examples
964 ///
965 /// ```no_run
966 /// use nu_path::AbsolutePath;
967 ///
968 /// let path = AbsolutePath::try_new("/is_a_directory/").unwrap();
969 /// assert_eq!(path.is_file(), false);
970 ///
971 /// let path = AbsolutePath::try_new("/a_file.txt").unwrap();
972 /// assert_eq!(path.is_file(), true);
973 /// ```
974 ///
975 /// # See Also
976 ///
977 /// When the goal is simply to read from (or write to) the source, the most reliable way
978 /// to test the source can be read (or written to) is to open it. Only using `is_file` can
979 /// break workflows like `diff <( prog_a )` on a Unix-like system for example.
980 /// See [`std::fs::File::open`] or [`std::fs::OpenOptions::open`] for more information.
981 #[must_use]
982 #[inline]
983 pub fn is_file(&self) -> bool {
984 self.inner.is_file()
985 }
986
987 /// Returns `true` if the path exists on disk and is pointing at a directory.
988 ///
989 /// This function will traverse symbolic links to query information about the destination file.
990 ///
991 /// If you cannot access the metadata of the file, e.g. because of a permission error
992 /// or broken symbolic links, this will return `false`.
993 ///
994 /// # Examples
995 ///
996 /// ```no_run
997 /// use nu_path::AbsolutePath;
998 ///
999 /// let path = AbsolutePath::try_new("/is_a_directory/").unwrap();
1000 /// assert_eq!(path.is_dir(), true);
1001 ///
1002 /// let path = AbsolutePath::try_new("/a_file.txt").unwrap();
1003 /// assert_eq!(path.is_dir(), false);
1004 /// ```
1005 #[must_use]
1006 #[inline]
1007 pub fn is_dir(&self) -> bool {
1008 self.inner.is_dir()
1009 }
1010}
1011
1012impl AbsolutePath {
1013 /// Returns the canonical, absolute form of the path with all intermediate components
1014 /// normalized and symbolic links resolved.
1015 ///
1016 /// On Windows, this will also simplify to a winuser path.
1017 ///
1018 /// This is an alias to [`std::fs::canonicalize`].
1019 ///
1020 /// # Examples
1021 ///
1022 /// ```no_run
1023 /// use nu_path::{AbsolutePath, PathBuf};
1024 ///
1025 /// let path = AbsolutePath::try_new("/foo/test/../test/bar.rs").unwrap();
1026 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
1027 /// ```
1028 #[cfg(not(windows))]
1029 #[inline]
1030 pub fn canonicalize(&self) -> io::Result<CanonicalPathBuf> {
1031 self.inner
1032 .canonicalize()
1033 .map(CanonicalPathBuf::new_unchecked)
1034 }
1035
1036 /// Returns the canonical, absolute form of the path with all intermediate components
1037 /// normalized and symbolic links resolved.
1038 ///
1039 /// On Windows, this will also simplify to a winuser path.
1040 ///
1041 /// This is an alias to [`std::fs::canonicalize`].
1042 ///
1043 /// # Examples
1044 ///
1045 /// ```no_run
1046 /// use nu_path::{AbsolutePath, PathBuf};
1047 ///
1048 /// let path = AbsolutePath::try_new("/foo/test/../test/bar.rs").unwrap();
1049 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
1050 /// ```
1051 #[cfg(windows)]
1052 pub fn canonicalize(&self) -> io::Result<CanonicalPathBuf> {
1053 use omnipath::WinPathExt;
1054
1055 let path = self.inner.canonicalize()?.to_winuser_path()?;
1056 Ok(CanonicalPathBuf::new_unchecked(path))
1057 }
1058
1059 /// Reads a symbolic link, returning the file that the link points to.
1060 ///
1061 /// This is an alias to [`std::fs::read_link`].
1062 ///
1063 /// # Examples
1064 ///
1065 /// ```no_run
1066 /// use nu_path::AbsolutePath;
1067 ///
1068 /// let path = AbsolutePath::try_new("/laputa/sky_castle.rs").unwrap();
1069 /// let path_link = path.read_link().expect("read_link call failed");
1070 /// ```
1071 #[inline]
1072 pub fn read_link(&self) -> io::Result<AbsolutePathBuf> {
1073 self.inner.read_link().map(PathBuf::new_unchecked)
1074 }
1075
1076 /// Returns `Ok(true)` if the path points at an existing entity.
1077 ///
1078 /// This function will traverse symbolic links to query information about the destination file.
1079 /// In case of broken symbolic links this will return `Ok(false)`.
1080 ///
1081 /// [`Path::exists`] only checks whether or not a path was both found and readable.
1082 /// By contrast, [`try_exists`](Path::try_exists) will return `Ok(true)` or `Ok(false)`,
1083 /// respectively, if the path was _verified_ to exist or not exist.
1084 /// If its existence can neither be confirmed nor denied, it will propagate an `Err` instead.
1085 /// This can be the case if e.g. listing permission is denied on one of the parent directories.
1086 ///
1087 /// Note that while this avoids some pitfalls of the [`exists`](Path::exists) method,
1088 /// it still can not prevent time-of-check to time-of-use (TOCTOU) bugs.
1089 /// You should only use it in scenarios where those bugs are not an issue.
1090 ///
1091 /// # Examples
1092 ///
1093 /// ```no_run
1094 /// use nu_path::AbsolutePath;
1095 ///
1096 /// let path = AbsolutePath::try_new("/does_not_exist").unwrap();
1097 /// assert!(!path.try_exists().unwrap());
1098 ///
1099 /// let path = AbsolutePath::try_new("/root/secret_file.txt").unwrap();
1100 /// assert!(path.try_exists().is_err());
1101 /// ```
1102 #[inline]
1103 pub fn try_exists(&self) -> io::Result<bool> {
1104 self.inner.try_exists()
1105 }
1106
1107 /// Returns `true` if the path exists on disk and is pointing at a symbolic link.
1108 ///
1109 /// This function will not traverse symbolic links.
1110 /// In case of a broken symbolic link this will also return true.
1111 ///
1112 /// If you cannot access the directory containing the file, e.g., because of a permission error,
1113 /// this will return false.
1114 ///
1115 /// # Examples
1116 ///
1117 #[cfg_attr(unix, doc = "```no_run")]
1118 #[cfg_attr(not(unix), doc = "```ignore")]
1119 /// use nu_path::AbsolutePath;
1120 /// use std::os::unix::fs::symlink;
1121 ///
1122 /// let link_path = AbsolutePath::try_new("/link").unwrap();
1123 /// symlink("/origin_does_not_exist/", link_path).unwrap();
1124 /// assert_eq!(link_path.is_symlink(), true);
1125 /// assert_eq!(link_path.exists(), false);
1126 /// ```
1127 #[must_use]
1128 #[inline]
1129 pub fn is_symlink(&self) -> bool {
1130 self.inner.is_symlink()
1131 }
1132
1133 /// Queries the metadata about a file without following symlinks.
1134 ///
1135 /// This is an alias to [`std::fs::symlink_metadata`].
1136 ///
1137 /// # Examples
1138 ///
1139 /// ```no_run
1140 /// use nu_path::AbsolutePath;
1141 ///
1142 /// let path = AbsolutePath::try_new("/Minas/tirith").unwrap();
1143 /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
1144 /// println!("{:?}", metadata.file_type());
1145 /// ```
1146 #[inline]
1147 pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
1148 self.inner.symlink_metadata()
1149 }
1150}
1151
1152impl CanonicalPath {
1153 /// Returns a [`CanonicalPath`] as a [`AbsolutePath`].
1154 ///
1155 /// # Examples
1156 ///
1157 /// ```no_run
1158 /// use nu_path::AbsolutePath;
1159 ///
1160 /// let absolute = AbsolutePath::try_new("/test").unwrap();
1161 /// let p = absolute.canonicalize().unwrap();
1162 /// assert_eq!(absolute, p.as_absolute());
1163 /// ```
1164 #[inline]
1165 pub fn as_absolute(&self) -> &AbsolutePath {
1166 self.cast()
1167 }
1168}
1169
1170impl<Form: PathForm> fmt::Debug for Path<Form> {
1171 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 fmt::Debug::fmt(&self.inner, fmt)
1173 }
1174}
1175
1176impl<Form: PathForm> Clone for Box<Path<Form>> {
1177 #[inline]
1178 fn clone(&self) -> Self {
1179 std_box_to_box(self.inner.into())
1180 }
1181}
1182
1183impl<Form: PathForm> ToOwned for Path<Form> {
1184 type Owned = PathBuf<Form>;
1185
1186 #[inline]
1187 fn to_owned(&self) -> Self::Owned {
1188 self.to_path_buf()
1189 }
1190
1191 #[inline]
1192 fn clone_into(&self, target: &mut PathBuf<Form>) {
1193 self.inner.clone_into(&mut target.inner);
1194 }
1195}
1196
1197impl<'a, Form: PathForm> IntoIterator for &'a Path<Form> {
1198 type Item = &'a OsStr;
1199
1200 type IntoIter = std::path::Iter<'a>;
1201
1202 #[inline]
1203 fn into_iter(self) -> Self::IntoIter {
1204 self.iter()
1205 }
1206}
1207
1208/// An iterator over [`Path`] and its ancestors.
1209///
1210/// This `struct` is created by the [`ancestors`](Path::ancestors) method on [`Path`].
1211/// See its documentation for more.
1212///
1213/// # Examples
1214///
1215/// ```
1216/// use nu_path::Path;
1217///
1218/// let path = Path::new("/foo/bar");
1219///
1220/// for ancestor in path.ancestors() {
1221/// println!("{}", ancestor.display());
1222/// }
1223/// ```
1224#[derive(Clone, Copy)]
1225pub struct Ancestors<'a, Form: PathForm> {
1226 _form: PhantomData<Form>,
1227 inner: std::path::Ancestors<'a>,
1228}
1229
1230impl<Form: PathForm> fmt::Debug for Ancestors<'_, Form> {
1231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1232 fmt::Debug::fmt(&self.inner, f)
1233 }
1234}
1235
1236impl<'a, Form: PathForm> Iterator for Ancestors<'a, Form> {
1237 type Item = &'a Path<Form>;
1238
1239 fn next(&mut self) -> Option<Self::Item> {
1240 self.inner.next().map(Path::new_unchecked)
1241 }
1242}
1243
1244impl<Form: PathForm> FusedIterator for Ancestors<'_, Form> {}
1245
1246/// A wrapper around [`std::path::PathBuf`] with extra invariants determined by its `Form`.
1247///
1248/// The possible path forms are [`Any`], [`Relative`], [`Absolute`], or [`Canonical`].
1249/// To learn more, view the documentation on [`PathForm`] or any of the individual forms.
1250///
1251/// There are also several type aliases available, corresponding to each [`PathForm`]:
1252/// - [`RelativePathBuf`] (same as [`PathBuf<Relative>`])
1253/// - [`AbsolutePathBuf`] (same as [`PathBuf<Absolute>`])
1254/// - [`CanonicalPathBuf`] (same as [`PathBuf<Canonical>`])
1255///
1256/// If the `Form` is not specified, then it defaults to [`Any`],
1257/// so [`PathBuf`] and [`PathBuf<Any>`] are one in the same.
1258///
1259/// # Examples
1260///
1261/// To create a [`PathBuf`] with [`Any`] form, you can use the same techniques as when creating
1262/// a [`std::path::PathBuf`].
1263///
1264/// ```
1265/// use nu_path::PathBuf;
1266///
1267/// let path = PathBuf::from(r"C:\windows\system32.dll");
1268///
1269/// let mut path1 = PathBuf::new();
1270/// path1.push(r"C:\");
1271/// path1.push("windows");
1272/// path1.push("system32");
1273/// path1.set_extension("dll");
1274///
1275/// let path2: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
1276///
1277/// assert_eq!(path1, path2);
1278/// ```
1279///
1280/// # Converting to [`std::path`] types
1281///
1282/// [`PathBuf`]s with form [`Any`] cannot be easily referenced as a [`std::path::Path`]
1283/// or converted to a [`std::path::PathBuf`] by design.
1284/// Other Nushell crates need to account for the emulated current working directory
1285/// before passing a path to functions in [`std`] or other third party crates.
1286/// You can [`join`](Path::join) a [`Path`] onto an [`AbsolutePath`] or a [`CanonicalPath`].
1287/// This will return an [`AbsolutePathBuf`] which can be easily referenced as a [`std::path::Path`].
1288/// If you really mean it, you can instead use [`as_relative_std_path`](Path::as_relative_std_path)
1289/// or [`into_relative_std_path_buf`](PathBuf::into_relative_std_path_buf)
1290/// to get the underlying [`std::path::Path`] or [`std::path::PathBuf`] from a [`PathBuf`].
1291/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
1292/// the path which is almost always incorrect behavior. Extra care is needed to ensure that this
1293/// is not the case after using [`as_relative_std_path`](Path::as_relative_std_path)
1294/// or [`into_relative_std_path_buf`](PathBuf::into_relative_std_path_buf).
1295#[repr(transparent)]
1296pub struct PathBuf<Form: PathForm = Any> {
1297 _form: PhantomData<Form>,
1298 inner: std::path::PathBuf,
1299}
1300
1301/// A path buf that is strictly relative.
1302///
1303/// I.e., this path buf is guaranteed to never be absolute.
1304///
1305/// [`RelativePathBuf`]s cannot be easily referenced as a [`std::path::Path`]
1306/// or converted to a [`std::path::PathBuf`] by design.
1307/// Other Nushell crates need to account for the emulated current working directory
1308/// before passing a path to functions in [`std`] or other third party crates.
1309/// You can [`join`](Path::join) a [`RelativePath`] onto an [`AbsolutePath`] or a [`CanonicalPath`].
1310/// This will return an [`AbsolutePathBuf`] which can be easily referenced as a [`std::path::Path`].
1311/// If you really mean it, you can instead use
1312/// [`as_relative_std_path`](RelativePath::as_relative_std_path)
1313/// or [`into_relative_std_path_buf`](RelativePathBuf::into_relative_std_path_buf)
1314/// to get the underlying [`std::path::Path`] or [`std::path::PathBuf`] from a [`RelativePathBuf`].
1315/// But this may cause third-party code to use [`std::env::current_dir`] to resolve
1316/// the path which is almost always incorrect behavior. Extra care is needed to ensure that this
1317/// is not the case after using [`as_relative_std_path`](RelativePath::as_relative_std_path)
1318/// or [`into_relative_std_path_buf`](RelativePathBuf::into_relative_std_path_buf).
1319///
1320/// # Examples
1321///
1322/// [`RelativePathBuf`]s can be created by using [`try_into_relative`](PathBuf::try_into_relative)
1323/// on a [`PathBuf`] or by using [`to_path_buf`](Path::to_path_buf) on a [`RelativePath`].
1324///
1325/// ```
1326/// use nu_path::{PathBuf, RelativePath, RelativePathBuf};
1327///
1328/// let path_buf = PathBuf::from("foo.txt");
1329/// let path_buf = path_buf.try_into_relative().unwrap();
1330///
1331/// let path = RelativePath::try_new("foo.txt").unwrap();
1332/// let path_buf2 = path.to_path_buf();
1333///
1334/// assert_eq!(path_buf, path_buf2);
1335/// ```
1336///
1337/// You can also use `RelativePathBuf::try_from` or `try_into`.
1338/// This supports attempted conversions from [`Path`] as well as types in [`std::path`].
1339///
1340/// ```
1341/// use nu_path::{Path, RelativePathBuf};
1342///
1343/// let path1 = RelativePathBuf::try_from("foo.txt").unwrap();
1344///
1345/// let path2 = Path::new("foo.txt");
1346/// let path2 = RelativePathBuf::try_from(path2).unwrap();
1347///
1348/// let path3 = std::path::PathBuf::from("foo.txt");
1349/// let path3: RelativePathBuf = path3.try_into().unwrap();
1350///
1351/// assert_eq!(path1, path2);
1352/// assert_eq!(path2, path3);
1353/// ```
1354pub type RelativePathBuf = PathBuf<Relative>;
1355
1356/// A path buf that is strictly absolute.
1357///
1358/// I.e., this path buf is guaranteed to never be relative.
1359///
1360/// # Examples
1361///
1362/// [`AbsolutePathBuf`]s can be created by using [`try_into_absolute`](PathBuf::try_into_absolute)
1363/// on a [`PathBuf`] or by using [`to_path_buf`](Path::to_path_buf) on an [`AbsolutePath`].
1364///
1365#[cfg_attr(not(windows), doc = "```")]
1366#[cfg_attr(windows, doc = "```no_run")]
1367/// use nu_path::{AbsolutePath, AbsolutePathBuf, PathBuf};
1368///
1369/// let path_buf1 = PathBuf::from("/foo");
1370/// let path_buf1 = path_buf1.try_into_absolute().unwrap();
1371///
1372/// let path = AbsolutePath::try_new("/foo").unwrap();
1373/// let path_buf2 = path.to_path_buf();
1374///
1375/// assert_eq!(path_buf1, path_buf2);
1376/// ```
1377///
1378/// You can also use `AbsolutePathBuf::try_from` or `try_into`.
1379/// This supports attempted conversions from [`Path`] as well as types in [`std::path`].
1380///
1381#[cfg_attr(not(windows), doc = "```")]
1382#[cfg_attr(windows, doc = "```no_run")]
1383/// use nu_path::{AbsolutePathBuf, Path};
1384///
1385/// let path1 = AbsolutePathBuf::try_from("/foo").unwrap();
1386///
1387/// let path2 = Path::new("/foo");
1388/// let path2 = AbsolutePathBuf::try_from(path2).unwrap();
1389///
1390/// let path3 = std::path::PathBuf::from("/foo");
1391/// let path3: AbsolutePathBuf = path3.try_into().unwrap();
1392///
1393/// assert_eq!(path1, path2);
1394/// assert_eq!(path2, path3);
1395/// ```
1396pub type AbsolutePathBuf = PathBuf<Absolute>;
1397
1398/// An absolute, canonical path buf.
1399///
1400/// # Examples
1401///
1402/// [`CanonicalPathBuf`]s can only be created by using [`canonicalize`](Path::canonicalize) on
1403/// an [`AbsolutePath`]. [`CanonicalPathBuf`]s can be converted back to [`AbsolutePathBuf`]s via
1404/// [`into_absolute`](CanonicalPathBuf::into_absolute).
1405///
1406/// ```no_run
1407/// use nu_path::AbsolutePathBuf;
1408///
1409/// let path = AbsolutePathBuf::try_from("/foo").unwrap();
1410///
1411/// let canonical = path.canonicalize().expect("canonicalization failed");
1412///
1413/// assert_eq!(path, canonical.into_absolute());
1414/// ```
1415pub type CanonicalPathBuf = PathBuf<Canonical>;
1416
1417impl<Form: PathForm> PathBuf<Form> {
1418 /// Create a new [`PathBuf`] of any form without validiting invariants.
1419 #[inline]
1420 pub(crate) fn new_unchecked(buf: std::path::PathBuf) -> Self {
1421 debug_assert!(Form::invariants_satisfied(&buf));
1422 Self {
1423 _form: PhantomData,
1424 inner: buf,
1425 }
1426 }
1427
1428 /// Coerces to a [`Path`] slice.
1429 ///
1430 /// # Examples
1431 ///
1432 /// ```
1433 /// use nu_path::{Path, PathBuf};
1434 ///
1435 /// let p = PathBuf::from("/test");
1436 /// assert_eq!(Path::new("/test"), p.as_path());
1437 /// ```
1438 #[must_use]
1439 #[inline]
1440 pub fn as_path(&self) -> &Path<Form> {
1441 Path::new_unchecked(&self.inner)
1442 }
1443
1444 /// Truncates `self` to [`self.parent`](Path::parent).
1445 ///
1446 /// Returns `false` and does nothing if [`self.parent`](Path::parent) is [`None`].
1447 /// Otherwise, returns `true`.
1448 ///
1449 /// # Examples
1450 ///
1451 /// ```
1452 /// use nu_path::{Path, PathBuf};
1453 ///
1454 /// let mut p = PathBuf::from("/spirited/away.rs");
1455 ///
1456 /// p.pop();
1457 /// assert_eq!(Path::new("/spirited"), p);
1458 /// p.pop();
1459 /// assert_eq!(Path::new("/"), p);
1460 /// ```
1461 #[inline]
1462 pub fn pop(&mut self) -> bool {
1463 self.inner.pop()
1464 }
1465
1466 /// Consumes the [`PathBuf`], returning its internal [`OsString`] storage.
1467 ///
1468 /// # Examples
1469 ///
1470 /// ```
1471 /// use nu_path::PathBuf;
1472 ///
1473 /// let p = PathBuf::from("/the/head");
1474 /// let os_str = p.into_os_string();
1475 /// ```
1476 #[inline]
1477 pub fn into_os_string(self) -> OsString {
1478 self.inner.into_os_string()
1479 }
1480
1481 /// Converts this [`PathBuf`] into a [boxed](Box) [`Path`].
1482 #[inline]
1483 pub fn into_boxed_path(self) -> Box<Path<Form>> {
1484 std_box_to_box(self.inner.into_boxed_path())
1485 }
1486
1487 /// Returns the [`capacity`](OsString::capacity) of the underlying [`OsString`].
1488 #[must_use]
1489 #[inline]
1490 pub fn capacity(&self) -> usize {
1491 self.inner.capacity()
1492 }
1493
1494 /// Invokes [`reserve`](OsString::reserve) on the underlying [`OsString`].
1495 #[inline]
1496 pub fn reserve(&mut self, additional: usize) {
1497 self.inner.reserve(additional)
1498 }
1499
1500 /// Invokes [`try_reserve`](OsString::try_reserve) on the underlying [`OsString`].
1501 #[inline]
1502 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
1503 self.inner.try_reserve(additional)
1504 }
1505
1506 /// Invokes [`reserve_exact`](OsString::reserve_exact) on the underlying [`OsString`].
1507 #[inline]
1508 pub fn reserve_exact(&mut self, additional: usize) {
1509 self.inner.reserve_exact(additional)
1510 }
1511
1512 /// Invokes [`try_reserve_exact`](OsString::try_reserve_exact) on the underlying [`OsString`].
1513 #[inline]
1514 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
1515 self.inner.try_reserve_exact(additional)
1516 }
1517
1518 /// Invokes [`shrink_to_fit`](OsString::shrink_to_fit) on the underlying [`OsString`].
1519 #[inline]
1520 pub fn shrink_to_fit(&mut self) {
1521 self.inner.shrink_to_fit()
1522 }
1523
1524 /// Invokes [`shrink_to`](OsString::shrink_to) on the underlying [`OsString`].
1525 #[inline]
1526 pub fn shrink_to(&mut self, min_capacity: usize) {
1527 self.inner.shrink_to(min_capacity)
1528 }
1529
1530 /// Consumes a [`PathBuf`], returning it with a different form.
1531 ///
1532 /// [`PathForm`]s can be converted to one another based on [`PathCast`] implementations.
1533 /// Namely, the following form conversions are possible:
1534 /// - [`Relative`], [`Absolute`], or [`Canonical`] into [`Any`].
1535 /// - [`Canonical`] into [`Absolute`].
1536 /// - Any form into itself.
1537 ///
1538 /// # Examples
1539 ///
1540 /// ```
1541 /// use nu_path::{PathBuf, RelativePathBuf};
1542 ///
1543 /// let p = RelativePathBuf::try_from("test.txt").unwrap();
1544 /// let p: PathBuf = p.cast_into();
1545 /// assert_eq!(PathBuf::from("test.txt"), p);
1546 /// ```
1547 #[inline]
1548 pub fn cast_into<To>(self) -> PathBuf<To>
1549 where
1550 To: PathForm,
1551 Form: PathCast<To>,
1552 {
1553 PathBuf::new_unchecked(self.inner)
1554 }
1555
1556 /// Consumes a [`PathBuf`], returning it with form [`Any`].
1557 ///
1558 /// # Examples
1559 ///
1560 /// ```
1561 /// use nu_path::{PathBuf, RelativePathBuf};
1562 ///
1563 /// let p = RelativePathBuf::try_from("test.txt").unwrap();
1564 /// assert_eq!(PathBuf::from("test.txt"), p.into_any());
1565 /// ```
1566 #[inline]
1567 pub fn into_any(self) -> PathBuf {
1568 PathBuf::new_unchecked(self.inner)
1569 }
1570}
1571
1572impl PathBuf {
1573 /// Creates an empty [`PathBuf`].
1574 ///
1575 /// # Examples
1576 ///
1577 /// ```
1578 /// use nu_path::PathBuf;
1579 ///
1580 /// let path = PathBuf::new();
1581 /// ```
1582 #[must_use]
1583 #[inline]
1584 pub fn new() -> Self {
1585 Self::new_unchecked(std::path::PathBuf::new())
1586 }
1587
1588 /// Creates a new [`PathBuf`] with a given capacity used to create the internal [`OsString`].
1589 /// See [`with_capacity`](OsString::with_capacity) defined on [`OsString`].
1590 ///
1591 /// # Examples
1592 ///
1593 /// ```
1594 /// use nu_path::PathBuf;
1595 ///
1596 /// let mut path = PathBuf::with_capacity(10);
1597 /// let capacity = path.capacity();
1598 ///
1599 /// // This push is done without reallocating
1600 /// path.push(r"C:\");
1601 ///
1602 /// assert_eq!(capacity, path.capacity());
1603 /// ```
1604 #[inline]
1605 #[must_use]
1606 pub fn with_capacity(capacity: usize) -> Self {
1607 Self::new_unchecked(std::path::PathBuf::with_capacity(capacity))
1608 }
1609
1610 /// Returns a mutable reference to the underlying [`OsString`].
1611 ///
1612 /// # Examples
1613 ///
1614 /// ```
1615 /// use nu_path::{Path, PathBuf};
1616 ///
1617 /// let mut path = PathBuf::from("/foo");
1618 ///
1619 /// path.push("bar");
1620 /// assert_eq!(path, Path::new("/foo/bar"));
1621 ///
1622 /// // OsString's `push` does not add a separator.
1623 /// path.as_mut_os_string().push("baz");
1624 /// assert_eq!(path, Path::new("/foo/barbaz"));
1625 /// ```
1626 #[must_use]
1627 #[inline]
1628 pub fn as_mut_os_string(&mut self) -> &mut OsString {
1629 self.inner.as_mut_os_string()
1630 }
1631
1632 /// Invokes [`clear`](OsString::clear) on the underlying [`OsString`].
1633 #[inline]
1634 pub fn clear(&mut self) {
1635 self.inner.clear()
1636 }
1637
1638 /// Consumes a [`PathBuf`], returning an `Ok` [`RelativePathBuf`] if the [`PathBuf`]
1639 /// is relative. Otherwise, returns the original [`PathBuf`] as an `Err`.
1640 ///
1641 /// # Examples
1642 ///
1643 /// ```
1644 /// use nu_path::PathBuf;
1645 ///
1646 /// assert!(PathBuf::from("test.txt").try_into_relative().is_ok());
1647 /// ```
1648 #[inline]
1649 pub fn try_into_relative(self) -> Result<RelativePathBuf, Self> {
1650 if self.inner.is_relative() {
1651 Ok(PathBuf::new_unchecked(self.inner))
1652 } else {
1653 Err(self)
1654 }
1655 }
1656
1657 /// Consumes a [`PathBuf`], returning an `Ok` [`AbsolutePathBuf`] if the [`PathBuf`]
1658 /// is absolute. Otherwise, returns the original [`PathBuf`] as an `Err`.
1659 ///
1660 /// # Examples
1661 ///
1662 /// ```
1663 /// use nu_path::PathBuf;
1664 ///
1665 /// assert!(PathBuf::from("test.txt").try_into_absolute().is_err());
1666 /// ```
1667 #[inline]
1668 pub fn try_into_absolute(self) -> Result<AbsolutePathBuf, Self> {
1669 if self.inner.is_absolute() {
1670 Ok(PathBuf::new_unchecked(self.inner))
1671 } else {
1672 Err(self)
1673 }
1674 }
1675}
1676
1677impl<Form: PathPush> PathBuf<Form> {
1678 /// Extends `self` with `path`.
1679 ///
1680 /// If `path` is absolute, it replaces the current path.
1681 ///
1682 /// On Windows:
1683 ///
1684 /// * if `path` has a root but no prefix (e.g., `\windows`), it
1685 /// replaces everything except for the prefix (if any) of `self`.
1686 /// * if `path` has a prefix but no root, it replaces `self`.
1687 /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`)
1688 /// and `path` is not empty, the new path is normalized: all references
1689 /// to `.` and `..` are removed.
1690 ///
1691 /// Consider using [`Path::join`] if you need a new [`PathBuf`] instead of
1692 /// using this function on a cloned [`PathBuf`].
1693 ///
1694 /// # Examples
1695 ///
1696 /// Pushing a relative path extends the existing path:
1697 ///
1698 /// ```
1699 /// use nu_path::PathBuf;
1700 ///
1701 /// let mut path = PathBuf::from("/tmp");
1702 /// path.push("file.bk");
1703 /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
1704 /// ```
1705 ///
1706 /// Pushing an absolute path replaces the existing path:
1707 ///
1708 /// ```
1709 /// use nu_path::PathBuf;
1710 ///
1711 /// let mut path = PathBuf::from("/tmp");
1712 /// path.push("/etc");
1713 /// assert_eq!(path, PathBuf::from("/etc"));
1714 /// ```
1715 #[inline]
1716 pub fn push(&mut self, path: impl AsRef<Path>) {
1717 self.inner.push(&path.as_ref().inner)
1718 }
1719}
1720
1721impl<Form: PathSet> PathBuf<Form> {
1722 /// Updates [`self.file_name`](Path::file_name) to `file_name`.
1723 ///
1724 /// If [`self.file_name`](Path::file_name) was [`None`],
1725 /// this is equivalent to pushing `file_name`.
1726 ///
1727 /// Otherwise it is equivalent to calling [`pop`](PathBuf::pop) and then pushing `file_name`.
1728 /// The new path will be a sibling of the original path.
1729 /// (That is, it will have the same parent.)
1730 ///
1731 /// # Examples
1732 ///
1733 /// ```
1734 /// use nu_path::PathBuf;
1735 ///
1736 /// let mut buf = PathBuf::from("/");
1737 /// assert!(buf.file_name() == None);
1738 ///
1739 /// buf.set_file_name("foo.txt");
1740 /// assert!(buf == PathBuf::from("/foo.txt"));
1741 /// assert!(buf.file_name().is_some());
1742 ///
1743 /// buf.set_file_name("bar.txt");
1744 /// assert!(buf == PathBuf::from("/bar.txt"));
1745 ///
1746 /// buf.set_file_name("baz");
1747 /// assert!(buf == PathBuf::from("/baz"));
1748 /// ```
1749 #[inline]
1750 pub fn set_file_name(&mut self, file_name: impl AsRef<OsStr>) {
1751 self.inner.set_file_name(file_name)
1752 }
1753
1754 /// Updates [`self.extension`](Path::extension) to `Some(extension)` or to [`None`] if
1755 /// `extension` is empty.
1756 ///
1757 /// Returns `false` and does nothing if [`self.file_name`](Path::file_name) is [`None`],
1758 /// returns `true` and updates the extension otherwise.
1759 ///
1760 /// If [`self.extension`](Path::extension) is [`None`], the extension is added; otherwise
1761 /// it is replaced.
1762 ///
1763 /// If `extension` is the empty string, [`self.extension`](Path::extension) will be [`None`]
1764 /// afterwards, not `Some("")`.
1765 ///
1766 /// # Caveats
1767 ///
1768 /// The new `extension` may contain dots and will be used in its entirety,
1769 /// but only the part after the final dot will be reflected in
1770 /// [`self.extension`](Path::extension).
1771 ///
1772 /// If the file stem contains internal dots and `extension` is empty, part of the
1773 /// old file stem will be considered the new [`self.extension`](Path::extension).
1774 ///
1775 /// # Examples
1776 ///
1777 /// ```
1778 /// use nu_path::{Path, PathBuf};
1779 ///
1780 /// let mut p = PathBuf::from("/feel/the");
1781 ///
1782 /// p.set_extension("force");
1783 /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
1784 ///
1785 /// p.set_extension("dark.side");
1786 /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path());
1787 ///
1788 /// p.set_extension("cookie");
1789 /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path());
1790 ///
1791 /// p.set_extension("");
1792 /// assert_eq!(Path::new("/feel/the.dark"), p.as_path());
1793 ///
1794 /// p.set_extension("");
1795 /// assert_eq!(Path::new("/feel/the"), p.as_path());
1796 ///
1797 /// p.set_extension("");
1798 /// assert_eq!(Path::new("/feel/the"), p.as_path());
1799 /// ```
1800 #[inline]
1801 pub fn set_extension(&mut self, extension: impl AsRef<OsStr>) -> bool {
1802 self.inner.set_extension(extension)
1803 }
1804}
1805
1806impl<Form: MaybeRelative> PathBuf<Form> {
1807 /// Consumes a [`PathBuf`] and returns the, potentially relative,
1808 /// underlying [`std::path::PathBuf`].
1809 ///
1810 /// # Note
1811 ///
1812 /// Caution should be taken when using this function. Nushell keeps track of an emulated current
1813 /// working directory, and using the [`std::path::PathBuf`] returned from this method
1814 /// will likely use [`std::env::current_dir`] to resolve the path instead of
1815 /// using the emulated current working directory.
1816 ///
1817 /// Instead, you should probably join this path onto the emulated current working directory.
1818 /// Any [`AbsolutePath`] or [`CanonicalPath`] will also suffice.
1819 ///
1820 /// # Examples
1821 ///
1822 /// ```
1823 /// use nu_path::PathBuf;
1824 ///
1825 /// let p = PathBuf::from("test.txt");
1826 /// assert_eq!(std::path::PathBuf::from("test.txt"), p.into_relative_std_path_buf());
1827 /// ```
1828 #[inline]
1829 pub fn into_relative_std_path_buf(self) -> std::path::PathBuf {
1830 self.inner
1831 }
1832}
1833
1834impl<Form: IsAbsolute> PathBuf<Form> {
1835 /// Consumes a [`PathBuf`] and returns the underlying [`std::path::PathBuf`].
1836 ///
1837 /// # Examples
1838 ///
1839 #[cfg_attr(not(windows), doc = "```")]
1840 #[cfg_attr(windows, doc = "```no_run")]
1841 /// use nu_path::AbsolutePathBuf;
1842 ///
1843 /// let p = AbsolutePathBuf::try_from("/test").unwrap();
1844 /// assert_eq!(std::path::PathBuf::from("/test"), p.into_std_path_buf());
1845 /// ```
1846 #[inline]
1847 pub fn into_std_path_buf(self) -> std::path::PathBuf {
1848 self.inner
1849 }
1850}
1851
1852impl CanonicalPathBuf {
1853 /// Consumes a [`CanonicalPathBuf`] and returns an [`AbsolutePathBuf`].
1854 ///
1855 /// # Examples
1856 ///
1857 /// ```no_run
1858 /// use nu_path::AbsolutePathBuf;
1859 ///
1860 /// let absolute = AbsolutePathBuf::try_from("/test").unwrap();
1861 /// let p = absolute.canonicalize().unwrap();
1862 /// assert_eq!(absolute, p.into_absolute());
1863 /// ```
1864 #[inline]
1865 pub fn into_absolute(self) -> AbsolutePathBuf {
1866 self.cast_into()
1867 }
1868}
1869
1870impl Default for PathBuf {
1871 #[inline]
1872 fn default() -> Self {
1873 Self::new()
1874 }
1875}
1876
1877impl<Form: PathForm> Clone for PathBuf<Form> {
1878 #[inline]
1879 fn clone(&self) -> Self {
1880 Self {
1881 _form: PhantomData,
1882 inner: self.inner.clone(),
1883 }
1884 }
1885}
1886
1887impl<Form: PathForm> fmt::Debug for PathBuf<Form> {
1888 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1889 fmt::Debug::fmt(&**self, f)
1890 }
1891}
1892
1893impl<Form: PathForm> Deref for PathBuf<Form> {
1894 type Target = Path<Form>;
1895
1896 #[inline]
1897 fn deref(&self) -> &Self::Target {
1898 self.as_path()
1899 }
1900}
1901
1902impl DerefMut for PathBuf {
1903 #[inline]
1904 fn deref_mut(&mut self) -> &mut Self::Target {
1905 #[ref_cast_custom]
1906 fn ref_cast<Form: PathForm>(path: &mut std::path::Path) -> &mut Path<Form>;
1907
1908 ref_cast(&mut self.inner)
1909 }
1910}
1911
1912impl<From: PathCast<To>, To: PathForm> Borrow<Path<To>> for PathBuf<From> {
1913 #[inline]
1914 fn borrow(&self) -> &Path<To> {
1915 self.cast()
1916 }
1917}
1918
1919impl<Form: IsAbsolute> Borrow<std::path::Path> for PathBuf<Form> {
1920 #[inline]
1921 fn borrow(&self) -> &std::path::Path {
1922 self.as_ref()
1923 }
1924}
1925
1926impl Borrow<Path> for std::path::PathBuf {
1927 #[inline]
1928 fn borrow(&self) -> &Path {
1929 self.as_ref()
1930 }
1931}
1932
1933impl FromStr for PathBuf {
1934 type Err = Infallible;
1935
1936 #[inline]
1937 fn from_str(s: &str) -> Result<Self, Self::Err> {
1938 Ok(s.into())
1939 }
1940}
1941
1942impl FromStr for RelativePathBuf {
1943 type Err = TryRelativeError;
1944
1945 #[inline]
1946 fn from_str(s: &str) -> Result<Self, Self::Err> {
1947 s.try_into()
1948 }
1949}
1950
1951impl FromStr for AbsolutePathBuf {
1952 type Err = TryAbsoluteError;
1953
1954 #[inline]
1955 fn from_str(s: &str) -> Result<Self, Self::Err> {
1956 s.try_into()
1957 }
1958}
1959
1960impl<P: AsRef<Path>> Extend<P> for PathBuf {
1961 fn extend<T: IntoIterator<Item = P>>(&mut self, iter: T) {
1962 for path in iter {
1963 self.push(path);
1964 }
1965 }
1966}
1967
1968impl<P: AsRef<Path>> FromIterator<P> for PathBuf {
1969 fn from_iter<T: IntoIterator<Item = P>>(iter: T) -> Self {
1970 let mut buf = Self::new_unchecked(std::path::PathBuf::new());
1971 buf.extend(iter);
1972 buf
1973 }
1974}
1975
1976impl<'a, Form: PathForm> IntoIterator for &'a PathBuf<Form> {
1977 type Item = &'a OsStr;
1978
1979 type IntoIter = std::path::Iter<'a>;
1980
1981 #[inline]
1982 fn into_iter(self) -> Self::IntoIter {
1983 self.iter()
1984 }
1985}
1986
1987#[inline]
1988fn box_to_box_unchecked<From: PathForm, To: PathForm>(path: Box<Path<From>>) -> Box<Path<To>> {
1989 // Safety: `Path<From>` and `Path<To>` differ only by PhantomData tag.
1990 let ptr = Box::into_raw(path) as *mut Path<To>;
1991 unsafe { Box::from_raw(ptr) }
1992}
1993
1994#[inline]
1995fn std_box_to_box<Form: PathForm>(path: Box<std::path::Path>) -> Box<Path<Form>> {
1996 // Safety: `Path<From>` is a repr(transparent) wrapper around `std::path::Path`.
1997 let ptr = Box::into_raw(path) as *mut Path<Form>;
1998 unsafe { Box::from_raw(ptr) }
1999}
2000
2001#[inline]
2002fn std_arc_to_arc<Form: PathForm>(path: Arc<std::path::Path>) -> Arc<Path<Form>> {
2003 // Safety: `Path<From>` is a repr(transparent) wrapper around `std::path::Path`.
2004 let ptr = Arc::into_raw(path) as *mut Path<Form>;
2005 unsafe { Arc::from_raw(ptr) }
2006}
2007
2008#[inline]
2009fn std_rc_to_rc<Form: PathForm>(path: Rc<std::path::Path>) -> Rc<Path<Form>> {
2010 // Safety: `Path<From>` is a repr(transparent) wrapper around `std::path::Path`.
2011 let ptr = Rc::into_raw(path) as *mut Path<Form>;
2012 unsafe { Rc::from_raw(ptr) }
2013}
2014
2015/*
2016================================================================================
2017 AsRef
2018================================================================================
2019*/
2020
2021// Here we match all `AsRef` implementations on `std::path::Path` and `std::path::PathBuf`,
2022// adding casting variations where possible.
2023
2024macro_rules! impl_as_ref {
2025 ([$($from:ty),* $(,)?] => $to:ty |$self:ident| $cast:block) => {
2026 $(
2027 impl AsRef<$to> for $from {
2028 #[inline]
2029 fn as_ref(&$self) -> &$to $cast
2030 }
2031 )*
2032 };
2033}
2034
2035// === To and from crate types ===
2036
2037impl<From: PathCast<To>, To: PathForm> AsRef<Path<To>> for Path<From> {
2038 #[inline]
2039 fn as_ref(&self) -> &Path<To> {
2040 self.cast()
2041 }
2042}
2043
2044impl<From: PathCast<To>, To: PathForm> AsRef<Path<To>> for PathBuf<From> {
2045 #[inline]
2046 fn as_ref(&self) -> &Path<To> {
2047 self.cast()
2048 }
2049}
2050
2051impl_as_ref!(
2052 [
2053 Box<RelativePath>, Box<AbsolutePath>, Box<CanonicalPath>,
2054 Cow<'_, RelativePath>, Cow<'_, AbsolutePath>, Cow<'_, CanonicalPath>,
2055 Rc<RelativePath>, Rc<AbsolutePath>, Rc<CanonicalPath>,
2056 Arc<RelativePath>, Arc<AbsolutePath>, Arc<CanonicalPath>,
2057 ]
2058 => Path |self| { self.cast() }
2059);
2060
2061impl_as_ref!(
2062 [Box<CanonicalPath>, Cow<'_, CanonicalPath>, Rc<CanonicalPath>, Arc<CanonicalPath>]
2063 => AbsolutePath |self| { self.cast() }
2064);
2065
2066// === To and from std::path types ===
2067
2068impl<Form: IsAbsolute> AsRef<std::path::Path> for Path<Form> {
2069 #[inline]
2070 fn as_ref(&self) -> &std::path::Path {
2071 self.as_std_path()
2072 }
2073}
2074
2075impl<Form: IsAbsolute> AsRef<std::path::Path> for PathBuf<Form> {
2076 #[inline]
2077 fn as_ref(&self) -> &std::path::Path {
2078 self.as_std_path()
2079 }
2080}
2081
2082impl_as_ref!(
2083 [std::path::Path, std::path::PathBuf, std::path::Component<'_>]
2084 => Path |self| { Path::new(self) }
2085);
2086
2087impl_as_ref!(
2088 [Box<std::path::Path>, Cow<'_, std::path::Path>, Rc<std::path::Path>, Arc<std::path::Path>]
2089 => Path |self| { Path::new(self.as_os_str()) }
2090);
2091
2092// === To and from string types ===
2093
2094impl<Form: PathForm> AsRef<OsStr> for Path<Form> {
2095 #[inline]
2096 fn as_ref(&self) -> &OsStr {
2097 self.as_os_str()
2098 }
2099}
2100
2101impl<Form: PathForm> AsRef<OsStr> for PathBuf<Form> {
2102 #[inline]
2103 fn as_ref(&self) -> &OsStr {
2104 self.as_os_str()
2105 }
2106}
2107
2108impl_as_ref!([OsStr, OsString, Cow<'_, OsStr>, str, String] => Path |self| { Path::new(self) });
2109
2110/*
2111================================================================================
2112 From
2113================================================================================
2114*/
2115
2116// Here we match all `From` implementations on `std::path::Path` and `std::path::PathBuf`,
2117// adding casting variations where possible.
2118
2119macro_rules! impl_from {
2120 ([$($from:ty),* $(,)?] => $to:ty |$value:ident| $convert:block) => {
2121 $(
2122 impl From<$from> for $to {
2123 #[inline]
2124 fn from($value: $from) -> Self $convert
2125 }
2126 )*
2127 };
2128 (<$form:ident> $from:ty => $to:ty |$value:ident| $convert:block) => {
2129 impl<$form: PathForm> From<$from> for $to {
2130 #[inline]
2131 fn from($value: $from) -> Self $convert
2132 }
2133 };
2134}
2135
2136macro_rules! impl_into_std {
2137 (<$form:ident> $from:ty => [$($to:ty),* $(,)?] |$value:ident| $convert:block) => {
2138 $(
2139 impl<$form: IsAbsolute> From<$from> for $to {
2140 #[inline]
2141 fn from($value: $from) -> Self $convert
2142 }
2143 )*
2144 };
2145}
2146
2147// ===== Owned to Owned =====
2148
2149// === To and from crate types ===
2150
2151impl_from!([RelativePathBuf, AbsolutePathBuf, CanonicalPathBuf] => PathBuf
2152 |buf| { buf.cast_into() }
2153);
2154impl_from!([CanonicalPathBuf] => AbsolutePathBuf |buf| { buf.cast_into() });
2155
2156#[inline]
2157fn box_to_box<From: PathCast<To>, To: PathForm>(path: Box<Path<From>>) -> Box<Path<To>> {
2158 box_to_box_unchecked(path)
2159}
2160impl_from!([Box<RelativePath>, Box<AbsolutePath>, Box<CanonicalPath>] => Box<Path>
2161 |path| { box_to_box(path) }
2162);
2163impl_from!([Box<CanonicalPath>] => Box<AbsolutePath> |path| { box_to_box(path) });
2164
2165impl_from!(<Form> PathBuf<Form> => Box<Path<Form>> |buf| { buf.into_boxed_path() });
2166impl_from!([RelativePathBuf, AbsolutePathBuf, CanonicalPathBuf] => Box<Path>
2167 |buf| { buf.into_boxed_path().into() }
2168);
2169impl_from!([CanonicalPathBuf] => Box<AbsolutePath> |buf| { buf.into_boxed_path().into() });
2170
2171impl_from!(<Form> Box<Path<Form>> => PathBuf<Form> |path| { path.into_path_buf() });
2172impl_from!([Box<RelativePath>, Box<AbsolutePath>, Box<CanonicalPath>] => PathBuf
2173 |path| { path.into_path_buf().into() }
2174);
2175impl_from!([Box<CanonicalPath>] => AbsolutePathBuf |path| { path.into_path_buf().into() });
2176
2177impl_from!(<Form> PathBuf<Form> => Cow<'_, Path<Form>> |buf| { Self::Owned(buf) });
2178impl_from!([RelativePathBuf, AbsolutePathBuf, CanonicalPathBuf] => Cow<'_, Path>
2179 |buf| { Self::Owned(buf.into()) }
2180);
2181impl_from!([CanonicalPathBuf] => Cow<'_, AbsolutePath> |buf| { Self::Owned(buf.into()) });
2182
2183impl_from!(<Form> Cow<'_, Path<Form>> => PathBuf<Form> |cow| { cow.into_owned() });
2184impl_from!([Cow<'_, RelativePath>, Cow<'_, AbsolutePath>, Cow<'_, CanonicalPath>] => PathBuf
2185 |cow| { cow.into_owned().into() }
2186);
2187impl_from!([Cow<'_, CanonicalPath>] => AbsolutePathBuf |cow| { cow.into_owned().into() });
2188
2189#[inline]
2190fn cow_to_box<From, To>(cow: Cow<'_, From>) -> Box<To>
2191where
2192 From: ?Sized + ToOwned,
2193 for<'a> &'a From: Into<Box<To>>,
2194 From::Owned: Into<Box<To>>,
2195 To: ?Sized,
2196{
2197 match cow {
2198 Cow::Borrowed(path) => path.into(),
2199 Cow::Owned(path) => path.into(),
2200 }
2201}
2202impl_from!(<Form> Cow<'_, Path<Form>> => Box<Path<Form>> |cow| { cow_to_box(cow) });
2203impl_from!([Cow<'_, RelativePath>, Cow<'_, AbsolutePath>, Cow<'_, CanonicalPath>] => Box<Path>
2204 |cow| { cow_to_box(cow) }
2205);
2206impl_from!([Cow<'_, CanonicalPath>] => Box<AbsolutePath> |cow| { cow_to_box(cow) });
2207
2208#[inline]
2209fn buf_to_arc<From: PathCast<To>, To: PathForm>(buf: PathBuf<From>) -> Arc<Path<To>> {
2210 std_arc_to_arc(buf.inner.into())
2211}
2212impl_from!(<Form> PathBuf<Form> => Arc<Path<Form>> |buf| { buf_to_arc(buf) });
2213impl_from!([RelativePathBuf, AbsolutePathBuf, CanonicalPathBuf] => Arc<Path>
2214 |buf| { buf_to_arc(buf) }
2215);
2216impl_from!([CanonicalPathBuf] => Arc<AbsolutePath> |buf| { buf_to_arc(buf) });
2217
2218#[inline]
2219fn buf_to_rc<From: PathCast<To>, To: PathForm>(buf: PathBuf<From>) -> Rc<Path<To>> {
2220 std_rc_to_rc(buf.inner.into())
2221}
2222impl_from!(<Form> PathBuf<Form> => Rc<Path<Form>> |buf| { buf_to_rc(buf) });
2223impl_from!([RelativePathBuf, AbsolutePathBuf, CanonicalPathBuf] => Rc<Path>
2224 |buf| { buf_to_rc(buf) }
2225);
2226impl_from!([CanonicalPathBuf] => Rc<AbsolutePath> |buf| { buf_to_rc(buf) });
2227
2228// === To and from std::path types ===
2229
2230impl_into_std!(<Form> PathBuf<Form> => [std::path::PathBuf] |buf| { buf.inner });
2231impl_into_std!(
2232 <Form> PathBuf<Form> => [
2233 Box<std::path::Path>, Cow<'_, std::path::Path>, Arc<std::path::Path>, Rc<std::path::Path>
2234 ]
2235 |buf| { buf.inner.into() }
2236);
2237impl_into_std!(<Form> Box<Path<Form>> => [std::path::PathBuf, Box<std::path::Path>]
2238 |path| { path.inner.into() }
2239);
2240
2241impl_from!([std::path::PathBuf] => PathBuf |buf| { Self::new_unchecked(buf) });
2242impl_from!([Box<std::path::Path>] => PathBuf |path| { Self::new_unchecked(path.into()) });
2243impl_from!([Cow<'_, std::path::Path>] => PathBuf |cow| { Self::new_unchecked(cow.into()) });
2244
2245impl From<Box<std::path::Path>> for Box<Path> {
2246 #[inline]
2247 fn from(path: Box<std::path::Path>) -> Self {
2248 std_box_to_box(path)
2249 }
2250}
2251impl_from!([std::path::PathBuf] => Box<Path> |buf| { buf.into_boxed_path().into() });
2252impl_from!([Cow<'_, std::path::Path>] => Box<Path> |cow| { cow_to_box(cow) });
2253
2254// === To and from string types ===
2255
2256impl_from!(<Form> PathBuf<Form> => OsString |buf| { buf.inner.into() });
2257impl_from!([OsString, String] => PathBuf |s| { Self::new_unchecked(s.into()) });
2258
2259// ===== Borrowed to Owned =====
2260
2261// === To and from crate types ===
2262// Here we also add casting conversions from `T: impl AsRef<Path<Form>>` to `PathBuf<Form>`.
2263
2264impl<Source: PathCast<To>, To: PathForm> From<&Path<Source>> for Box<Path<To>> {
2265 #[inline]
2266 fn from(path: &Path<Source>) -> Self {
2267 std_box_to_box(path.inner.into())
2268 }
2269}
2270
2271impl<'a, Source: PathCast<To>, To: PathForm> From<&'a Path<Source>> for Cow<'a, Path<To>> {
2272 #[inline]
2273 fn from(path: &'a Path<Source>) -> Self {
2274 path.cast().into()
2275 }
2276}
2277
2278impl<'a, Source: PathCast<To>, To: PathForm> From<&'a PathBuf<Source>> for Cow<'a, Path<To>> {
2279 #[inline]
2280 fn from(buf: &'a PathBuf<Source>) -> Self {
2281 buf.cast().into()
2282 }
2283}
2284
2285impl<Source: PathCast<To>, To: PathForm> From<&Path<Source>> for Arc<Path<To>> {
2286 #[inline]
2287 fn from(path: &Path<Source>) -> Self {
2288 std_arc_to_arc(path.inner.into())
2289 }
2290}
2291
2292impl<Source: PathCast<To>, To: PathForm> From<&Path<Source>> for Rc<Path<To>> {
2293 #[inline]
2294 fn from(path: &Path<Source>) -> Self {
2295 std_rc_to_rc(path.inner.into())
2296 }
2297}
2298
2299impl<T: ?Sized + AsRef<RelativePath>> From<&T> for RelativePathBuf {
2300 #[inline]
2301 fn from(s: &T) -> Self {
2302 Self::new_unchecked(s.as_ref().into())
2303 }
2304}
2305
2306impl<T: ?Sized + AsRef<AbsolutePath>> From<&T> for AbsolutePathBuf {
2307 #[inline]
2308 fn from(s: &T) -> Self {
2309 Self::new_unchecked(s.as_ref().into())
2310 }
2311}
2312
2313impl<T: ?Sized + AsRef<CanonicalPath>> From<&T> for CanonicalPathBuf {
2314 #[inline]
2315 fn from(s: &T) -> Self {
2316 Self::new_unchecked(s.as_ref().into())
2317 }
2318}
2319
2320// === To and from std::path types ===
2321
2322impl_into_std!(
2323 <Form> &Path<Form> => [Box<std::path::Path>, Arc<std::path::Path>, Rc<std::path::Path>]
2324 |path| { path.inner.into() }
2325);
2326
2327impl<'a, Form: IsAbsolute> From<&'a Path<Form>> for Cow<'a, std::path::Path> {
2328 #[inline]
2329 fn from(path: &'a Path<Form>) -> Self {
2330 path.inner.into()
2331 }
2332}
2333
2334impl<'a, Form: IsAbsolute> From<&'a PathBuf<Form>> for Cow<'a, std::path::Path> {
2335 #[inline]
2336 fn from(buf: &'a PathBuf<Form>) -> Self {
2337 Self::Borrowed(buf.as_ref())
2338 }
2339}
2340
2341impl_from!([&std::path::Path] => Box<Path> |path| { Path::new(path).into() });
2342
2343// === To and from string types ===
2344
2345impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
2346 #[inline]
2347 fn from(s: &T) -> Self {
2348 Self::new_unchecked(s.as_ref().into())
2349 }
2350}
2351
2352/*
2353================================================================================
2354 TryFrom
2355================================================================================
2356*/
2357
2358#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2359pub struct TryRelativeError;
2360
2361impl fmt::Display for TryRelativeError {
2362 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2363 write!(fmt, "path was not a relative path")
2364 }
2365}
2366
2367#[derive(Debug, Copy, Clone, PartialEq, Eq)]
2368pub struct TryAbsoluteError;
2369
2370impl fmt::Display for TryAbsoluteError {
2371 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2372 write!(fmt, "path was not an absolute path")
2373 }
2374}
2375
2376// ===== Borrowed to borrowed =====
2377// Here we match all `AsRef` implementations on `std::path::Path`.
2378
2379macro_rules! impl_try_from_borrowed_to_borrowed {
2380 ([$($from:ty),* $(,)?], |$value:ident| $convert:block $(,)?) => {
2381 $(
2382 impl<'a> TryFrom<&'a $from> for &'a RelativePath {
2383 type Error = TryRelativeError;
2384
2385 #[inline]
2386 fn try_from($value: &'a $from) -> Result<Self, Self::Error> $convert
2387 }
2388
2389 impl<'a> TryFrom<&'a $from> for &'a AbsolutePath {
2390 type Error = TryAbsoluteError;
2391
2392 #[inline]
2393 fn try_from($value: &'a $from) -> Result<Self, Self::Error> $convert
2394 }
2395 )*
2396 };
2397}
2398
2399// === From crate types ===
2400
2401impl<'a> TryFrom<&'a Path> for &'a RelativePath {
2402 type Error = TryRelativeError;
2403
2404 #[inline]
2405 fn try_from(path: &'a Path) -> Result<Self, Self::Error> {
2406 path.try_relative().map_err(|_| TryRelativeError)
2407 }
2408}
2409
2410impl<'a> TryFrom<&'a Path> for &'a AbsolutePath {
2411 type Error = TryAbsoluteError;
2412
2413 #[inline]
2414 fn try_from(path: &'a Path) -> Result<Self, Self::Error> {
2415 path.try_absolute().map_err(|_| TryAbsoluteError)
2416 }
2417}
2418
2419impl_try_from_borrowed_to_borrowed!([PathBuf], |buf| { Path::new(buf).try_into() });
2420
2421// === From std::path types ===
2422
2423impl_try_from_borrowed_to_borrowed!([std::path::Path], |path| { Path::new(path).try_into() });
2424impl_try_from_borrowed_to_borrowed!([std::path::PathBuf], |buf| { Path::new(buf).try_into() });
2425impl_try_from_borrowed_to_borrowed!([std::path::Component<'_>], |component| {
2426 Path::new(component).try_into()
2427});
2428impl_try_from_borrowed_to_borrowed!([std::path::Components<'_>], |components| {
2429 Path::new(components).try_into()
2430});
2431impl_try_from_borrowed_to_borrowed!([std::path::Iter<'_>], |iter| { Path::new(iter).try_into() });
2432
2433// === From string types ===
2434
2435impl_try_from_borrowed_to_borrowed!(
2436 [OsStr, OsString, Cow<'_, OsStr>, str, String],
2437 |s| { Path::new(s).try_into() },
2438);
2439
2440// ===== Borrowed to Owned =====
2441// Here we match all `From<&T>` implementations on `std::path::Path` and `std::path::PathBuf`.
2442// Note that to match `From<&T: AsRef<OsStr>>` on `std::path::PathBuf`,
2443// we add string conversions and a few others.
2444
2445macro_rules! impl_try_from_borrowed_to_owned {
2446 ([$($from:ty),* $(,)?] => $rel:ty, $abs:ty $(,)?) => {
2447 $(
2448 impl TryFrom<&$from> for $rel {
2449 type Error = TryRelativeError;
2450
2451 #[inline]
2452 fn try_from(path: &$from) -> Result<Self, Self::Error> {
2453 let path: &RelativePath = path.try_into()?;
2454 Ok(path.into())
2455 }
2456 }
2457
2458 impl TryFrom<&$from> for $abs {
2459 type Error = TryAbsoluteError;
2460
2461 #[inline]
2462 fn try_from(path: &$from) -> Result<Self, Self::Error> {
2463 let path: &AbsolutePath = path.try_into()?;
2464 Ok(path.into())
2465 }
2466 }
2467 )*
2468 };
2469 (<$life:lifetime> $from:ty => $rel:ty, $abs:ty $(,)?) => {
2470 impl<$life> TryFrom<&$life $from> for $rel {
2471 type Error = TryRelativeError;
2472
2473 #[inline]
2474 fn try_from(path: &$life $from) -> Result<Self, Self::Error> {
2475 let path: &RelativePath = path.try_into()?;
2476 Ok(path.into())
2477 }
2478 }
2479
2480 impl<$life> TryFrom<&$life $from> for $abs {
2481 type Error = TryAbsoluteError;
2482
2483 #[inline]
2484 fn try_from(path: &$life $from) -> Result<Self, Self::Error> {
2485 let path: &AbsolutePath = path.try_into()?;
2486 Ok(path.into())
2487 }
2488 }
2489 };
2490}
2491
2492// === From crate types ===
2493
2494impl_try_from_borrowed_to_owned!([Path] => Box<RelativePath>, Box<AbsolutePath>);
2495impl_try_from_borrowed_to_owned!(<'a> Path => Cow<'a, RelativePath>, Cow<'a, AbsolutePath>);
2496impl_try_from_borrowed_to_owned!([Path] => Arc<RelativePath>, Arc<AbsolutePath>);
2497impl_try_from_borrowed_to_owned!([Path] => Rc<RelativePath>, Rc<AbsolutePath>);
2498
2499impl_try_from_borrowed_to_owned!([Path, PathBuf] => RelativePathBuf, AbsolutePathBuf);
2500impl_try_from_borrowed_to_owned!(<'a> PathBuf => Cow<'a, RelativePath>, Cow<'a, AbsolutePath>);
2501
2502// === From std::path types ===
2503
2504impl_try_from_borrowed_to_owned!([std::path::Path] => Box<RelativePath>, Box<AbsolutePath>);
2505
2506impl_try_from_borrowed_to_owned!(
2507 [std::path::Path, std::path::PathBuf, std::path::Component<'_>]
2508 => RelativePathBuf, AbsolutePathBuf
2509);
2510
2511// === From string types ===
2512
2513impl_try_from_borrowed_to_owned!(
2514 [OsStr, OsString, Cow<'_, OsStr>, str, String] => RelativePathBuf, AbsolutePathBuf
2515);
2516
2517// ===== Owned to Owned =====
2518// Here we match all `From<T>` implementations on `std::path::Path` and `std::path::PathBuf`
2519// where `T` is an owned type.
2520
2521// === From crate types ===
2522
2523impl TryFrom<PathBuf> for RelativePathBuf {
2524 type Error = PathBuf;
2525
2526 #[inline]
2527 fn try_from(buf: PathBuf) -> Result<Self, Self::Error> {
2528 buf.try_into_relative()
2529 }
2530}
2531
2532impl TryFrom<PathBuf> for AbsolutePathBuf {
2533 type Error = PathBuf;
2534
2535 #[inline]
2536 fn try_from(buf: PathBuf) -> Result<Self, Self::Error> {
2537 buf.try_into_absolute()
2538 }
2539}
2540
2541impl TryFrom<Box<Path>> for RelativePathBuf {
2542 type Error = Box<Path>;
2543
2544 #[inline]
2545 fn try_from(path: Box<Path>) -> Result<Self, Self::Error> {
2546 if path.is_relative() {
2547 Ok(Self::new_unchecked(path.inner.into()))
2548 } else {
2549 Err(path)
2550 }
2551 }
2552}
2553
2554impl TryFrom<Box<Path>> for AbsolutePathBuf {
2555 type Error = Box<Path>;
2556
2557 #[inline]
2558 fn try_from(path: Box<Path>) -> Result<Self, Self::Error> {
2559 if path.is_absolute() {
2560 Ok(Self::new_unchecked(path.inner.into()))
2561 } else {
2562 Err(path)
2563 }
2564 }
2565}
2566
2567impl TryFrom<Box<Path>> for Box<RelativePath> {
2568 type Error = Box<Path>;
2569
2570 #[inline]
2571 fn try_from(path: Box<Path>) -> Result<Self, Self::Error> {
2572 if path.is_relative() {
2573 Ok(box_to_box_unchecked(path))
2574 } else {
2575 Err(path)
2576 }
2577 }
2578}
2579
2580impl TryFrom<Box<Path>> for Box<AbsolutePath> {
2581 type Error = Box<Path>;
2582
2583 #[inline]
2584 fn try_from(path: Box<Path>) -> Result<Self, Self::Error> {
2585 if path.is_absolute() {
2586 Ok(box_to_box_unchecked(path))
2587 } else {
2588 Err(path)
2589 }
2590 }
2591}
2592
2593impl TryFrom<PathBuf> for Box<RelativePath> {
2594 type Error = PathBuf;
2595
2596 #[inline]
2597 fn try_from(buf: PathBuf) -> Result<Self, Self::Error> {
2598 RelativePathBuf::try_from(buf).map(Into::into)
2599 }
2600}
2601
2602impl TryFrom<PathBuf> for Box<AbsolutePath> {
2603 type Error = PathBuf;
2604
2605 #[inline]
2606 fn try_from(buf: PathBuf) -> Result<Self, Self::Error> {
2607 AbsolutePathBuf::try_from(buf).map(Into::into)
2608 }
2609}
2610
2611impl<'a> TryFrom<Cow<'a, Path>> for RelativePathBuf {
2612 type Error = Cow<'a, Path>;
2613
2614 #[inline]
2615 fn try_from(path: Cow<'a, Path>) -> Result<Self, Self::Error> {
2616 match path {
2617 Cow::Borrowed(path) => Self::try_from(path).map_err(|_| Cow::Borrowed(path)),
2618 Cow::Owned(path) => Self::try_from(path).map_err(Cow::Owned),
2619 }
2620 }
2621}
2622
2623impl<'a> TryFrom<Cow<'a, Path>> for AbsolutePathBuf {
2624 type Error = Cow<'a, Path>;
2625
2626 #[inline]
2627 fn try_from(path: Cow<'a, Path>) -> Result<Self, Self::Error> {
2628 match path {
2629 Cow::Borrowed(path) => Self::try_from(path).map_err(|_| Cow::Borrowed(path)),
2630 Cow::Owned(path) => Self::try_from(path).map_err(Cow::Owned),
2631 }
2632 }
2633}
2634
2635impl<'a> TryFrom<Cow<'a, Path>> for Box<RelativePath> {
2636 type Error = Cow<'a, Path>;
2637
2638 #[inline]
2639 fn try_from(path: Cow<'a, Path>) -> Result<Self, Self::Error> {
2640 match path {
2641 Cow::Borrowed(path) => Box::try_from(path).map_err(|_| Cow::Borrowed(path)),
2642 Cow::Owned(path) => Box::try_from(path).map_err(Cow::Owned),
2643 }
2644 }
2645}
2646
2647impl<'a> TryFrom<Cow<'a, Path>> for Box<AbsolutePath> {
2648 type Error = Cow<'a, Path>;
2649
2650 #[inline]
2651 fn try_from(path: Cow<'a, Path>) -> Result<Self, Self::Error> {
2652 match path {
2653 Cow::Borrowed(path) => Box::try_from(path).map_err(|_| Cow::Borrowed(path)),
2654 Cow::Owned(path) => Box::try_from(path).map_err(Cow::Owned),
2655 }
2656 }
2657}
2658
2659// === From std::path types ===
2660
2661impl TryFrom<std::path::PathBuf> for RelativePathBuf {
2662 type Error = std::path::PathBuf;
2663
2664 #[inline]
2665 fn try_from(buf: std::path::PathBuf) -> Result<Self, Self::Error> {
2666 Self::try_from(PathBuf::from(buf)).map_err(|buf| buf.inner)
2667 }
2668}
2669
2670impl TryFrom<std::path::PathBuf> for AbsolutePathBuf {
2671 type Error = std::path::PathBuf;
2672
2673 #[inline]
2674 fn try_from(buf: std::path::PathBuf) -> Result<Self, Self::Error> {
2675 Self::try_from(PathBuf::from(buf)).map_err(|buf| buf.inner)
2676 }
2677}
2678
2679impl TryFrom<Box<std::path::Path>> for RelativePathBuf {
2680 type Error = Box<std::path::Path>;
2681
2682 #[inline]
2683 fn try_from(path: Box<std::path::Path>) -> Result<Self, Self::Error> {
2684 if path.is_relative() {
2685 Ok(Self::new_unchecked(path.into()))
2686 } else {
2687 Err(path)
2688 }
2689 }
2690}
2691
2692impl TryFrom<Box<std::path::Path>> for AbsolutePathBuf {
2693 type Error = Box<std::path::Path>;
2694
2695 #[inline]
2696 fn try_from(path: Box<std::path::Path>) -> Result<Self, Self::Error> {
2697 if path.is_absolute() {
2698 Ok(Self::new_unchecked(path.into()))
2699 } else {
2700 Err(path)
2701 }
2702 }
2703}
2704
2705impl TryFrom<Box<std::path::Path>> for Box<RelativePath> {
2706 type Error = Box<std::path::Path>;
2707
2708 #[inline]
2709 fn try_from(path: Box<std::path::Path>) -> Result<Self, Self::Error> {
2710 if path.is_relative() {
2711 Ok(std_box_to_box(path))
2712 } else {
2713 Err(path)
2714 }
2715 }
2716}
2717
2718impl TryFrom<Box<std::path::Path>> for Box<AbsolutePath> {
2719 type Error = Box<std::path::Path>;
2720
2721 #[inline]
2722 fn try_from(path: Box<std::path::Path>) -> Result<Self, Self::Error> {
2723 if path.is_absolute() {
2724 Ok(std_box_to_box(path))
2725 } else {
2726 Err(path)
2727 }
2728 }
2729}
2730
2731impl TryFrom<std::path::PathBuf> for Box<RelativePath> {
2732 type Error = std::path::PathBuf;
2733
2734 #[inline]
2735 fn try_from(buf: std::path::PathBuf) -> Result<Self, Self::Error> {
2736 RelativePathBuf::try_from(buf).map(Into::into)
2737 }
2738}
2739
2740impl TryFrom<std::path::PathBuf> for Box<AbsolutePath> {
2741 type Error = std::path::PathBuf;
2742
2743 #[inline]
2744 fn try_from(buf: std::path::PathBuf) -> Result<Self, Self::Error> {
2745 AbsolutePathBuf::try_from(buf).map(Into::into)
2746 }
2747}
2748
2749impl<'a> TryFrom<Cow<'a, std::path::Path>> for RelativePathBuf {
2750 type Error = Cow<'a, std::path::Path>;
2751
2752 #[inline]
2753 fn try_from(path: Cow<'a, std::path::Path>) -> Result<Self, Self::Error> {
2754 match path {
2755 Cow::Borrowed(path) => Self::try_from(path).map_err(|_| Cow::Borrowed(path)),
2756 Cow::Owned(path) => Self::try_from(path).map_err(Cow::Owned),
2757 }
2758 }
2759}
2760
2761impl<'a> TryFrom<Cow<'a, std::path::Path>> for AbsolutePathBuf {
2762 type Error = Cow<'a, std::path::Path>;
2763
2764 #[inline]
2765 fn try_from(path: Cow<'a, std::path::Path>) -> Result<Self, Self::Error> {
2766 match path {
2767 Cow::Borrowed(path) => Self::try_from(path).map_err(|_| Cow::Borrowed(path)),
2768 Cow::Owned(path) => Self::try_from(path).map_err(Cow::Owned),
2769 }
2770 }
2771}
2772
2773impl<'a> TryFrom<Cow<'a, std::path::Path>> for Box<RelativePath> {
2774 type Error = Cow<'a, std::path::Path>;
2775
2776 #[inline]
2777 fn try_from(path: Cow<'a, std::path::Path>) -> Result<Self, Self::Error> {
2778 match path {
2779 Cow::Borrowed(path) => Box::try_from(path).map_err(|_| Cow::Borrowed(path)),
2780 Cow::Owned(path) => Box::try_from(path).map_err(Cow::Owned),
2781 }
2782 }
2783}
2784
2785impl<'a> TryFrom<Cow<'a, std::path::Path>> for Box<AbsolutePath> {
2786 type Error = Cow<'a, std::path::Path>;
2787
2788 #[inline]
2789 fn try_from(path: Cow<'a, std::path::Path>) -> Result<Self, Self::Error> {
2790 match path {
2791 Cow::Borrowed(path) => Box::try_from(path).map_err(|_| Cow::Borrowed(path)),
2792 Cow::Owned(path) => Box::try_from(path).map_err(Cow::Owned),
2793 }
2794 }
2795}
2796
2797// === From string types ===
2798
2799impl TryFrom<OsString> for RelativePathBuf {
2800 type Error = OsString;
2801
2802 #[inline]
2803 fn try_from(s: OsString) -> Result<Self, Self::Error> {
2804 Self::try_from(PathBuf::from(s)).map_err(|buf| buf.into_os_string())
2805 }
2806}
2807
2808impl TryFrom<OsString> for AbsolutePathBuf {
2809 type Error = OsString;
2810
2811 #[inline]
2812 fn try_from(s: OsString) -> Result<Self, Self::Error> {
2813 Self::try_from(PathBuf::from(s)).map_err(|buf| buf.into_os_string())
2814 }
2815}
2816
2817impl TryFrom<String> for RelativePathBuf {
2818 type Error = String;
2819
2820 #[inline]
2821 fn try_from(s: String) -> Result<Self, Self::Error> {
2822 if Path::new(&s).is_relative() {
2823 Ok(Self::new_unchecked(s.into()))
2824 } else {
2825 Err(s)
2826 }
2827 }
2828}
2829
2830impl TryFrom<String> for AbsolutePathBuf {
2831 type Error = String;
2832
2833 #[inline]
2834 fn try_from(s: String) -> Result<Self, Self::Error> {
2835 if Path::new(&s).is_absolute() {
2836 Ok(Self::new_unchecked(s.into()))
2837 } else {
2838 Err(s)
2839 }
2840 }
2841}
2842
2843/*
2844================================================================================
2845 PartialEq, Eq, PartialOrd, and Ord
2846================================================================================
2847*/
2848
2849// Here we match all `PartialEq` and `PartialOrd` implementations on `std::path::Path`
2850// and `std::path::PathBuf`, adding casting variations where possible.
2851
2852// === Between crate types ===
2853
2854impl<Form: PathForm> PartialEq for Path<Form> {
2855 fn eq(&self, other: &Self) -> bool {
2856 self.inner == other.inner
2857 }
2858}
2859
2860impl<Form: PathForm> Eq for Path<Form> {}
2861
2862impl<Form: PathForm> PartialOrd for Path<Form> {
2863 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2864 Some(self.cmp(other))
2865 }
2866}
2867
2868impl<Form: PathForm> Ord for Path<Form> {
2869 fn cmp(&self, other: &Self) -> Ordering {
2870 self.inner.cmp(&other.inner)
2871 }
2872}
2873
2874impl<Form: PathForm> Hash for Path<Form> {
2875 fn hash<H: Hasher>(&self, state: &mut H) {
2876 self.inner.hash(state);
2877 }
2878}
2879
2880impl<Form: PathForm> PartialEq for PathBuf<Form> {
2881 fn eq(&self, other: &Self) -> bool {
2882 self.inner == other.inner
2883 }
2884}
2885
2886impl<Form: PathForm> Eq for PathBuf<Form> {}
2887
2888impl<Form: PathForm> PartialOrd for PathBuf<Form> {
2889 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2890 Some(self.cmp(other))
2891 }
2892}
2893
2894impl<Form: PathForm> Ord for PathBuf<Form> {
2895 fn cmp(&self, other: &Self) -> Ordering {
2896 self.inner.cmp(&other.inner)
2897 }
2898}
2899
2900impl<Form: PathForm> Hash for PathBuf<Form> {
2901 fn hash<H: Hasher>(&self, state: &mut H) {
2902 self.inner.hash(state);
2903 }
2904}
2905
2906macro_rules! impl_cmp {
2907 (<$($life:lifetime),*> $lhs:ty, $rhs:ty) => {
2908 impl<$($life,)* Form: PathForm> PartialEq<$rhs> for $lhs {
2909 #[inline]
2910 fn eq(&self, other: &$rhs) -> bool {
2911 <Path<Form> as PartialEq>::eq(self, other)
2912 }
2913 }
2914
2915 impl<$($life,)* Form: PathForm> PartialEq<$lhs> for $rhs {
2916 #[inline]
2917 fn eq(&self, other: &$lhs) -> bool {
2918 <Path<Form> as PartialEq>::eq(self, other)
2919 }
2920 }
2921
2922 impl<$($life,)* Form: PathForm> PartialOrd<$rhs> for $lhs {
2923 #[inline]
2924 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
2925 <Path<Form> as PartialOrd>::partial_cmp(self, other)
2926 }
2927 }
2928
2929 impl<$($life,)* Form: PathForm> PartialOrd<$lhs> for $rhs {
2930 #[inline]
2931 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
2932 <Path<Form> as PartialOrd>::partial_cmp(self, other)
2933 }
2934 }
2935 };
2936}
2937
2938impl_cmp!(<> PathBuf<Form>, Path<Form>);
2939impl_cmp!(<'a> PathBuf<Form>, &'a Path<Form>);
2940impl_cmp!(<'a> Cow<'a, Path<Form>>, Path<Form>);
2941impl_cmp!(<'a, 'b> Cow<'a, Path<Form>>, &'b Path<Form>);
2942impl_cmp!(<'a> Cow<'a, Path<Form>>, PathBuf<Form>);
2943
2944macro_rules! impl_cmp_cast {
2945 (<$($life:lifetime),*> $lhs:ty, $rhs:ty) => {
2946 impl<$($life),*> PartialEq<$rhs> for $lhs {
2947 #[inline]
2948 fn eq(&self, other: &$rhs) -> bool {
2949 <Path as PartialEq>::eq(self.cast(), other.cast())
2950 }
2951 }
2952
2953 impl<$($life),*> PartialEq<$lhs> for $rhs {
2954 #[inline]
2955 fn eq(&self, other: &$lhs) -> bool {
2956 <Path as PartialEq>::eq(self.cast(), other.cast())
2957 }
2958 }
2959
2960 impl<$($life),*> PartialOrd<$rhs> for $lhs {
2961 #[inline]
2962 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
2963 <Path as PartialOrd>::partial_cmp(self.cast(), other.cast())
2964 }
2965 }
2966
2967 impl<$($life),*> PartialOrd<$lhs> for $rhs {
2968 #[inline]
2969 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
2970 <Path as PartialOrd>::partial_cmp(self.cast(), other.cast())
2971 }
2972 }
2973 };
2974}
2975
2976impl_cmp_cast!(<> Path, RelativePath);
2977impl_cmp_cast!(<> Path, AbsolutePath);
2978impl_cmp_cast!(<> Path, CanonicalPath);
2979impl_cmp_cast!(<> AbsolutePath, CanonicalPath);
2980impl_cmp_cast!(<> PathBuf, RelativePathBuf);
2981impl_cmp_cast!(<> PathBuf, AbsolutePathBuf);
2982impl_cmp_cast!(<> PathBuf, CanonicalPathBuf);
2983impl_cmp_cast!(<> AbsolutePathBuf, CanonicalPathBuf);
2984
2985impl_cmp_cast!(<'a> &'a Path, RelativePath);
2986impl_cmp_cast!(<'a> &'a Path, AbsolutePath);
2987impl_cmp_cast!(<'a> &'a Path, CanonicalPath);
2988impl_cmp_cast!(<'a> &'a AbsolutePath, CanonicalPath);
2989impl_cmp_cast!(<'a> Path, &'a RelativePath);
2990impl_cmp_cast!(<'a> Path, &'a AbsolutePath);
2991impl_cmp_cast!(<'a> Path, &'a CanonicalPath);
2992impl_cmp_cast!(<'a> AbsolutePath, &'a CanonicalPath);
2993
2994impl_cmp_cast!(<> PathBuf, RelativePath);
2995impl_cmp_cast!(<> PathBuf, AbsolutePath);
2996impl_cmp_cast!(<> PathBuf, CanonicalPath);
2997impl_cmp_cast!(<> AbsolutePathBuf, CanonicalPath);
2998impl_cmp_cast!(<> RelativePathBuf, Path);
2999impl_cmp_cast!(<> AbsolutePathBuf, Path);
3000impl_cmp_cast!(<> CanonicalPathBuf, Path);
3001impl_cmp_cast!(<> CanonicalPathBuf, AbsolutePath);
3002
3003impl_cmp_cast!(<'a> PathBuf, &'a RelativePath);
3004impl_cmp_cast!(<'a> PathBuf, &'a AbsolutePath);
3005impl_cmp_cast!(<'a> PathBuf, &'a CanonicalPath);
3006impl_cmp_cast!(<'a> AbsolutePathBuf, &'a CanonicalPath);
3007impl_cmp_cast!(<'a> RelativePathBuf, &'a Path);
3008impl_cmp_cast!(<'a> AbsolutePathBuf, &'a Path);
3009impl_cmp_cast!(<'a> CanonicalPathBuf, &'a Path);
3010impl_cmp_cast!(<'a> CanonicalPathBuf, &'a AbsolutePath);
3011
3012impl_cmp_cast!(<'a> Cow<'a, Path>, RelativePath);
3013impl_cmp_cast!(<'a> Cow<'a, Path>, AbsolutePath);
3014impl_cmp_cast!(<'a> Cow<'a, Path>, CanonicalPath);
3015impl_cmp_cast!(<'a> Cow<'a, AbsolutePath>, CanonicalPath);
3016impl_cmp_cast!(<'a> Cow<'a, RelativePath>, Path);
3017impl_cmp_cast!(<'a> Cow<'a, AbsolutePath>, Path);
3018impl_cmp_cast!(<'a> Cow<'a, CanonicalPath>, Path);
3019impl_cmp_cast!(<'a> Cow<'a, CanonicalPath>, AbsolutePath);
3020
3021impl_cmp_cast!(<'a, 'b> Cow<'a, Path>, &'b RelativePath);
3022impl_cmp_cast!(<'a, 'b> Cow<'a, Path>, &'b AbsolutePath);
3023impl_cmp_cast!(<'a, 'b> Cow<'a, Path>, &'b CanonicalPath);
3024impl_cmp_cast!(<'a, 'b> Cow<'a, AbsolutePath>, &'b CanonicalPath);
3025impl_cmp_cast!(<'a, 'b> Cow<'a, RelativePath>, &'b Path);
3026impl_cmp_cast!(<'a, 'b> Cow<'a, AbsolutePath>, &'b Path);
3027impl_cmp_cast!(<'a, 'b> Cow<'a, CanonicalPath>, &'b Path);
3028impl_cmp_cast!(<'a, 'b> Cow<'a, CanonicalPath>, &'b AbsolutePath);
3029
3030impl_cmp_cast!(<'a> Cow<'a, Path>, RelativePathBuf);
3031impl_cmp_cast!(<'a> Cow<'a, Path>, AbsolutePathBuf);
3032impl_cmp_cast!(<'a> Cow<'a, Path>, CanonicalPathBuf);
3033impl_cmp_cast!(<'a> Cow<'a, AbsolutePath>, CanonicalPathBuf);
3034impl_cmp_cast!(<'a> Cow<'a, RelativePath>, PathBuf);
3035impl_cmp_cast!(<'a> Cow<'a, AbsolutePath>, PathBuf);
3036impl_cmp_cast!(<'a> Cow<'a, CanonicalPath>, PathBuf);
3037impl_cmp_cast!(<'a> Cow<'a, CanonicalPath>, AbsolutePathBuf);
3038
3039// === Between std::path types ===
3040
3041macro_rules! impl_cmp_std {
3042 (<$($life:lifetime),*> $lhs:ty, $rhs:ty) => {
3043 impl<$($life,)* Form: PathForm> PartialEq<$rhs> for $lhs {
3044 #[inline]
3045 fn eq(&self, other: &$rhs) -> bool {
3046 <Path as PartialEq>::eq(self.as_ref(), other.as_any())
3047 }
3048 }
3049
3050 impl<$($life,)* Form: PathForm> PartialEq<$lhs> for $rhs {
3051 #[inline]
3052 fn eq(&self, other: &$lhs) -> bool {
3053 <Path as PartialEq>::eq(self.as_any(), other.as_ref())
3054 }
3055 }
3056
3057 impl<$($life,)* Form: PathForm> PartialOrd<$rhs> for $lhs {
3058 #[inline]
3059 fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
3060 <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_any())
3061 }
3062 }
3063
3064 impl<$($life,)* Form: PathForm> PartialOrd<$lhs> for $rhs {
3065 #[inline]
3066 fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
3067 <Path as PartialOrd>::partial_cmp(self.as_any(), other.as_ref())
3068 }
3069 }
3070 };
3071}
3072
3073impl_cmp_std!(<> std::path::Path, Path<Form>);
3074impl_cmp_std!(<> std::path::PathBuf, Path<Form>);
3075impl_cmp_std!(<'a> std::path::PathBuf, &'a Path<Form>);
3076impl_cmp_std!(<'a> Cow<'a, std::path::Path>, Path<Form>);
3077impl_cmp_std!(<'a, 'b> Cow<'a, std::path::Path>, &'b Path<Form>);
3078
3079impl_cmp_std!(<> std::path::Path, PathBuf<Form>);
3080impl_cmp_std!(<'a> &'a std::path::Path, PathBuf<Form>);
3081impl_cmp_std!(<> std::path::PathBuf, PathBuf<Form>);
3082impl_cmp_std!(<'a> Cow<'a, std::path::Path>, PathBuf<Form>);
3083
3084// === Between string types ===
3085
3086impl_cmp_std!(<> OsStr, Path<Form>);
3087impl_cmp_std!(<'a> OsStr, &'a Path<Form>);
3088impl_cmp_std!(<'a> &'a OsStr, Path<Form>);
3089impl_cmp_std!(<'a> Cow<'a, OsStr>, Path<Form>);
3090impl_cmp_std!(<'a, 'b> Cow<'b, OsStr>, &'a Path<Form>);
3091impl_cmp_std!(<> OsString, Path<Form>);
3092impl_cmp_std!(<'a> OsString, &'a Path<Form>);
3093
3094impl_cmp_std!(<> OsStr, PathBuf<Form>);
3095impl_cmp_std!(<'a> &'a OsStr, PathBuf<Form>);
3096impl_cmp_std!(<'a> Cow<'a, OsStr>, PathBuf<Form>);
3097impl_cmp_std!(<> OsString, PathBuf<Form>);