1 //! which
2 //!
3 //! A Rust equivalent of Unix command `which(1)`.
4 //! # Example:
5 //!
6 //! To find which rustc executable binary is using:
7 //!
8 //! ```no_run
9 //! use which::which;
10 //! use std::path::PathBuf;
11 //!
12 //! let result = which("rustc").unwrap();
13 //! assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
14 //!
15 //! ```
16
17 mod checker;
18 mod error;
19 mod finder;
20 #[cfg(windows)]
21 mod helper;
22
23 #[cfg(feature = "regex")]
24 use std::borrow::Borrow;
25 use std::env;
26 use std::fmt;
27 use std::path;
28
29 use std::ffi::{OsStr, OsString};
30
31 use crate::checker::{CompositeChecker, ExecutableChecker, ExistedChecker};
32 pub use crate::error::*;
33 use crate::finder::Finder;
34
35 /// Find an executable binary's path by name.
36 ///
37 /// If given an absolute path, returns it if the file exists and is executable.
38 ///
39 /// If given a relative path, returns an absolute path to the file if
40 /// it exists and is executable.
41 ///
42 /// If given a string without path separators, looks for a file named
43 /// `binary_name` at each directory in `$PATH` and if it finds an executable
44 /// file there, returns it.
45 ///
46 /// # Example
47 ///
48 /// ```no_run
49 /// use which::which;
50 /// use std::path::PathBuf;
51 ///
52 /// let result = which::which("rustc").unwrap();
53 /// assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
54 ///
55 /// ```
which<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf>56 pub fn which<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
57 which_all(binary_name).and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
58 }
59
60 /// Find an executable binary's path by name, ignoring `cwd`.
61 ///
62 /// If given an absolute path, returns it if the file exists and is executable.
63 ///
64 /// Does not resolve relative paths.
65 ///
66 /// If given a string without path separators, looks for a file named
67 /// `binary_name` at each directory in `$PATH` and if it finds an executable
68 /// file there, returns it.
69 ///
70 /// # Example
71 ///
72 /// ```no_run
73 /// use which::which;
74 /// use std::path::PathBuf;
75 ///
76 /// let result = which::which_global("rustc").unwrap();
77 /// assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
78 ///
79 /// ```
which_global<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf>80 pub fn which_global<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
81 which_all_global(binary_name).and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
82 }
83
84 /// Find all binaries with `binary_name` using `cwd` to resolve relative paths.
which_all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = path::PathBuf>>85 pub fn which_all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = path::PathBuf>> {
86 let cwd = env::current_dir().ok();
87
88 let binary_checker = build_binary_checker();
89
90 let finder = Finder::new();
91
92 finder.find(binary_name, env::var_os("PATH"), cwd, binary_checker)
93 }
94
95 /// Find all binaries with `binary_name` ignoring `cwd`.
which_all_global<T: AsRef<OsStr>>( binary_name: T, ) -> Result<impl Iterator<Item = path::PathBuf>>96 pub fn which_all_global<T: AsRef<OsStr>>(
97 binary_name: T,
98 ) -> Result<impl Iterator<Item = path::PathBuf>> {
99 let binary_checker = build_binary_checker();
100
101 let finder = Finder::new();
102
103 finder.find(
104 binary_name,
105 env::var_os("PATH"),
106 Option::<&Path>::None,
107 binary_checker,
108 )
109 }
110
111 /// Find all binaries matching a regular expression in a the system PATH.
112 ///
113 /// Only available when feature `regex` is enabled.
114 ///
115 /// # Arguments
116 ///
117 /// * `regex` - A regular expression to match binaries with
118 ///
119 /// # Examples
120 ///
121 /// Find Python executables:
122 ///
123 /// ```no_run
124 /// use regex::Regex;
125 /// use which::which;
126 /// use std::path::PathBuf;
127 ///
128 /// let re = Regex::new(r"python\d$").unwrap();
129 /// let binaries: Vec<PathBuf> = which::which_re(re).unwrap().collect();
130 /// let python_paths = vec![PathBuf::from("/usr/bin/python2"), PathBuf::from("/usr/bin/python3")];
131 /// assert_eq!(binaries, python_paths);
132 /// ```
133 ///
134 /// Find all cargo subcommand executables on the path:
135 ///
136 /// ```
137 /// use which::which_re;
138 /// use regex::Regex;
139 ///
140 /// which_re(Regex::new("^cargo-.*").unwrap()).unwrap()
141 /// .for_each(|pth| println!("{}", pth.to_string_lossy()));
142 /// ```
143 #[cfg(feature = "regex")]
which_re(regex: impl Borrow<Regex>) -> Result<impl Iterator<Item = path::PathBuf>>144 pub fn which_re(regex: impl Borrow<Regex>) -> Result<impl Iterator<Item = path::PathBuf>> {
145 which_re_in(regex, env::var_os("PATH"))
146 }
147
148 /// Find `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
which_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<path::PathBuf> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,149 pub fn which_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<path::PathBuf>
150 where
151 T: AsRef<OsStr>,
152 U: AsRef<OsStr>,
153 V: AsRef<path::Path>,
154 {
155 which_in_all(binary_name, paths, cwd)
156 .and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
157 }
158
159 /// Find all binaries matching a regular expression in a list of paths.
160 ///
161 /// Only available when feature `regex` is enabled.
162 ///
163 /// # Arguments
164 ///
165 /// * `regex` - A regular expression to match binaries with
166 /// * `paths` - A string containing the paths to search
167 /// (separated in the same way as the PATH environment variable)
168 ///
169 /// # Examples
170 ///
171 /// ```no_run
172 /// use regex::Regex;
173 /// use which::which;
174 /// use std::path::PathBuf;
175 ///
176 /// let re = Regex::new(r"python\d$").unwrap();
177 /// let paths = Some("/usr/bin:/usr/local/bin");
178 /// let binaries: Vec<PathBuf> = which::which_re_in(re, paths).unwrap().collect();
179 /// let python_paths = vec![PathBuf::from("/usr/bin/python2"), PathBuf::from("/usr/bin/python3")];
180 /// assert_eq!(binaries, python_paths);
181 /// ```
182 #[cfg(feature = "regex")]
which_re_in<T>( regex: impl Borrow<Regex>, paths: Option<T>, ) -> Result<impl Iterator<Item = path::PathBuf>> where T: AsRef<OsStr>,183 pub fn which_re_in<T>(
184 regex: impl Borrow<Regex>,
185 paths: Option<T>,
186 ) -> Result<impl Iterator<Item = path::PathBuf>>
187 where
188 T: AsRef<OsStr>,
189 {
190 let binary_checker = build_binary_checker();
191
192 let finder = Finder::new();
193
194 finder.find_re(regex, paths, binary_checker)
195 }
196
197 /// Find all binaries with `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
which_in_all<T, U, V>( binary_name: T, paths: Option<U>, cwd: V, ) -> Result<impl Iterator<Item = path::PathBuf>> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,198 pub fn which_in_all<T, U, V>(
199 binary_name: T,
200 paths: Option<U>,
201 cwd: V,
202 ) -> Result<impl Iterator<Item = path::PathBuf>>
203 where
204 T: AsRef<OsStr>,
205 U: AsRef<OsStr>,
206 V: AsRef<path::Path>,
207 {
208 let binary_checker = build_binary_checker();
209
210 let finder = Finder::new();
211
212 finder.find(binary_name, paths, Some(cwd), binary_checker)
213 }
214
215 /// Find all binaries with `binary_name` in the path list `paths`, ignoring `cwd`.
which_in_global<T, U>( binary_name: T, paths: Option<U>, ) -> Result<impl Iterator<Item = path::PathBuf>> where T: AsRef<OsStr>, U: AsRef<OsStr>,216 pub fn which_in_global<T, U>(
217 binary_name: T,
218 paths: Option<U>,
219 ) -> Result<impl Iterator<Item = path::PathBuf>>
220 where
221 T: AsRef<OsStr>,
222 U: AsRef<OsStr>,
223 {
224 let binary_checker = build_binary_checker();
225
226 let finder = Finder::new();
227
228 finder.find(binary_name, paths, Option::<&Path>::None, binary_checker)
229 }
230
build_binary_checker() -> CompositeChecker231 fn build_binary_checker() -> CompositeChecker {
232 CompositeChecker::new()
233 .add_checker(Box::new(ExistedChecker::new()))
234 .add_checker(Box::new(ExecutableChecker::new()))
235 }
236
237 /// A wrapper containing all functionality in this crate.
238 pub struct WhichConfig {
239 cwd: Option<either::Either<bool, path::PathBuf>>,
240 custom_path_list: Option<OsString>,
241 binary_name: Option<OsString>,
242 #[cfg(feature = "regex")]
243 regex: Option<Regex>,
244 }
245
246 impl Default for WhichConfig {
default() -> Self247 fn default() -> Self {
248 Self {
249 cwd: Some(either::Either::Left(true)),
250 custom_path_list: None,
251 binary_name: None,
252 #[cfg(feature = "regex")]
253 regex: None,
254 }
255 }
256 }
257
258 #[cfg(feature = "regex")]
259 type Regex = regex::Regex;
260
261 #[cfg(not(feature = "regex"))]
262 type Regex = ();
263
264 impl WhichConfig {
new() -> Self265 pub fn new() -> Self {
266 Self::default()
267 }
268
269 /// Whether or not to use the current working directory. `true` by default.
270 ///
271 /// # Panics
272 ///
273 /// If regex was set previously, and you've just passed in `use_cwd: true`, this will panic.
system_cwd(mut self, use_cwd: bool) -> Self274 pub fn system_cwd(mut self, use_cwd: bool) -> Self {
275 #[cfg(feature = "regex")]
276 if self.regex.is_some() && use_cwd {
277 panic!("which can't use regex and cwd at the same time!")
278 }
279 self.cwd = Some(either::Either::Left(use_cwd));
280 self
281 }
282
283 /// Sets a custom path for resolving relative paths.
284 ///
285 /// # Panics
286 ///
287 /// If regex was set previously, this will panic.
custom_cwd(mut self, cwd: path::PathBuf) -> Self288 pub fn custom_cwd(mut self, cwd: path::PathBuf) -> Self {
289 #[cfg(feature = "regex")]
290 if self.regex.is_some() {
291 panic!("which can't use regex and cwd at the same time!")
292 }
293 self.cwd = Some(either::Either::Right(cwd));
294 self
295 }
296
297 /// Sets the path name regex to search for. You ***MUST*** call this, or [`Self::binary_name`] prior to searching.
298 ///
299 /// When `Regex` is disabled this function takes the unit type as a stand in. The parameter will change when
300 /// `Regex` is enabled.
301 ///
302 /// # Panics
303 ///
304 /// If the `regex` feature wasn't turned on for this crate this will always panic. Additionally if a
305 /// `cwd` (aka current working directory) or `binary_name` was set previously, this will panic, as those options
306 /// are incompatible with `regex`.
307 #[allow(unused_variables)]
regex(mut self, regex: Regex) -> Self308 pub fn regex(mut self, regex: Regex) -> Self {
309 #[cfg(not(feature = "regex"))]
310 {
311 panic!("which's regex feature was not enabled in your Cargo.toml!")
312 }
313 #[cfg(feature = "regex")]
314 {
315 if self.cwd != Some(either::Either::Left(false)) && self.cwd.is_some() {
316 panic!("which can't use regex and cwd at the same time!")
317 }
318 if self.binary_name.is_some() {
319 panic!("which can't use `binary_name` and `regex` at the same time!");
320 }
321 self.regex = Some(regex);
322 self
323 }
324 }
325
326 /// Sets the path name to search for. You ***MUST*** call this, or [`Self::regex`] prior to searching.
327 ///
328 /// # Panics
329 ///
330 /// If a `regex` was set previously this will panic as this is not compatible with `regex`.
binary_name(mut self, name: OsString) -> Self331 pub fn binary_name(mut self, name: OsString) -> Self {
332 #[cfg(feature = "regex")]
333 if self.regex.is_some() {
334 panic!("which can't use `binary_name` and `regex` at the same time!");
335 }
336 self.binary_name = Some(name);
337 self
338 }
339
340 /// Uses the given string instead of the `PATH` env variable.
custom_path_list(mut self, custom_path_list: OsString) -> Self341 pub fn custom_path_list(mut self, custom_path_list: OsString) -> Self {
342 self.custom_path_list = Some(custom_path_list);
343 self
344 }
345
346 /// Uses the `PATH` env variable. Enabled by default.
system_path_list(mut self) -> Self347 pub fn system_path_list(mut self) -> Self {
348 self.custom_path_list = None;
349 self
350 }
351
352 /// Finishes configuring, runs the query and returns the first result.
first_result(self) -> Result<path::PathBuf>353 pub fn first_result(self) -> Result<path::PathBuf> {
354 self.all_results()
355 .and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
356 }
357
358 /// Finishes configuring, runs the query and returns all results.
all_results(self) -> Result<impl Iterator<Item = path::PathBuf>>359 pub fn all_results(self) -> Result<impl Iterator<Item = path::PathBuf>> {
360 let binary_checker = build_binary_checker();
361
362 let finder = Finder::new();
363
364 let paths = self.custom_path_list.or_else(|| env::var_os("PATH"));
365
366 #[cfg(feature = "regex")]
367 if let Some(regex) = self.regex {
368 return finder
369 .find_re(regex, paths, binary_checker)
370 .map(|i| Box::new(i) as Box<dyn Iterator<Item = path::PathBuf>>);
371 }
372
373 let cwd = match self.cwd {
374 Some(either::Either::Left(false)) => None,
375 Some(either::Either::Right(custom)) => Some(custom),
376 None | Some(either::Either::Left(true)) => env::current_dir().ok(),
377 };
378
379 finder
380 .find(
381 self.binary_name.expect(
382 "binary_name not set! You must set binary_name or regex before searching!",
383 ),
384 paths,
385 cwd,
386 binary_checker,
387 )
388 .map(|i| Box::new(i) as Box<dyn Iterator<Item = path::PathBuf>>)
389 }
390 }
391
392 /// An owned, immutable wrapper around a `PathBuf` containing the path of an executable.
393 ///
394 /// The constructed `PathBuf` is the output of `which` or `which_in`, but `which::Path` has the
395 /// advantage of being a type distinct from `std::path::Path` and `std::path::PathBuf`.
396 ///
397 /// It can be beneficial to use `which::Path` instead of `std::path::Path` when you want the type
398 /// system to enforce the need for a path that exists and points to a binary that is executable.
399 ///
400 /// Since `which::Path` implements `Deref` for `std::path::Path`, all methods on `&std::path::Path`
401 /// are also available to `&which::Path` values.
402 #[derive(Clone, PartialEq, Eq)]
403 pub struct Path {
404 inner: path::PathBuf,
405 }
406
407 impl Path {
408 /// Returns the path of an executable binary by name.
409 ///
410 /// This calls `which` and maps the result into a `Path`.
new<T: AsRef<OsStr>>(binary_name: T) -> Result<Path>411 pub fn new<T: AsRef<OsStr>>(binary_name: T) -> Result<Path> {
412 which(binary_name).map(|inner| Path { inner })
413 }
414
415 /// Returns the paths of all executable binaries by a name.
416 ///
417 /// this calls `which_all` and maps the results into `Path`s.
all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = Path>>418 pub fn all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = Path>> {
419 which_all(binary_name).map(|inner| inner.map(|inner| Path { inner }))
420 }
421
422 /// Returns the path of an executable binary by name in the path list `paths` and using the
423 /// current working directory `cwd` to resolve relative paths.
424 ///
425 /// This calls `which_in` and maps the result into a `Path`.
new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<Path> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,426 pub fn new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<Path>
427 where
428 T: AsRef<OsStr>,
429 U: AsRef<OsStr>,
430 V: AsRef<path::Path>,
431 {
432 which_in(binary_name, paths, cwd).map(|inner| Path { inner })
433 }
434
435 /// Returns all paths of an executable binary by name in the path list `paths` and using the
436 /// current working directory `cwd` to resolve relative paths.
437 ///
438 /// This calls `which_in_all` and maps the results into a `Path`.
all_in<T, U, V>( binary_name: T, paths: Option<U>, cwd: V, ) -> Result<impl Iterator<Item = Path>> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,439 pub fn all_in<T, U, V>(
440 binary_name: T,
441 paths: Option<U>,
442 cwd: V,
443 ) -> Result<impl Iterator<Item = Path>>
444 where
445 T: AsRef<OsStr>,
446 U: AsRef<OsStr>,
447 V: AsRef<path::Path>,
448 {
449 which_in_all(binary_name, paths, cwd).map(|inner| inner.map(|inner| Path { inner }))
450 }
451
452 /// Returns a reference to a `std::path::Path`.
as_path(&self) -> &path::Path453 pub fn as_path(&self) -> &path::Path {
454 self.inner.as_path()
455 }
456
457 /// Consumes the `which::Path`, yielding its underlying `std::path::PathBuf`.
into_path_buf(self) -> path::PathBuf458 pub fn into_path_buf(self) -> path::PathBuf {
459 self.inner
460 }
461 }
462
463 impl fmt::Debug for Path {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result464 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
465 fmt::Debug::fmt(&self.inner, f)
466 }
467 }
468
469 impl std::ops::Deref for Path {
470 type Target = path::Path;
471
deref(&self) -> &path::Path472 fn deref(&self) -> &path::Path {
473 self.inner.deref()
474 }
475 }
476
477 impl AsRef<path::Path> for Path {
as_ref(&self) -> &path::Path478 fn as_ref(&self) -> &path::Path {
479 self.as_path()
480 }
481 }
482
483 impl AsRef<OsStr> for Path {
as_ref(&self) -> &OsStr484 fn as_ref(&self) -> &OsStr {
485 self.as_os_str()
486 }
487 }
488
489 impl PartialEq<path::PathBuf> for Path {
eq(&self, other: &path::PathBuf) -> bool490 fn eq(&self, other: &path::PathBuf) -> bool {
491 self.inner == *other
492 }
493 }
494
495 impl PartialEq<Path> for path::PathBuf {
eq(&self, other: &Path) -> bool496 fn eq(&self, other: &Path) -> bool {
497 *self == other.inner
498 }
499 }
500
501 /// An owned, immutable wrapper around a `PathBuf` containing the _canonical_ path of an
502 /// executable.
503 ///
504 /// The constructed `PathBuf` is the result of `which` or `which_in` followed by
505 /// `Path::canonicalize`, but `CanonicalPath` has the advantage of being a type distinct from
506 /// `std::path::Path` and `std::path::PathBuf`.
507 ///
508 /// It can be beneficial to use `CanonicalPath` instead of `std::path::Path` when you want the type
509 /// system to enforce the need for a path that exists, points to a binary that is executable, is
510 /// absolute, has all components normalized, and has all symbolic links resolved
511 ///
512 /// Since `CanonicalPath` implements `Deref` for `std::path::Path`, all methods on
513 /// `&std::path::Path` are also available to `&CanonicalPath` values.
514 #[derive(Clone, PartialEq, Eq)]
515 pub struct CanonicalPath {
516 inner: path::PathBuf,
517 }
518
519 impl CanonicalPath {
520 /// Returns the canonical path of an executable binary by name.
521 ///
522 /// This calls `which` and `Path::canonicalize` and maps the result into a `CanonicalPath`.
new<T: AsRef<OsStr>>(binary_name: T) -> Result<CanonicalPath>523 pub fn new<T: AsRef<OsStr>>(binary_name: T) -> Result<CanonicalPath> {
524 which(binary_name)
525 .and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
526 .map(|inner| CanonicalPath { inner })
527 }
528
529 /// Returns the canonical paths of an executable binary by name.
530 ///
531 /// This calls `which_all` and `Path::canonicalize` and maps the results into `CanonicalPath`s.
all<T: AsRef<OsStr>>( binary_name: T, ) -> Result<impl Iterator<Item = Result<CanonicalPath>>>532 pub fn all<T: AsRef<OsStr>>(
533 binary_name: T,
534 ) -> Result<impl Iterator<Item = Result<CanonicalPath>>> {
535 which_all(binary_name).map(|inner| {
536 inner.map(|inner| {
537 inner
538 .canonicalize()
539 .map_err(|_| Error::CannotCanonicalize)
540 .map(|inner| CanonicalPath { inner })
541 })
542 })
543 }
544
545 /// Returns the canonical path of an executable binary by name in the path list `paths` and
546 /// using the current working directory `cwd` to resolve relative paths.
547 ///
548 /// This calls `which_in` and `Path::canonicalize` and maps the result into a `CanonicalPath`.
new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<CanonicalPath> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,549 pub fn new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<CanonicalPath>
550 where
551 T: AsRef<OsStr>,
552 U: AsRef<OsStr>,
553 V: AsRef<path::Path>,
554 {
555 which_in(binary_name, paths, cwd)
556 .and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
557 .map(|inner| CanonicalPath { inner })
558 }
559
560 /// Returns all of the canonical paths of an executable binary by name in the path list `paths` and
561 /// using the current working directory `cwd` to resolve relative paths.
562 ///
563 /// This calls `which_in_all` and `Path::canonicalize` and maps the result into a `CanonicalPath`.
all_in<T, U, V>( binary_name: T, paths: Option<U>, cwd: V, ) -> Result<impl Iterator<Item = Result<CanonicalPath>>> where T: AsRef<OsStr>, U: AsRef<OsStr>, V: AsRef<path::Path>,564 pub fn all_in<T, U, V>(
565 binary_name: T,
566 paths: Option<U>,
567 cwd: V,
568 ) -> Result<impl Iterator<Item = Result<CanonicalPath>>>
569 where
570 T: AsRef<OsStr>,
571 U: AsRef<OsStr>,
572 V: AsRef<path::Path>,
573 {
574 which_in_all(binary_name, paths, cwd).map(|inner| {
575 inner.map(|inner| {
576 inner
577 .canonicalize()
578 .map_err(|_| Error::CannotCanonicalize)
579 .map(|inner| CanonicalPath { inner })
580 })
581 })
582 }
583
584 /// Returns a reference to a `std::path::Path`.
as_path(&self) -> &path::Path585 pub fn as_path(&self) -> &path::Path {
586 self.inner.as_path()
587 }
588
589 /// Consumes the `which::CanonicalPath`, yielding its underlying `std::path::PathBuf`.
into_path_buf(self) -> path::PathBuf590 pub fn into_path_buf(self) -> path::PathBuf {
591 self.inner
592 }
593 }
594
595 impl fmt::Debug for CanonicalPath {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result596 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
597 fmt::Debug::fmt(&self.inner, f)
598 }
599 }
600
601 impl std::ops::Deref for CanonicalPath {
602 type Target = path::Path;
603
deref(&self) -> &path::Path604 fn deref(&self) -> &path::Path {
605 self.inner.deref()
606 }
607 }
608
609 impl AsRef<path::Path> for CanonicalPath {
as_ref(&self) -> &path::Path610 fn as_ref(&self) -> &path::Path {
611 self.as_path()
612 }
613 }
614
615 impl AsRef<OsStr> for CanonicalPath {
as_ref(&self) -> &OsStr616 fn as_ref(&self) -> &OsStr {
617 self.as_os_str()
618 }
619 }
620
621 impl PartialEq<path::PathBuf> for CanonicalPath {
eq(&self, other: &path::PathBuf) -> bool622 fn eq(&self, other: &path::PathBuf) -> bool {
623 self.inner == *other
624 }
625 }
626
627 impl PartialEq<CanonicalPath> for path::PathBuf {
eq(&self, other: &CanonicalPath) -> bool628 fn eq(&self, other: &CanonicalPath) -> bool {
629 *self == other.inner
630 }
631 }
632