1use std::ffi;
9use std_prelude::*;
10
11use super::Result;
12use super::{PathAbs, PathDir, PathFile, PathInfo, PathOps};
13
14#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
15#[cfg_attr(
16 feature = "serialize",
17 serde(tag = "type", content = "path", rename_all = "lowercase")
18)]
19#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
20pub enum PathType {
28 File(PathFile),
29 Dir(PathDir),
30}
31
32impl PathType {
33 pub fn new<P: AsRef<Path>>(path: P) -> Result<PathType> {
47 let abs = PathAbs::new(&path)?;
48 PathType::try_from(abs)
49 }
50
51 pub fn try_from<P: Into<PathAbs>>(path: P) -> Result<PathType> {
53 let abs = path.into();
54 let ty = abs.metadata()?.file_type();
55 if ty.is_file() {
56 Ok(PathType::File(PathFile(abs)))
57 } else if ty.is_dir() {
58 Ok(PathType::Dir(PathDir(abs)))
59 } else {
60 unreachable!("rust docs: The fs::metadata function follows symbolic links")
61 }
62 }
63
64 pub fn unwrap_file(self) -> PathFile {
75 match self {
76 PathType::File(f) => f,
77 PathType::Dir(d) => {
78 panic!("unwrap_file called on {}, which is not a file", d.display())
79 }
80 }
81 }
82
83 pub fn unwrap_dir(self) -> PathDir {
94 match self {
95 PathType::Dir(d) => d,
96 PathType::File(f) => panic!(
97 "unwrap_dir called on {}, which is not a directory",
98 f.display()
99 ),
100 }
101 }
102
103 pub fn is_dir(&self) -> bool {
105 if let PathType::Dir(_) = *self {
106 true
107 } else {
108 false
109 }
110 }
111
112 pub fn is_file(&self) -> bool {
114 if let PathType::File(_) = *self {
115 true
116 } else {
117 false
118 }
119 }
120}
121
122impl AsRef<ffi::OsStr> for PathType {
123 fn as_ref(&self) -> &std::ffi::OsStr {
124 self.as_path().as_ref()
125 }
126}
127
128impl AsRef<PathAbs> for PathType {
129 fn as_ref(&self) -> &PathAbs {
130 match *self {
131 PathType::File(ref file) => file.as_ref(),
132 PathType::Dir(ref dir) => dir.as_ref(),
133 }
134 }
135}
136
137impl AsRef<Path> for PathType {
138 fn as_ref(&self) -> &Path {
139 let r: &PathAbs = self.as_ref();
140 r.as_ref()
141 }
142}
143
144impl AsRef<PathBuf> for PathType {
145 fn as_ref(&self) -> &PathBuf {
146 let r: &PathAbs = self.as_ref();
147 r.as_ref()
148 }
149}
150
151impl Borrow<PathAbs> for PathType {
152 fn borrow(&self) -> &PathAbs {
153 self.as_ref()
154 }
155}
156
157impl Borrow<Path> for PathType {
158 fn borrow(&self) -> &Path {
159 self.as_ref()
160 }
161}
162
163impl Borrow<PathBuf> for PathType {
164 fn borrow(&self) -> &PathBuf {
165 self.as_ref()
166 }
167}
168
169impl<'a> Borrow<PathAbs> for &'a PathType {
170 fn borrow(&self) -> &PathAbs {
171 self.as_ref()
172 }
173}
174
175impl<'a> Borrow<Path> for &'a PathType {
176 fn borrow(&self) -> &Path {
177 self.as_ref()
178 }
179}
180
181impl<'a> Borrow<PathBuf> for &'a PathType {
182 fn borrow(&self) -> &PathBuf {
183 self.as_ref()
184 }
185}
186
187impl From<PathType> for PathAbs {
188 fn from(path: PathType) -> PathAbs {
189 match path {
190 PathType::File(p) => p.into(),
191 PathType::Dir(p) => p.into(),
192 }
193 }
194}
195
196impl From<PathType> for Arc<PathBuf> {
197 fn from(path: PathType) -> Arc<PathBuf> {
198 let abs: PathAbs = path.into();
199 abs.into()
200 }
201}
202
203impl From<PathType> for PathBuf {
204 fn from(path: PathType) -> PathBuf {
205 let abs: PathAbs = path.into();
206 abs.into()
207 }
208}
209
210impl PathOps for PathType {
211 type Output = PathAbs;
212
213 fn concat<P: AsRef<Path>>(&self, path: P) -> Result<Self::Output> {
214 match self {
215 PathType::File(p) => p.concat(path),
216 PathType::Dir(p) => p.concat(path),
217 }
218 }
219
220 fn join<P: AsRef<Path>>(&self, path: P) -> Self::Output {
221 let buf = Path::join(self.as_path(), path);
222 Self::Output::new_unchecked(buf)
223 }
224
225 fn with_file_name<S: AsRef<ffi::OsStr>>(&self, file_name: S) -> Self::Output {
226 match self {
227 PathType::File(p) => p.with_file_name(file_name),
228 PathType::Dir(p) => p.with_file_name(file_name),
229 }
230 }
231
232 fn with_extension<S: AsRef<ffi::OsStr>>(&self, extension: S) -> Self::Output {
233 match self {
234 PathType::File(p) => p.with_extension(extension),
235 PathType::Dir(p) => p.with_extension(extension),
236 }
237 }
238}