pub struct ConfigManager<T> { /* private fields */ }Expand description
Manages one typed JSON settings file.
ConfigManager<T> stores and loads a complete configuration value of type
T. The type must implement Serde Serialize and DeserializeOwned.
The manager is intentionally small. It owns only:
- the directory containing the settings file,
- the settings file name,
- the JSON output format, and
- the save strategy.
Implementations§
Source§impl<T> ConfigManager<T>where
T: Serialize + DeserializeOwned,
impl<T> ConfigManager<T>where
T: Serialize + DeserializeOwned,
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a config manager using the OS-standard config directory and the current executable name.
On Windows desktop apps this resolves under %APPDATA%. Pure UWP apps
should use with_root_dir or the optional
uwp feature instead.
This constructor cannot report storage-root resolution failure without
an API break, so it falls back to the current directory when the
platform configuration directory cannot be determined (for example, no
HOME or %APPDATA% in the environment). For production applications,
prefer for_app: it uses an explicit stable
application identity instead of deriving one from the executable file
name, and it reports resolution failure instead of silently falling
back.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 let root = std::env::temp_dir().join("app-json-settings-update-example");
21 let manager = ConfigManager::<AppSettings>::new()
22 .with_root_dir(root)
23 .try_with_filename("settings.json")?;
24
25 let updated = manager.update(|settings| {
26 settings.launch_count += 1;
27 if settings.theme.is_empty() {
28 settings.theme = "system".to_string();
29 }
30 })?;
31
32 println!("settings path: {}", manager.path().display());
33 println!("launch count: {}", updated.launch_count);
34 println!("theme: {}", updated.theme);
35
36 Ok(())
37}More examples
23fn main() -> app_json_settings::Result<()> {
24 // The production desktop form is usually:
25 //
26 // let manager = ConfigManager::<AppSettings>::for_app("my-gui-app")?;
27 //
28 // This example uses a temporary root so running it does not write to your
29 // real app settings directory.
30 let root = std::env::temp_dir().join("app-json-settings-basic-example");
31 let manager = ConfigManager::<AppSettings>::new()
32 .with_root_dir(root)
33 .try_with_filename("settings.json")?;
34
35 let settings = manager.load_or_default()?;
36
37 println!("settings path: {}", manager.path().display());
38 println!("theme: {}", settings.theme);
39 println!(
40 "window: {}x{}",
41 settings.window_width, settings.window_height
42 );
43
44 Ok(())
45}19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Sourcepub fn for_app(app_name: &str) -> Result<Self>
pub fn for_app(app_name: &str) -> Result<Self>
Creates a config manager for an explicit application name.
This is the recommended desktop constructor for production apps because
the storage directory is stable even if the executable file name changes.
The app_name must be a single safe path component, not a path.
Returns ConfigError::Platform if the platform configuration
directory cannot be resolved (for example, no HOME or %APPDATA% in
the environment). Applications that hit this in practice — typically
services or containers without a user environment — should supply a
path explicitly with with_root_dir instead.
Sourcepub fn at_current_dir(self) -> Self
pub fn at_current_dir(self) -> Self
Stores the settings file in the current working directory.
If the current working directory cannot be determined, falls back to
".". Unlike for_app, this fallback is not
surprising here: the caller explicitly asked for working-directory
storage, and "." already means “the working directory” to the
filesystem.
Sourcepub fn with_root_dir<P: Into<PathBuf>>(self, path: P) -> Self
pub fn with_root_dir<P: Into<PathBuf>>(self, path: P) -> Self
Stores the settings file in a caller-provided directory.
This is the primary compatibility seam for sandboxed hosts, including Pure UWP. The host application may resolve its application data directory and pass it here.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 let root = std::env::temp_dir().join("app-json-settings-update-example");
21 let manager = ConfigManager::<AppSettings>::new()
22 .with_root_dir(root)
23 .try_with_filename("settings.json")?;
24
25 let updated = manager.update(|settings| {
26 settings.launch_count += 1;
27 if settings.theme.is_empty() {
28 settings.theme = "system".to_string();
29 }
30 })?;
31
32 println!("settings path: {}", manager.path().display());
33 println!("launch count: {}", updated.launch_count);
34 println!("theme: {}", updated.theme);
35
36 Ok(())
37}More examples
23fn main() -> app_json_settings::Result<()> {
24 // The production desktop form is usually:
25 //
26 // let manager = ConfigManager::<AppSettings>::for_app("my-gui-app")?;
27 //
28 // This example uses a temporary root so running it does not write to your
29 // real app settings directory.
30 let root = std::env::temp_dir().join("app-json-settings-basic-example");
31 let manager = ConfigManager::<AppSettings>::new()
32 .with_root_dir(root)
33 .try_with_filename("settings.json")?;
34
35 let settings = manager.load_or_default()?;
36
37 println!("settings path: {}", manager.path().display());
38 println!("theme: {}", settings.theme);
39 println!(
40 "window: {}x{}",
41 settings.window_width, settings.window_height
42 );
43
44 Ok(())
45}19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Sourcepub fn at_custom_dir<P: Into<PathBuf>>(self, path: P) -> Self
pub fn at_custom_dir<P: Into<PathBuf>>(self, path: P) -> Self
Stores the settings file in a caller-provided directory.
This method is kept for compatibility with v2.0.x. Prefer
with_root_dir in new code.
Sourcepub fn with_filename(self, name: &str) -> Self
pub fn with_filename(self, name: &str) -> Self
Changes the settings file name without validation.
This method is retained for v2.x compatibility. New code should prefer
try_with_filename, which rejects path-like
names such as ../settings.json.
Sourcepub fn try_with_filename(self, name: &str) -> Result<Self>
pub fn try_with_filename(self, name: &str) -> Result<Self>
Changes the settings file name after validating it as a plain file name.
The accepted value must be a single file name, not an absolute path and not a relative path containing directory traversal.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 let root = std::env::temp_dir().join("app-json-settings-update-example");
21 let manager = ConfigManager::<AppSettings>::new()
22 .with_root_dir(root)
23 .try_with_filename("settings.json")?;
24
25 let updated = manager.update(|settings| {
26 settings.launch_count += 1;
27 if settings.theme.is_empty() {
28 settings.theme = "system".to_string();
29 }
30 })?;
31
32 println!("settings path: {}", manager.path().display());
33 println!("launch count: {}", updated.launch_count);
34 println!("theme: {}", updated.theme);
35
36 Ok(())
37}More examples
23fn main() -> app_json_settings::Result<()> {
24 // The production desktop form is usually:
25 //
26 // let manager = ConfigManager::<AppSettings>::for_app("my-gui-app")?;
27 //
28 // This example uses a temporary root so running it does not write to your
29 // real app settings directory.
30 let root = std::env::temp_dir().join("app-json-settings-basic-example");
31 let manager = ConfigManager::<AppSettings>::new()
32 .with_root_dir(root)
33 .try_with_filename("settings.json")?;
34
35 let settings = manager.load_or_default()?;
36
37 println!("settings path: {}", manager.path().display());
38 println!("theme: {}", settings.theme);
39 println!(
40 "window: {}x{}",
41 settings.window_width, settings.window_height
42 );
43
44 Ok(())
45}19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Sourcepub fn disable_pretty_json(self) -> Self
pub fn disable_pretty_json(self) -> Self
Stores JSON in compact form instead of pretty-printed form.
Sourcepub fn with_save_mode(self, mode: SaveMode) -> Self
pub fn with_save_mode(self, mode: SaveMode) -> Self
Selects the save strategy.
The default is SaveMode::Atomic. Use SaveMode::Direct only when
an application intentionally wants v2.2-style direct overwrite behavior
or needs to work around unusual filesystem semantics.
Sourcepub fn with_direct_save(self) -> Self
pub fn with_direct_save(self) -> Self
Selects direct overwrite saves.
This is a convenience alias for with_save_mode(SaveMode::Direct).
Sourcepub fn folder_path(&self) -> &Path
pub fn folder_path(&self) -> &Path
Returns the settings folder path.
Sourcepub fn path(&self) -> PathBuf
pub fn path(&self) -> PathBuf
Returns the settings file path.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 let root = std::env::temp_dir().join("app-json-settings-update-example");
21 let manager = ConfigManager::<AppSettings>::new()
22 .with_root_dir(root)
23 .try_with_filename("settings.json")?;
24
25 let updated = manager.update(|settings| {
26 settings.launch_count += 1;
27 if settings.theme.is_empty() {
28 settings.theme = "system".to_string();
29 }
30 })?;
31
32 println!("settings path: {}", manager.path().display());
33 println!("launch count: {}", updated.launch_count);
34 println!("theme: {}", updated.theme);
35
36 Ok(())
37}More examples
23fn main() -> app_json_settings::Result<()> {
24 // The production desktop form is usually:
25 //
26 // let manager = ConfigManager::<AppSettings>::for_app("my-gui-app")?;
27 //
28 // This example uses a temporary root so running it does not write to your
29 // real app settings directory.
30 let root = std::env::temp_dir().join("app-json-settings-basic-example");
31 let manager = ConfigManager::<AppSettings>::new()
32 .with_root_dir(root)
33 .try_with_filename("settings.json")?;
34
35 let settings = manager.load_or_default()?;
36
37 println!("settings path: {}", manager.path().display());
38 println!("theme: {}", settings.theme);
39 println!(
40 "window: {}x{}",
41 settings.window_width, settings.window_height
42 );
43
44 Ok(())
45}19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Sourcepub fn save(&self, config: &T) -> Result<()>
pub fn save(&self, config: &T) -> Result<()>
Saves the complete configuration, replacing the existing file content.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Source§impl<T> ConfigManager<T>
impl<T> ConfigManager<T>
Sourcepub fn load_or_default(&self) -> Result<T>
pub fn load_or_default(&self) -> Result<T>
Loads the configuration, or creates and saves T::default() on first run.
Examples found in repository?
23fn main() -> app_json_settings::Result<()> {
24 // The production desktop form is usually:
25 //
26 // let manager = ConfigManager::<AppSettings>::for_app("my-gui-app")?;
27 //
28 // This example uses a temporary root so running it does not write to your
29 // real app settings directory.
30 let root = std::env::temp_dir().join("app-json-settings-basic-example");
31 let manager = ConfigManager::<AppSettings>::new()
32 .with_root_dir(root)
33 .try_with_filename("settings.json")?;
34
35 let settings = manager.load_or_default()?;
36
37 println!("settings path: {}", manager.path().display());
38 println!("theme: {}", settings.theme);
39 println!(
40 "window: {}x{}",
41 settings.window_width, settings.window_height
42 );
43
44 Ok(())
45}More examples
19fn main() -> app_json_settings::Result<()> {
20 // Caller-provided roots are useful for portable apps, tests, sandboxed
21 // hosts, and UWP-style apps where the host resolves its own local folder.
22 let root = std::env::temp_dir().join("app-json-settings-custom-root-example");
23
24 let manager = ConfigManager::<PortableSettings>::new()
25 .with_root_dir(&root)
26 .try_with_filename("preferences.json")?;
27
28 let mut settings = manager.load_or_default()?;
29
30 if settings.recent_files.is_empty() {
31 settings
32 .recent_files
33 .push("/example/documents/readme.md".to_string());
34 manager.save(&settings)?;
35 }
36
37 println!("custom root: {}", root.display());
38 println!("settings file: {}", manager.path().display());
39 println!("recent files: {:?}", settings.recent_files);
40
41 Ok(())
42}Sourcepub fn update<F>(&self, f: F) -> Result<T>
pub fn update<F>(&self, f: F) -> Result<T>
Applies a read-modify-write update and saves the result.
Examples found in repository?
19fn main() -> app_json_settings::Result<()> {
20 let root = std::env::temp_dir().join("app-json-settings-update-example");
21 let manager = ConfigManager::<AppSettings>::new()
22 .with_root_dir(root)
23 .try_with_filename("settings.json")?;
24
25 let updated = manager.update(|settings| {
26 settings.launch_count += 1;
27 if settings.theme.is_empty() {
28 settings.theme = "system".to_string();
29 }
30 })?;
31
32 println!("settings path: {}", manager.path().display());
33 println!("launch count: {}", updated.launch_count);
34 println!("theme: {}", updated.theme);
35
36 Ok(())
37}Trait Implementations§
Source§impl<T: Clone> Clone for ConfigManager<T>
impl<T: Clone> Clone for ConfigManager<T>
Source§fn clone(&self) -> ConfigManager<T>
fn clone(&self) -> ConfigManager<T>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more