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#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
71pub enum RunTimeVersion {
72 Default,
74 Sniper,
76 Soldier,
78 BattleEye,
80 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}