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 132 133 134 135 136 137
/* 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. */ use std::io; use std_prelude::*; use super::{Error, Result}; use super::PathAbs; use file::PathFile; use dir::PathDir; #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serialize", serde(tag = "type", content = "path", rename_all = "lowercase"))] #[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] /// An an enum containing either a file or a directory. /// /// This is used primarily for: /// - The items returned from `PathDir::list` /// - Serializing paths of different types. /// /// > Note: symlinks are not supported because they are /// > *impossible* for canonicalized paths. pub enum PathType { File(PathFile), Dir(PathDir), } impl PathType { /// Resolves and returns the `PathType` of the given path. /// /// > If the path exists but is not a file or a directory (i.e. is a symlink), then /// > `io::ErrorKind::InvalidInput` is returned. /// /// # Examples /// ```rust /// # extern crate path_abs; /// use path_abs::PathType; /// /// # fn try_main() -> ::std::io::Result<()> { /// let src = PathType::new("src")?; /// # Ok(()) } fn main() { try_main().unwrap() } pub fn new<P: AsRef<Path>>(path: P) -> Result<PathType> { let abs = PathAbs::new(&path)?; PathType::from_abs(abs) } /// Consume the `PathAbs` returning the `PathType`. pub fn from_abs(abs: PathAbs) -> Result<PathType> { let ty = abs.metadata()?.file_type(); if ty.is_file() { Ok(PathType::File(PathFile(abs))) } else if ty.is_dir() { Ok(PathType::Dir(PathDir(abs))) } else { Err(Error::new( io::Error::new(io::ErrorKind::InvalidInput, "path is not a dir or a file"), "resolving", abs.into(), )) } } /// Unwrap the `PathType` as a `PathFile`. /// /// # Examples /// ```rust /// # extern crate path_abs; /// use path_abs::PathType; /// /// # fn try_main() -> ::std::io::Result<()> { /// let lib = PathType::new("src/lib.rs")?.unwrap_file(); /// # Ok(()) } fn main() { try_main().unwrap() } pub fn unwrap_file(self) -> PathFile { match self { PathType::File(f) => f, PathType::Dir(d) => { panic!("unwrap_file called on {}, which is not a file", d.display()) } } } /// Unwrap the `PathType` as a `PathDir`. /// /// # Examples /// ```rust /// # extern crate path_abs; /// use path_abs::PathType; /// /// # fn try_main() -> ::std::io::Result<()> { /// let src = PathType::new("src")?.unwrap_dir(); /// # Ok(()) } fn main() { try_main().unwrap() } pub fn unwrap_dir(self) -> PathDir { match self { PathType::Dir(d) => d, PathType::File(f) => panic!( "unwrap_dir called on {}, which is not a directory", f.display() ), } } /// Return whether this variant is `PathType::Dir`. pub fn is_dir(&self) -> bool { if let PathType::Dir(_) = *self { true } else { false } } /// Return whether this variant is `PathType::File`. pub fn is_file(&self) -> bool { if let PathType::File(_) = *self { true } else { false } } /// Create a mock file type. *For use in tests only*. /// /// See the docs for [`PathAbs::mock`](struct.PathAbs.html#method.mock) pub fn mock_file<P: AsRef<Path>>(path: P) -> PathType { PathType::File(PathFile::mock(path)) } /// Create a mock dir type. *For use in tests only*. /// /// See the docs for [`PathAbs::mock`](struct.PathAbs.html#method.mock) pub fn mock_dir<P: AsRef<Path>>(path: P) -> PathType { PathType::Dir(PathDir::mock(path)) } }