freezable_trait/
freezable.rs

1use std::fs;
2use std::fs::OpenOptions;
3use std::io;
4use std::path::PathBuf;
5use serde::Deserialize;
6use serde::Serialize;
7
8pub trait Freezable: Serialize + for<'a> Deserialize<'a> {
9    fn write_to_file(&self, path: PathBuf);
10    fn write_to_file_str(&self, path: &str);
11    fn from_file(path: PathBuf) -> Self;
12    fn from_file_str(path: &str) -> Self;
13    fn freeze_to_string(&self) -> String;
14    fn unfreeze_from_string(from: String) -> Self;
15}
16
17impl<T: Serialize + for<'a> Deserialize<'a>> Freezable for T {
18    fn write_to_file(&self, path: PathBuf) {
19        let file_exists = fs::metadata(&path).is_ok();
20        if !file_exists {
21            touch(&path).unwrap_or_else(|why| {
22                println!("! {:?}", why.kind());
23            });
24        }
25        let write_str = serde_json::to_string(&self).expect("Could not serialize object");
26        fs::write(path, write_str).expect("Unable to write config file.")
27    }
28
29    fn write_to_file_str(&self, path_str: &str) {
30        let path_expanded = shellexpand::tilde(path_str).into_owned().to_string();
31        let mut path = PathBuf::new();
32        path.push(path_expanded);
33        self.write_to_file(path);
34    }
35
36    fn from_file(path: PathBuf) -> Self {
37        let file_exists = fs::metadata(&path).is_ok();
38        if !file_exists {
39            return serde_json::from_str("{}").expect("Could not initialize default value for self");
40        }
41        let contents = fs::read_to_string(path).expect("Could not read provided file");
42        serde_json::from_str(&contents).expect("Could not deserialize object")
43    }
44
45    fn from_file_str(path: &str) -> Self {
46        let path_expanded = shellexpand::tilde(path).into_owned().to_string();
47        let mut path = PathBuf::new();
48        path.push(path_expanded);
49        Self::from_file(path)
50    }
51
52    fn freeze_to_string(&self) -> String {
53        serde_json::to_string(&self).expect("Could not serialize object")
54    }
55
56    fn unfreeze_from_string(from: String) -> Self {
57        serde_json::from_str(&from).expect("Could not deserialize object")
58    }
59}
60
61fn touch(path: &PathBuf) -> io::Result<()> {
62    match OpenOptions::new().create(true).truncate(false).write(true).open(path) {
63        Ok(_) => Ok(()),
64        Err(e) => Err(e),
65    }
66}