freezable_trait/
freezable.rs1use 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}