1use crate::error::Error;
2use crate::matcher;
3use serde::{Deserialize, Serialize};
4use std::fs;
5use std::fs::File;
6use std::io::prelude::*;
7use std::io::Write;
8use std::path::{Path, PathBuf};
9use std::str::FromStr;
10
11#[derive(Debug, Serialize, Deserialize)]
12pub struct Config {
13 pub path: String,
14 pub interval: u32,
15 pub version: Option<String>,
17}
18
19impl Config {
20 pub fn new<T>(path: T, interval: u32, version: String) -> Config
21 where
22 T: ToString,
23 {
24 Config {
25 path: path.to_string(),
26 interval,
27 version: Some(version),
28 }
29 }
30
31 pub fn set_version(&mut self, version: String) {
32 self.version = Some(version)
33 }
34
35 pub fn walk<T>(path: T, to: T) -> Result<PathBuf, Error>
36 where
37 T: AsRef<str>,
38 {
39 let mut result = String::new();
40
41 result.push_str(path.as_ref());
42
43 if !result.ends_with('/') {
44 result.push('/')
45 }
46
47 result.push_str(to.as_ref());
48
49 return match Path::new(&result).exists() {
50 true => Ok(match PathBuf::from_str(&result) {
51 Ok(p) => p,
52 Err(err) => return Err(Error::PathBufParseError(err.to_string())),
53 }),
54 false => return Err(Error::NoCorrespondingPathError),
55 };
56 }
57
58 pub fn from_local_conf() -> Result<Config, Error> {
59 let config_path = match dirs::config_dir() {
60 Some(p) => p,
61 None => return Err(Error::NoCorrespondingPathError),
62 };
63
64 let config_dir = matcher!(Config::walk(config_path.to_str().unwrap(), "wall"));
65
66 let config = matcher!(Config::walk(config_dir.to_str().unwrap(), "config.toml"));
67
68 let read = matcher!(Config::from_file(config));
69
70 Ok(read)
71 }
72
73 pub fn from_file<T>(path: T) -> Result<Config, Error>
74 where
75 T: AsRef<Path>,
76 {
77 let file = File::open(&path);
78
79 let mut file = match file {
80 Ok(file) => file,
81 Err(err) => {
82 return Err(Error::FileOpenError(err));
83 }
84 };
85
86 let mut content = String::new();
87
88 match file.read_to_string(&mut content) {
89 Ok(_) => dbg!("Successfully read the data"),
90 Err(err) => return Err(Error::ReadConfigError(err)),
91 };
92
93 let config = toml::from_str::<Config>(&content);
94
95 let result = match config {
96 Ok(d) => d,
97 Err(err) => return Err(Error::SerializeError(err.to_string())),
98 };
99
100 Ok(result)
101 }
102
103 pub fn write<T>(&self, path: T) -> Result<(), Error>
104 where
105 T: ToString + Clone,
106 {
107 let path = path.to_string();
108 let path = Path::new(&path);
109
110 if path.exists() {
111 std::fs::remove_file(path).expect("TODO: panic message");
112 }
113
114 let file = fs::OpenOptions::new()
115 .read(true)
116 .write(true)
117 .create(true)
118 .open(path);
119
120 let mut file = match file {
121 Ok(f) => f,
122 Err(err) => return Err(Error::WriteConfigError(err)),
123 };
124
125 let deser = match toml::to_string_pretty(self) {
126 Ok(s) => s,
127 Err(err) => return Err(Error::DeserializeError(err.to_string())),
128 };
129
130 file.write_all(deser.as_bytes())
131 .expect("Failed writing to a file");
132
133 Ok(())
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::Config;
140
141 #[test]
142 fn some() {
143 let config = Config::from_local_conf();
144
145 println!("{:?}", config);
146 }
147}