Skip to main content

ConfigManager

Struct ConfigManager 

Source
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>

Source

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?
examples/update.rs (line 21)
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
Hide additional examples
examples/basic.rs (line 31)
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}
examples/custom_root.rs (line 24)
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

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.

Source

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.

Source

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?
examples/update.rs (line 22)
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
Hide additional examples
examples/basic.rs (line 32)
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}
examples/custom_root.rs (line 25)
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

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.

Source

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.

Source

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?
examples/update.rs (line 23)
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
Hide additional examples
examples/basic.rs (line 33)
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}
examples/custom_root.rs (line 26)
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

pub fn disable_pretty_json(self) -> Self

Stores JSON in compact form instead of pretty-printed form.

Source

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.

Source

pub fn with_direct_save(self) -> Self

Selects direct overwrite saves.

This is a convenience alias for with_save_mode(SaveMode::Direct).

Source

pub fn save_mode(&self) -> SaveMode

Returns the configured save strategy.

Source

pub fn folder_path(&self) -> &Path

Returns the settings folder path.

Source

pub fn file_name(&self) -> &str

Returns the settings file name.

Source

pub fn path(&self) -> PathBuf

Returns the settings file path.

Examples found in repository?
examples/update.rs (line 32)
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
Hide additional examples
examples/basic.rs (line 37)
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}
examples/custom_root.rs (line 38)
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

pub fn save(&self, config: &T) -> Result<()>

Saves the complete configuration, replacing the existing file content.

Examples found in repository?
examples/custom_root.rs (line 34)
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

pub fn load(&self) -> Result<T>

Loads a configuration file that is expected to already exist.

Source§

impl<T> ConfigManager<T>

Source

pub fn load_or_default(&self) -> Result<T>

Loads the configuration, or creates and saves T::default() on first run.

Examples found in repository?
examples/basic.rs (line 35)
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
Hide additional examples
examples/custom_root.rs (line 28)
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

pub fn update<F>(&self, f: F) -> Result<T>
where F: FnOnce(&mut T),

Applies a read-modify-write update and saves the result.

Examples found in repository?
examples/update.rs (lines 25-30)
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>

Source§

fn clone(&self) -> ConfigManager<T>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for ConfigManager<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Default for ConfigManager<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> Freeze for ConfigManager<T>

§

impl<T> RefUnwindSafe for ConfigManager<T>
where T: RefUnwindSafe,

§

impl<T> Send for ConfigManager<T>
where T: Send,

§

impl<T> Sync for ConfigManager<T>
where T: Sync,

§

impl<T> Unpin for ConfigManager<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for ConfigManager<T>

§

impl<T> UnwindSafe for ConfigManager<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.