app_json_settings/
core.rs1use serde::{de::DeserializeOwned, Serialize};
2
3use std::fs;
4use std::io;
5use std::marker::PhantomData;
6use std::path::PathBuf;
7
8use crate::core::constant::DEFAULT_FILE_NAME;
9use crate::core::dir::default_config_dir;
10use crate::core::json::JsonFormat;
11use crate::ConfigError;
12use crate::Result;
13
14pub mod constant;
15mod dir;
16pub mod error;
17mod json;
18
19pub struct ConfigManager<T> {
20 folder_path: PathBuf,
21 file_name: String,
22 json_format: JsonFormat,
23 _marker: PhantomData<T>,
24}
25
26impl<T> ConfigManager<T>
27where
28 T: Serialize + DeserializeOwned,
29{
30 pub fn new() -> Self {
33 let app_name = std::env::current_exe()
34 .unwrap()
35 .file_stem()
36 .unwrap()
37 .to_string_lossy()
38 .to_string();
39
40 let folder_path = default_config_dir().join(&app_name);
41
42 Self {
43 folder_path,
44 file_name: DEFAULT_FILE_NAME.to_string(),
45 json_format: JsonFormat::Pretty,
46 _marker: PhantomData,
47 }
48 }
49
50 pub fn at_current_dir(mut self) -> Self {
52 self.folder_path = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
53 self
54 }
55
56 pub fn at_custom_dir<P: Into<PathBuf>>(mut self, path: P) -> Self {
58 self.folder_path = path.into();
59 self
60 }
61
62 pub fn with_filename(mut self, name: &str) -> Self {
64 self.file_name = name.to_string();
65 self
66 }
67
68 pub fn disable_pretty_json(mut self) -> Self {
70 self.json_format = JsonFormat::Compact;
71 self
72 }
73
74 pub fn path(&self) -> PathBuf {
76 self.folder_path.join(&self.file_name)
77 }
78
79 pub fn save(&self, config: &T) -> Result<()> {
81 if !self.folder_path.exists() {
82 fs::create_dir_all(&self.folder_path)?;
83 }
84
85 let content = match self.json_format {
86 JsonFormat::Compact => serde_json::to_string(config)?,
87 JsonFormat::Pretty => serde_json::to_string_pretty(config)?,
88 };
89
90 fs::write(self.path(), content)?;
91 Ok(())
92 }
93
94 pub fn load(&self) -> Result<T> {
96 let content = fs::read_to_string(self.path())?;
97 Ok(serde_json::from_str(&content)?)
98 }
99}
100
101impl<T> ConfigManager<T>
106where
107 T: Serialize + DeserializeOwned + Default,
108{
109 pub fn load_or_default(&self) -> Result<T> {
111 let path = self.path();
112
113 match fs::read_to_string(&path) {
114 Ok(content) => Ok(serde_json::from_str(&content)?),
115
116 Err(e) if e.kind() == io::ErrorKind::NotFound => {
117 let default_config = T::default();
118 self.save(&default_config)?;
119 Ok(default_config)
120 }
121
122 Err(e) => Err(ConfigError::Io(e)),
123 }
124 }
125
126 pub fn update<F>(&self, f: F) -> Result<T>
129 where
130 F: FnOnce(&mut T),
131 {
132 let mut cfg = self.load_or_default()?;
133 f(&mut cfg);
134 self.save(&cfg)?;
135 Ok(cfg)
136 }
137}