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)]
29 pub server_fingerprint: Option<String>,
30
31 pub local_root: String,
33
34 #[serde(default = "default_timeout")]
36 pub connect_timeout_secs: u64,
37
38 #[serde(default = "default_transfer_timeout")]
40 pub transfer_timeout_secs: u64,
41}
42
43fn default_port() -> u16 {
44 9742
45}
46
47fn default_timeout() -> u64 {
48 10
49}
50
51fn default_transfer_timeout() -> u64 {
52 300
53}
54
55impl PwrConfig {
56 pub fn new(
58 server_host: String,
59 server_port: u16,
60 server_psk: String,
61 local_root: String,
62 ) -> Self {
63 Self {
64 version: 2,
65 server_host,
66 server_port,
67 server_psk,
68 server_fingerprint: None,
69 local_root,
70 connect_timeout_secs: 10,
71 transfer_timeout_secs: 300,
72 }
73 }
74
75 pub fn server_addr(&self) -> String {
77 format!("{}:{}", self.server_host, self.server_port)
78 }
79}
80
81pub fn config_dir() -> PathBuf {
83 dirs::config_dir()
84 .unwrap_or_else(|| PathBuf::from("~/.config"))
85 .join("pwr")
86}
87
88pub fn config_path() -> PathBuf {
90 config_dir().join("config.toml")
91}
92
93pub fn identity_path() -> PathBuf {
95 config_dir().join("identity")
96}
97
98pub fn transaction_log_path() -> PathBuf {
100 config_dir().join("transactions.log")
101}
102
103pub fn config_exists() -> bool {
105 config_path().exists()
106}
107
108pub fn load_config() -> Result<PwrConfig> {
110 let path = config_path();
111 if !path.exists() {
112 return Err(PwrError::NoConfig);
113 }
114 let contents = fs::read_to_string(&path)?;
115 let config: PwrConfig =
116 toml::from_str(&contents).map_err(|e| PwrError::TomlParse {
117 path: path.to_string_lossy().to_string(),
118 source: e,
119 })?;
120 Ok(config)
121}
122
123pub fn save_config(config: &PwrConfig) -> Result<()> {
125 let dir = config_dir();
126 fs::create_dir_all(&dir)?;
127 let contents = toml::to_string_pretty(config)?;
128 fs::write(config_path(), contents)?;
129 log::info!("Config saved to {}", config_path().display());
130 Ok(())
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_server_addr() {
139 let config = PwrConfig::new(
140 "nas.local".into(),
141 9742,
142 "abcdef0123456789".into(),
143 "/home/jacob/Projects".into(),
144 );
145 assert_eq!(config.server_addr(), "nas.local:9742");
146 }
147
148 #[test]
149 fn test_config_path() {
150 let path = config_path();
151 assert!(path.ends_with("pwr/config.toml"));
152 }
153
154 #[test]
155 fn test_default_port() {
156 assert_eq!(default_port(), 9742);
157 }
158}