Skip to main content

SettingsManager

Struct SettingsManager 

Source
pub struct SettingsManager<S: StorageBackend = JsonStorage, Schema: SettingsSchema = ()> { /* private fields */ }
Expand description

Main settings manager and builder. Main settings manager for loading, saving, and managing application settings.

The SettingsManager provides a complete solution for application configuration:

  • Load/Save Settings: Read and write settings with schema validation
  • Sub-Settings: Manage per-entity configuration files (e.g., per-remote configs)
  • Change Events: Register callbacks for setting changes
  • Backup/Restore: Create and restore encrypted backups
  • Caching: In-memory caching for fast access
  • Secret Settings: Automatic keychain storage for sensitive values

§Example

use rcman::{SettingsManager, SettingsConfig};

// Create with builder
let config = SettingsConfig::builder("my-app", "1.0.0")
    .with_config_dir("~/.config/my-app")
    .with_credentials()  // Enable secret storage
    .build();

let manager = SettingsManager::new(config).unwrap();

§Type Parameters

  • Schema: The settings schema type (defaults to () for dynamic usage).

Implementations§

Source§

impl<S: StorageBackend + 'static, Schema: SettingsSchema> SettingsManager<S, Schema>

Source

pub fn new(config: SettingsConfig<S, Schema>) -> Result<Self>

Create a new settings manager with the given configuration.

This will create the config directory if it doesn’t exist.

§Arguments
  • config - Configuration specifying paths, app info, and storage backend
§Errors

Returns an error if the config directory cannot be created.

§Example
use rcman::{SettingsManager, SettingsConfig};

let config = SettingsConfig::builder("my-app", "1.0.0").build();
let manager = SettingsManager::new(config)?;
Source

pub fn config(&self) -> &SettingsConfig<S, Schema>

Get the configuration

Source

pub fn storage(&self) -> &S

Get the storage backend

Source

pub fn events(&self) -> &Arc<EventManager>

Get the event manager for registering change listeners and validators

Callback semantics:

  • save_setting() emits callbacks only when the effective value changes.
  • reset_setting() delegates to save_setting(), so unchanged resets emit nothing.
  • reset_all() emits one callback per changed key (no callbacks for already-default values).
  • With profiles enabled, switch_profile() emits callbacks for keys whose effective values differ between the old and new profiles.
§Example
// Watch all changes
manager.events().on_change(|key, old, new| {
    println!("Changed {}: {:?} -> {:?}", key, old, new);
});

// Watch specific key
manager.events().watch("ui.theme", |key, _old, new| {
    println!("Theme changed to: {:?}", new);
});

// Add validator
manager.events().add_validator("network.port", |v: &Value| {
    if v.as_i64().map(|n| n > 0 && n <= 65535).unwrap_or(false) {
        Ok(())
    } else {
        Err("Invalid port".into())
    }
});
Source

pub fn credentials(&self) -> Option<&CredentialManager>

Get reference to credential manager (if configured)

Source§

impl SettingsManager

Source

pub fn builder( app_name: impl Into<String>, app_version: impl Into<String>, ) -> SettingsManagerBuilder

Create a builder for SettingsManager with a fluent API.

This is the recommended way to create a SettingsManager.

§Example
use rcman::{SettingsManager, SubSettingsConfig};

let manager = SettingsManager::builder("my-app", "1.0.0")
    .with_config_dir("~/.config/my-app")
    .with_credentials()
    .with_sub_settings(SubSettingsConfig::new("remotes"))
    .build()
    .unwrap();
Source§

impl<S: StorageBackend + 'static, Schema: SettingsSchema> SettingsManager<S, Schema>

Source

pub fn invalidate_cache(&self)

Invalidate the settings cache

Call this if the settings file was modified externally.

Source

pub fn save_setting( &self, category: &str, key: &str, value: &Value, ) -> Result<()>

Save a single setting value.

This method validates the value, updates the cache, and writes to disk. If the setting is marked as secret: true and credentials are enabled, the value will be stored in the OS keychain instead of the settings file. If the value equals the default, it will be removed from storage. If the value is unchanged, no I/O occurs.

§Arguments
  • category - Category name (e.g., “ui”, “general”)
  • key - Setting key within the category (e.g., “theme”, “language”)
  • value - New value as JSON
§Errors

Returns an error if:

  • Validation fails
  • Saving to storage fails
  • Parsing the existing settings fails
Source

pub fn reset_setting(&self, category: &str, key: &str) -> Result<Value>

Reset a single setting to default

§Arguments
  • category - Category of the setting
  • key - Key of the setting
§Errors

Returns an error if:

  • The setting doesn’t exist
  • Writing to storage fails
Source

pub fn reset_all(&self) -> Result<()>

Reset all settings to defaults

§Errors

Returns an error if writing to storage fails or credential clearing fails.

Source

pub fn ensure_cache_populated(&self) -> Result<()>

Ensure the settings cache is populated

This method is thread-safe and safe to call multiple times. It uses double-checked locking to avoid unnecessary locks.

§Errors

Returns an error if the settings cannot be loaded from disk.

Source§

impl<S: StorageBackend + 'static, Schema: SettingsSchema> SettingsManager<S, Schema>

Source

pub fn metadata(&self) -> Result<HashMap<String, SettingMetadata>>

Get all setting metadata with current values populated.

Returns a HashMap of all settings with their metadata (type, label, default, current value). Useful for rendering settings UI.

Returns metadata map with current values populated. Uses in-memory cache when available.

§Errors

Returns an error if:

  • Storage read fails
  • Data is corrupted
Source

pub fn get<T>(&self, key: &str) -> Result<T>

Get a single setting value by key path.

§Type Parameters
  • T - The type to deserialize the value into
§Arguments
  • key - Setting key in “category.name” format (e.g., “general.restrict”)
§Errors

Returns an error if:

  • The setting doesn’t exist (and no default)
  • The value cannot be deserialized to type T
  • Storage read fails
Source

pub fn get_value(&self, key: &str) -> Result<Value>

Get raw JSON value for a setting key.

Returns the value from merged settings cache, or from keyring if it’s a secret.

§Arguments
  • key - Setting key in “category.name” format
§Errors

Returns an error if:

  • The setting key format is invalid
  • The setting doesn’t exist
  • Storage read fails
Source

pub fn get_all(&self) -> Result<Schema>

Get merged settings struct with caching.

§Errors

Returns an error if settings cannot be read or parsed.

Source

pub fn register_sub_settings(&self, config: SubSettingsConfig) -> Result<()>

Register a sub-settings type for per-entity configuration.

Sub-settings allow you to manage separate config files for each entity (e.g., one file per remote, per profile, etc.).

§Errors

Returns an error if the sub-settings handler cannot be initialized (e.g. invalid path).

Source

pub fn sub_settings(&self, name: &str) -> Result<Arc<SubSettings<S>>>

Get a registered sub-settings handler.

Returns the handler for the specified sub-settings type, which can be used to read, write, and manage individual entries.

§Arguments
  • name - The name of the sub-settings type to get
§Errors

Returns Error::SubSettingsNotFound if the sub-settings type is not registered.

Source

pub fn has_sub_settings(&self, name: &str) -> bool

Check if a sub-settings type exists

Source

pub fn sub_settings_types(&self) -> Vec<String>

List all registered sub-settings types

Source

pub fn list_sub_settings(&self, name: &str) -> Result<Vec<String>>

List all entries in a sub-settings type (convenience method)

This is a shorthand for manager.sub_settings(name)?.list()?

§Arguments
  • name - The name of the sub-settings type to list
§Errors

Returns Error::SubSettingsNotFound if the type is not registered, or I/O errors from the handler.

Source

pub fn register_external_provider( &self, provider: Box<dyn ExternalConfigProvider>, )

Register an external config provider for backups.

This allows dynamic registration of external files to be included in backups.

Source

pub fn backup(&self) -> BackupManager<'_, S, Schema>

Get the backup manager

Source

pub fn external_configs(&self) -> &[ExternalConfig]

Get all registered external configs

Returns the external config files that were registered via SettingsConfig::builder().with_external_config(...).

Source

pub fn get_export_categories(&self) -> Vec<ExportCategory>

Get all export categories for backup UI

Returns a list of all exportable categories:

  • Settings (main settings.json)
  • Sub-settings (each registered sub-settings type)
  • External configs (each registered external file)
Source§

impl<S: StorageBackend + 'static, Schema: SettingsSchema> SettingsManager<S, Schema>

Source

pub fn is_profiles_enabled(&self) -> bool

Check if profiles are enabled for main settings

Source

pub fn profiles(&self) -> Option<&ProfileManager<S>>

Get the profile manager for main settings

Returns None if profiles are not enabled for main settings.

Source

pub fn switch_profile(&self, name: &str) -> Result<()>

Switch to a different profile

This switches the active profile for main settings and updates internal paths. All subsequent operations will use the new profile’s settings.

If change listeners are registered via events().on_change(...), this emits callbacks for keys whose effective values differ between the previous and new active profile.

§Arguments
  • name - The name of the profile to switch to
§Errors

Returns an error if:

  • Profiles are not enabled for this manager
  • The profile does not exist
  • The profile switch fails (e.g. IO error)
Source

pub fn create_profile(&self, name: &str) -> Result<()>

Create a new profile for main settings

§Arguments
  • name - The name of the profile to create
§Errors

Returns an error if:

  • Profiles are not enabled
  • The profile already exists
  • Creation fails (e.g. IO error)
Source

pub fn list_profiles(&self) -> Result<Vec<String>>

List all available profiles

§Errors

Returns an error if profiles are not enabled or reading the profile list fails.

Source

pub fn active_profile(&self) -> Result<String>

Get the active profile name

§Errors

Returns an error if profiles are not enabled or determining the active profile fails.

Auto Trait Implementations§

§

impl<S = JsonStorage, Schema = ()> !Freeze for SettingsManager<S, Schema>

§

impl<S = JsonStorage, Schema = ()> !RefUnwindSafe for SettingsManager<S, Schema>

§

impl<S, Schema> Send for SettingsManager<S, Schema>
where Schema: Send,

§

impl<S, Schema> Sync for SettingsManager<S, Schema>
where Schema: Sync,

§

impl<S, Schema> Unpin for SettingsManager<S, Schema>
where S: Unpin, Schema: Unpin,

§

impl<S, Schema> UnsafeUnpin for SettingsManager<S, Schema>
where S: UnsafeUnpin,

§

impl<S = JsonStorage, Schema = ()> !UnwindSafe for SettingsManager<S, Schema>

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> 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> Same for T

Source§

type Output = T

Should always be Self
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.