wall_rs/
config.rs

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 mode: wallpaper::Mode
16    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}