1extern crate serde;
2extern crate toml;
3
4use crate::{
5 error::{Error, Kind},
6 throw,
7};
8use std::borrow::Cow;
9use std::fmt::{Display, Formatter};
10use std::path::PathBuf;
11
12#[derive(Debug, serde::Deserialize)]
14pub struct Config {
15 data: PathBuf,
16 steam: PathBuf,
17 common: Option<PathBuf>,
18}
19
20impl Config {
21 pub fn open() -> Result<Config, Error> {
30 use std::fs::File;
31 use std::io::Read;
32
33 let loc: PathBuf = Config::config_location()?;
35
36 let mut file: File = match File::open(&loc) {
38 Ok(f) => f,
39 Err(e) => throw!(Kind::ConfigOpen, "{}", e),
40 };
41
42 let mut buffer: Vec<u8> = Vec::new();
44
45 if let Err(e) = file.read_to_end(&mut buffer) {
46 throw!(Kind::ConfigRead, "{}", e);
47 }
48
49 let slice: &[u8] = buffer.as_slice();
51
52 let mut config: Config = toml::from_slice(slice)?;
53
54 config.default_common();
55
56 Ok(config)
57 }
58
59 pub fn config_location() -> Result<PathBuf, Error> {
65 use std::env::var;
66
67 if let Ok(val) = var("XDG_CONFIG_HOME") {
68 let path: String = format!("{}/proton.conf", val);
69 return Ok(PathBuf::from(path));
70 }
71
72 match var("HOME") {
73 Ok(var) => Ok(PathBuf::from(format!("{}/.config/proton.conf", var))),
74 Err(_) => throw!(Kind::Environment, "XDG_CONFIG_HOME / HOME missing"),
75 }
76 }
77
78 #[inline]
79 fn default_common(&mut self) {
81 if self.common.is_none() {
82 let common: PathBuf = self._default_common();
83 self.common = Some(common);
84 }
85 }
86
87 #[must_use]
88 fn _default_common(&self) -> PathBuf {
90 eprintln!("warning: using default common");
91 let steam: Cow<str> = self.steam.to_string_lossy();
92 let common_str: String = format!("{}/steamapps/common/", steam);
93 PathBuf::from(common_str)
94 }
95
96 #[must_use]
97 #[inline]
98 pub fn common(&self) -> PathBuf {
100 if let Some(common) = &self.common {
101 common.clone()
102 } else {
103 self._default_common()
104 }
105 }
106
107 #[must_use]
108 #[inline]
109 pub fn steam(&self) -> PathBuf {
111 self.steam.clone()
112 }
113
114 #[must_use]
115 #[inline]
116 pub fn data(&self) -> PathBuf {
118 self.data.clone()
119 }
120}
121
122impl Display for Config {
123 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
124 let data: Cow<str> = self.data.to_string_lossy();
125 let steam: Cow<str> = self.steam.to_string_lossy();
126
127 let common: String = if let Some(common) = &self.common {
128 common.to_string_lossy().to_string()
129 } else {
130 let pb: PathBuf = self._default_common();
131 pb.to_string_lossy().to_string()
132 };
133
134 write!(f, "steam: {}\ndata: {}\ncommon: {}", steam, data, common)
135 }
136}