proton_call/
runtime.rs

1use std::{
2    convert::Infallible,
3    fmt::Display,
4    path::{Path, PathBuf},
5    process::ExitStatus,
6    str::FromStr,
7};
8
9use crate::{
10    error::{Error, Kind},
11    pass, throw, Proton,
12};
13
14#[derive(Debug)]
15pub struct Runtime {
16    version: RunTimeVersion,
17    path: PathBuf,
18    proton: Proton,
19}
20
21impl Runtime {
22    pub fn from_proton(version: RunTimeVersion, proton: Proton) -> Result<Self, Error> {
23        Ok(Self {
24            version,
25            path: Self::find(&proton.common, version)?,
26            proton,
27        })
28    }
29
30    pub fn execute(self) -> Result<ExitStatus, Error> {
31        use std::process::{Child, Command};
32
33        let envs: Vec<(String, String)> = self.proton.gen_options();
34
35        let mut child: Child = match Command::new(&self.path)
36        .arg(&self.proton.path)
37        .arg("runinprefix")
38        .arg(&self.proton.program)
39        .args(&self.proton.args)
40        .env("STEAM_COMPAT_DATA_PATH", &self.proton.compat)
41        .env("STEAM_COMPAT_CLIENT_INSTALL_PATH", &self.proton.steam)
42        .envs(envs)
43        .spawn() {
44            Ok(child) => child,
45            Err(e) => throw!(Kind::ProtonExit, "{}", e),
46        };
47
48
49        let status: ExitStatus = match child.wait() {
50            Ok(e) => e,
51            Err(e) => throw!(Kind::ProtonWait, "'{}': {}", child.id(), e),
52        };
53
54        pass!(status)
55    }
56
57    pub fn find(common: &Path, version: RunTimeVersion) -> Result<PathBuf, Error> {
58        let tmp = format!("{}/{}/run", common.display(), version);
59        let path = PathBuf::from(tmp);
60
61        if path.exists() {
62            pass!(path)
63        } else {
64            throw!(Kind::RuntimeMissing, "{}", version)
65        }
66    }
67}
68
69/// Enum to represet Steam runtime versions
70#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
71pub enum RunTimeVersion {
72    /// Default version of Steam's runtime
73    Default,
74    /// Sniper version of Steam's runtime
75    Sniper,
76    /// Soldier version of Steam's runtime
77    Soldier,
78    /// BattleEye version of Steam's runtime
79    BattleEye,
80    /// EasyAntiCheat version of Steam's runtime
81    EasyAntiCheat,
82}
83
84impl Display for RunTimeVersion {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        match self {
87            RunTimeVersion::Default => write!(f, "SteamLinuxRuntime"),
88            RunTimeVersion::Sniper => write!(f, "SteamLinuxRuntime_sniper"),
89            RunTimeVersion::Soldier => write!(f, "SteamLinuxRuntime_soldier"),
90            RunTimeVersion::BattleEye => write!(f, "Proton BattlEye Runtime"),
91            RunTimeVersion::EasyAntiCheat => write!(f, "Proton EasyAntiCheat Runtime"),
92        }
93    }
94}
95
96impl FromStr for RunTimeVersion {
97    type Err = Infallible;
98
99    fn from_str(s: &str) -> Result<Self, Self::Err> {
100        Ok(match s {
101            "default" => Self::Default,
102            "soldier" => Self::Soldier,
103            "sniper" => Self::Sniper,
104            "battleeye" => Self::BattleEye,
105            "eac" | "easyanticheat" => Self::EasyAntiCheat,
106            _ => Self::Default,
107        })
108    }
109}