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 app_name: String,
21 folder_path: PathBuf,
22 file_name: String,
23 json_format: JsonFormat,
24 _marker: PhantomData<T>,
25}
26
27impl<T> ConfigManager<T>
28where
29 T: Serialize + DeserializeOwned,
30{
31 pub fn new() -> Self {
34 let folder_path = default_config_dir();
35
36 let app_name = std::env::current_exe()
37 .unwrap_or_default()
38 .file_name()
39 .unwrap_or_default()
40 .to_string_lossy()
41 .to_string();
42
43 Self {
44 app_name,
45 folder_path,
46 file_name: DEFAULT_FILE_NAME.to_string(),
47 json_format: JsonFormat::Pretty,
48 _marker: PhantomData,
49 }
50 }
51
52 pub fn at_current_dir(mut self) -> Self {
54 self.folder_path = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
55 self
56 }
57
58 pub fn at_custom_dir<P: Into<PathBuf>>(mut self, path: P) -> Self {
60 self.folder_path = path.into();
61 self
62 }
63
64 pub fn with_filename(mut self, name: &str) -> Self {
66 self.file_name = name.to_string();
67 self
68 }
69
70 pub fn disable_pretty_json(mut self) -> Self {
72 self.json_format = JsonFormat::Compact;
73 self
74 }
75
76 pub fn path(&self) -> PathBuf {
78 self.folder_path.join(&self.app_name).join(&self.file_name)
79 }
80
81 pub fn save(&self, config: &T) -> Result<()> {
83 if !self.folder_path.exists() {
84 fs::create_dir_all(&self.folder_path)?;
85 }
86
87 let content = match self.json_format {
88 JsonFormat::Compact => serde_json::to_string(config)?,
89 JsonFormat::Pretty => serde_json::to_string_pretty(config)?,
90 };
91
92 fs::write(self.path(), content)?;
93 Ok(())
94 }
95
96 pub fn load(&self) -> Result<T> {
98 let content = fs::read_to_string(self.path())?;
99 Ok(serde_json::from_str(&content)?)
100 }
101}
102
103impl<T> ConfigManager<T>
108where
109 T: Serialize + DeserializeOwned + Default,
110{
111 pub fn load_or_default(&self) -> Result<T> {
113 let path = self.path();
114
115 match fs::read_to_string(&path) {
116 Ok(content) => Ok(serde_json::from_str(&content)?),
117
118 Err(e) if e.kind() == io::ErrorKind::NotFound => {
119 let default_config = T::default();
120 self.save(&default_config)?;
121 Ok(default_config)
122 }
123
124 Err(e) => Err(ConfigError::Io(e)),
125 }
126 }
127
128 pub fn update<F>(&self, f: F) -> Result<T>
131 where
132 F: FnOnce(&mut T),
133 {
134 let mut cfg = self.load_or_default()?;
135 f(&mut cfg);
136 self.save(&cfg)?;
137 Ok(cfg)
138 }
139}