crate_root/
lib.rs

1use std::env;
2use std::{fs, path};
3
4/// Obtains the path to the crate root, if the crate root cannot be found `None` is returned.
5pub fn root() -> Option<path::PathBuf> {
6    if let Ok(exec_path) = env::current_exe() {
7        walk_up(&exec_path)
8    } else {
9        None
10    }
11}
12
13/// Recursive helper function to obtain the path to the crate root.
14fn walk_up(path: &path::Path) -> Option<path::PathBuf> {
15    if let Ok(dir) = fs::read_dir(&path) {
16        let mut found_target = false;
17        let mut found_cargo_toml = false;
18
19        for entry_result in dir {
20            if let Ok(entry) = &entry_result {
21                if !found_target && entry.file_name() == "target" {
22                    found_target = true;
23                }
24
25                if !found_cargo_toml && entry.file_name() == "Cargo.toml" {
26                    found_cargo_toml = true;
27                }
28
29                if found_target && found_cargo_toml {
30                    return Some(path.to_path_buf());
31                }
32            }
33        }
34    }
35
36    if let Some(parent) = path.parent() {
37        walk_up(parent)
38    } else {
39        None
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn found_crate() {
49        assert_eq!(root().unwrap(), env::current_dir().unwrap());
50    }
51}