Skip to main content

cli/lib/compiler/
rust_toolchain_loader.rs

1//! Rust toolchain discovery for the nestrs compiler path.
2
3use std::path::PathBuf;
4
5#[derive(Clone, Debug, PartialEq, Eq)]
6pub struct RustToolchain {
7    pub cargo_binary: PathBuf,
8}
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct RustToolchainLoader {
12    cwd: PathBuf,
13    cached: Option<RustToolchain>,
14}
15
16impl Default for RustToolchainLoader {
17    fn default() -> Self {
18        Self::new(std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")))
19    }
20}
21
22impl RustToolchainLoader {
23    pub fn new(cwd: impl Into<PathBuf>) -> Self {
24        Self {
25            cwd: cwd.into(),
26            cached: None,
27        }
28    }
29
30    pub fn with_module_paths(cwd: impl Into<PathBuf>, _module_paths: Vec<PathBuf>) -> Self {
31        Self {
32            cwd: cwd.into(),
33            cached: None,
34        }
35    }
36
37    pub fn load(&mut self) -> Result<RustToolchain, String> {
38        if let Some(toolchain) = &self.cached {
39            return Ok(toolchain.clone());
40        }
41        let toolchain = self.resolve().unwrap_or_else(|| RustToolchain {
42            cargo_binary: PathBuf::from("cargo"),
43        });
44        self.cached = Some(toolchain.clone());
45        Ok(toolchain)
46    }
47
48    pub fn resolve(&self) -> Option<RustToolchain> {
49        let local = self
50            .cwd
51            .join(".cargo")
52            .join("bin")
53            .join(cargo_binary_name());
54        local.exists().then_some(RustToolchain {
55            cargo_binary: local,
56        })
57    }
58
59    pub fn get_module_paths(&self) -> Vec<PathBuf> {
60        vec![self.cwd.join(".cargo").join("bin")]
61    }
62}
63
64fn cargo_binary_name() -> &'static str {
65    if cfg!(windows) { "cargo.exe" } else { "cargo" }
66}