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#[derive(Debug, Clone, Default)]
93#[cfg_attr(feature = "commandline", derive(clap::Args))]
94pub struct Paths {
95 #[cfg_attr(feature = "commandline", arg(short, long, default_value_t))]
97 data_dir: DataDir,
98 #[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}