proton_launch/
paths.rs

1use std::{fmt::Display, ops::Deref, path::PathBuf, str::FromStr};
2
3use xdg::BaseDirectories;
4
5#[derive(Debug, Clone)]
6pub struct DataDir(PathBuf);
7
8impl FromStr for DataDir {
9    type Err = <PathBuf as FromStr>::Err;
10
11    fn from_str(s: &str) -> Result<Self, Self::Err> {
12        Ok(Self(PathBuf::from_str(s)?))
13    }
14}
15
16impl Default for DataDir {
17    fn default() -> Self {
18        let basedirs = BaseDirectories::new().unwrap();
19        let data_dir = basedirs.create_data_directory("proton-launch").unwrap();
20        Self(data_dir)
21    }
22}
23
24impl Display for DataDir {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        write!(f, "{}", self.0.display())
27    }
28}
29
30impl Deref for DataDir {
31    type Target = PathBuf;
32
33    fn deref(&self) -> &Self::Target {
34        &self.0
35    }
36}
37
38impl DataDir {
39    pub fn compat_dir(&self, app_id: &str) -> PathBuf {
40        let compat_dir = self.0.join("compat").join(app_id);
41        std::fs::create_dir_all(&compat_dir).unwrap();
42        compat_dir
43    }
44
45    pub fn run_dir(&self, app_id: &str) -> PathBuf {
46        let run_dir = self.0.join("run").join(app_id);
47        std::fs::create_dir_all(&run_dir).unwrap();
48        run_dir
49    }
50
51    pub fn icon_path(&self, app_id: &str) -> PathBuf {
52        let icons_dir = self.0.join("icons");
53        std::fs::create_dir_all(&icons_dir).unwrap();
54        icons_dir.join(format!("{}.png", app_id))
55    }
56}
57
58#[derive(Debug, Clone)]
59pub struct ConfigDir(PathBuf);
60
61impl FromStr for ConfigDir {
62    type Err = <PathBuf as FromStr>::Err;
63
64    fn from_str(s: &str) -> Result<Self, Self::Err> {
65        Ok(Self(PathBuf::from_str(s)?))
66    }
67}
68
69impl Default for ConfigDir {
70    fn default() -> Self {
71        let basedirs = BaseDirectories::new().unwrap();
72        let config_dir = basedirs.create_config_directory("proton-launch").unwrap();
73        Self(config_dir)
74    }
75}
76
77impl Display for ConfigDir {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        write!(f, "{}", self.0.display())
80    }
81}
82
83impl Deref for ConfigDir {
84    type Target = PathBuf;
85
86    fn deref(&self) -> &Self::Target {
87        &self.0
88    }
89}
90
91/// The data paths to be used by the application
92#[derive(Debug, Clone, Default)]
93#[cfg_attr(feature = "commandline", derive(clap::Args))]
94pub struct Paths {
95    /// The directory to store the `compat` folders in
96    #[cfg_attr(feature = "commandline", arg(short, long, default_value_t))]
97    data_dir: DataDir,
98    /// The directory to store the `proton-launch` config in.
99    /// This is both Global and Game specific config
100    #[cfg_attr(feature = "commandline", arg(short, long, default_value_t))]
101    config_dir: ConfigDir,
102}
103
104impl Paths {
105    pub fn compat_dir(&self, app_id: &str) -> PathBuf {
106        self.data_dir.compat_dir(app_id)
107    }
108
109    pub fn run_dir(&self, app_id: &str) -> PathBuf {
110        self.data_dir.run_dir(app_id)
111    }
112
113    pub fn icon_path(&self, app_id: &str) -> PathBuf {
114        self.data_dir.icon_path(app_id)
115    }
116
117    pub fn application_entry(&self, app_id: &str) -> PathBuf {
118        let mut path = dirs::data_dir().unwrap().join("applications");
119        std::fs::create_dir_all(&path).unwrap();
120        path.push(format!("proton-{}.desktop", app_id));
121        path
122    }
123}