1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
/* Copyright (c) 2018 Garrett Berg, vitiral@gmail.com * * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or * http://opensource.org/licenses/MIT>, at your option. This file may not be * copied, modified, or distributed except according to those terms. */ //! The absolute path type, the root type for _most_ `Path*` types in this module //! (except for `PathArc`). use std::fmt; use std_prelude::*; use super::{PathArc, PathDir, PathFile, Result}; #[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] /// An absolute ([canonicalized][1]) path that is guaranteed (when created) to exist. /// /// [1]: https://doc.rust-lang.org/std/path/struct.Path.html?search=#method.canonicalize pub struct PathAbs(pub(crate) PathArc); impl PathAbs { /// Instantiate a new `PathAbs`. The path must exist or `io::Error` will be returned. /// /// # Examples /// ```rust /// use path_abs::PathAbs; /// /// # fn try_main() -> ::std::io::Result<()> { /// let lib = PathAbs::new("src/lib.rs")?; /// # Ok(()) } fn main() { try_main().unwrap() } /// ``` pub fn new<P: AsRef<Path>>(path: P) -> Result<PathAbs> { let arc = PathArc::new(path); arc.canonicalize() } /// Resolve the `PathAbs` as a `PathFile`. Return an error if it is not a file. pub fn into_file(self) -> Result<PathFile> { PathFile::from_abs(self) } /// Resolve the `PathAbs` as a `PathDir`. Return an error if it is not a directory. pub fn into_dir(self) -> Result<PathDir> { PathDir::from_abs(self) } /// Get the parent directory of this path as a `PathDir`. /// /// > This does not make aditional syscalls, as the parent by definition must be a directory /// > and exist. /// /// # Examples /// ```rust /// # extern crate path_abs; /// use path_abs::{PathDir, PathFile}; /// /// # fn try_main() -> ::std::io::Result<()> { /// let lib = PathFile::new("src/lib.rs")?; /// let src = lib.parent_dir().unwrap(); /// assert_eq!(PathDir::new("src")?, src); /// # Ok(()) } fn main() { try_main().unwrap() } /// ``` pub fn parent_dir(&self) -> Option<PathDir> { match self.parent() { Some(p) => Some(PathDir(PathAbs(PathArc::new(p)))), None => None, } } /// Return a reference to a basic `std::path::Path` pub fn as_path(&self) -> &Path { self.as_ref() } /// For constructing mocked paths during tests. This is effectively the same as a `PathBuf`. /// /// This is NOT checked for validity so the file may or may not actually exist and will /// NOT be, in any way, an absolute or canonicalized path. /// /// # Examples /// ```rust /// # extern crate path_abs; /// use path_abs::PathAbs; /// /// # fn try_main() -> ::std::io::Result<()> { /// // this file exist /// let lib = PathAbs::new("src/lib.rs")?; /// /// let lib_mocked = PathAbs::mock("src/lib.rs"); /// /// // in this case, the mocked file exists /// assert!(lib_mocked.exists()); /// /// // However, it is NOT equivalent to `lib` /// assert_ne!(lib, lib_mocked); /// /// // this file doesn't exist at all /// let dne = PathAbs::mock("src/dne.rs"); /// assert!(!dne.exists()); /// # Ok(()) } fn main() { try_main().unwrap() } /// ``` pub fn mock<P: AsRef<Path>>(fake_path: P) -> PathAbs { PathAbs(PathArc::new(fake_path)) } } impl fmt::Debug for PathAbs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } impl AsRef<PathArc> for PathAbs { fn as_ref(&self) -> &PathArc { &self.0 } } impl Deref for PathAbs { type Target = PathArc; fn deref(&self) -> &PathArc { &self.0 } } impl Into<PathArc> for PathAbs { fn into(self) -> PathArc { self.0 } }