1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5use crate::error::{PwrError, Result};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct PwrConfig {
13 pub version: u32,
15
16 pub server_host: String,
18
19 #[serde(default = "default_port")]
21 pub server_port: u16,
22
23 pub server_psk: String,
25
26 #[serde(default = "default_use_tls")]
29 pub use_tls: bool,
30
31 #[serde(default)]
34 pub server_fingerprint: Option<String>,
35
36 pub local_root: String,
38
39 #[serde(default = "default_timeout")]
41 pub connect_timeout_secs: u64,
42
43 #[serde(default = "default_transfer_timeout")]
45 pub transfer_timeout_secs: u64,
46}
47
48fn default_port() -> u16 {
49 9742
50}
51
52fn default_use_tls() -> bool {
53 true
54}
55
56fn default_timeout() -> u64 {
57 10
58}
59
60fn default_transfer_timeout() -> u64 {
61 300
62}
63
64impl PwrConfig {
65 pub fn new(
67 server_host: String,
68 server_port: u16,
69 server_psk: String,
70 local_root: String,
71 ) -> Self {
72 Self {
73 version: 2,
74 server_host,
75 server_port,
76 server_psk,
77 use_tls: true,
78 server_fingerprint: None,
79 local_root,
80 connect_timeout_secs: 10,
81 transfer_timeout_secs: 300,
82 }
83 }
84
85 pub fn server_addr(&self) -> String {
87 format!("{}:{}", self.server_host, self.server_port)
88 }
89}
90
91pub fn config_dir() -> PathBuf {
93 dirs::config_dir()
94 .unwrap_or_else(|| PathBuf::from("~/.config"))
95 .join("pwr")
96}
97
98pub fn config_path() -> PathBuf {
100 config_dir().join("config.toml")
101}
102
103pub fn identity_path() -> PathBuf {
105 config_dir().join("identity")
106}
107
108pub fn transaction_log_path() -> PathBuf {
110 config_dir().join("transactions.log")
111}
112
113pub fn config_exists() -> bool {
115 config_path().exists()
116}
117
118pub fn load_config() -> Result<PwrConfig> {
120 let path = config_path();
121 if !path.exists() {
122 return Err(PwrError::NoConfig);
123 }
124 let contents = fs::read_to_string(&path)?;
125 let config: PwrConfig =
126 toml::from_str(&contents).map_err(|e| PwrError::TomlParse {
127 path: path.to_string_lossy().to_string(),
128 source: e,
129 })?;
130 Ok(config)
131}
132
133pub fn save_config(config: &PwrConfig) -> Result<()> {
135 let dir = config_dir();
136 fs::create_dir_all(&dir)?;
137 let contents = toml::to_string_pretty(config)?;
138 fs::write(config_path(), contents)?;
139 log::info!("Config saved to {}", config_path().display());
140 Ok(())
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_server_addr() {
149 let config = PwrConfig::new(
150 "nas.local".into(),
151 9742,
152 "abcdef0123456789".into(),
153 "/home/jacob/Projects".into(),
154 );
155 assert_eq!(config.server_addr(), "nas.local:9742");
156 }
157
158 #[test]
159 fn test_config_path() {
160 let path = config_path();
161 assert!(path.ends_with("pwr/config.toml"));
162 }
163
164 #[test]
165 fn test_default_port() {
166 assert_eq!(default_port(), 9742);
167 }
168}