1use std::collections::HashMap;
2use std::fs;
3use std::io::Write;
4
5use toml::Value;
6
7const DATABASE_DIR: &str = ".ffs";
8const DATABASE_FILENAME: &str = "database.toml";
9
10pub struct Database {
11 filename: String,
12 data: HashMap<String, String>,
13}
14
15impl Default for Database {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl Database {
22 #[must_use]
28 pub fn new() -> Self {
29 let mut db = Self {
30 filename: DATABASE_FILENAME.to_string(),
31 data: HashMap::new(),
32 };
33 db.load().unwrap();
34 db
35 }
36}
37
38impl Database {
39 pub fn load(&mut self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
49 let home = std::env::var("HOME").unwrap();
50 let database_dir = format!("{home}/{DATABASE_DIR}");
51 let database_file = format!("{database_dir}/{DATABASE_FILENAME}");
52 if fs::metadata(&database_dir).is_err() {
54 println!("Creating database directory: {database_dir}");
55 fs::create_dir_all(database_dir)?;
56 }
57 if fs::metadata(&database_file).is_err() {
59 println!("Creating database file: {database_file}");
60 fs::File::create(&database_file)?;
61 }
62 let contents = fs::read_to_string(&database_file)?;
63 let value = contents.parse::<Value>()?;
64 let table = value.as_table().unwrap();
65 self.data = table
66 .iter()
67 .map(|(k, v)| (k.clone(), v.as_str().unwrap_or_default().to_string()))
68 .collect();
69 Ok(())
70 }
71
72 pub fn set(
78 &mut self,
79 key: &str,
80 value: &str,
81 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
82 self.data.insert(key.to_string(), value.to_string());
83 let mut file = fs::File::create(&self.filename)?;
84 let toml = toml::to_string(&self.data)?;
85 file.write_all(toml.as_bytes())?;
86 Ok(())
87 }
88
89 #[must_use]
90 pub fn get(&self, key: &str) -> Option<String> {
91 self.data.get(key).cloned()
92 }
93}