rvs_parser/
searchpath.rs

1use std::io;
2use std::path::Path;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Default)]
6pub struct SearchPath {
7    /// Search path for `import`
8    paths: Vec<PathBuf>,
9}
10
11impl SearchPath {
12    pub fn new(paths: Vec<PathBuf>) -> SearchPath {
13        SearchPath { paths }
14    }
15
16    /// Sets the search path used for `import`
17    ///
18    /// The string must be a colon separated list of paths.
19    ///
20    /// # Errors
21    ///
22    /// An error will be returned if any of the parsed paths do not exist.  If the search path
23    /// string contains a mix of paths that do and do not exist, none of the paths will be added to
24    /// the internal search path.
25    pub fn from_string(s: &str) -> io::Result<SearchPath> {
26        #[cfg(windows)]
27        let separator = ';';
28
29        #[cfg(not(windows))]
30        let separator = ':';
31
32        let paths: Vec<PathBuf> = s
33            .split(separator)
34            .into_iter()
35            .filter(|s| !s.is_empty())
36            .map(|s| Path::new(s).to_path_buf())
37            .collect();
38
39        let error_paths: Vec<PathBuf> = paths
40            .iter()
41            .filter(|path| !path.exists())
42            .map(|path| path.clone())
43            .collect();
44
45        if !error_paths.is_empty() {
46            Err(io::Error::new(
47                io::ErrorKind::NotFound,
48                format!(
49                    "Paths not found:\n{}",
50                    error_paths
51                        .iter()
52                        .map(|path| format!("   {:?}", path))
53                        .collect::<Vec<String>>()
54                        .join("\n")
55                ),
56            ))
57        } else {
58            Ok(SearchPath::new(paths))
59        }
60    }
61
62    pub fn find(&self, path: &Path) -> io::Result<PathBuf> {
63        if path.is_absolute() {
64            if path.exists() {
65                Ok(path.to_path_buf())
66            } else {
67                Err(io::Error::new(
68                    io::ErrorKind::NotFound,
69                    format!("Path '{:?}' does not exist", path),
70                ))
71            }
72        } else {
73            let result = self.paths.iter().map(|p| p.join(path)).find(|p| p.exists());
74
75            match result {
76                Some(path) => Ok(path),
77                None => Err(io::Error::new(
78                    io::ErrorKind::NotFound,
79                    format!("Path '{:?}' not found in: {:?}", path, self.paths),
80                )),
81            }
82        }
83    }
84}