path_locator/
lib.rs

1use std::path::{Path, PathBuf};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4pub enum PathError {
5    NotFound,
6}
7
8unsafe impl Send for PathError {}
9unsafe impl Sync for PathError {}
10
11pub fn find(
12    path: impl AsRef<Path>,
13    name: impl AsRef<Path>,
14) -> Result<PathBuf, PathError> {
15    let mut path = path.as_ref();
16    let name = name.as_ref();
17
18    loop {
19        let candidate = path.join(&name);
20        if candidate.exists() {
21            return Ok(candidate);
22        }
23
24        path = match path.parent() {
25            Some(parent) => parent,
26            None => return Err(PathError::NotFound),
27        };
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34
35    #[test]
36    fn test_find() {
37        let path = Path::new("src");
38        let name = Path::new(".gitignore");
39        let res = find(path, name);
40        assert!(res.is_ok());
41        assert_eq!(res.unwrap(), Path::new(".gitignore"));
42    }
43}