pub struct SettingsManager {
settings_dir: PathBuf,
manifest_path: PathBuf,
current_version: String,
build_uuid: String,
root_dir: PathBuf,
}Expand description
Manages versioned settings files and migrations.
Fields§
§settings_dir: PathBuf§manifest_path: PathBuf§current_version: String§build_uuid: String§root_dir: PathBufImplementations§
Source§impl SettingsManager
impl SettingsManager
Sourcepub fn new(current_version: String) -> Self
pub fn new(current_version: String) -> Self
Creates a new settings manager.
§Arguments
current_version- The current application version (e.g., fromGIT_VERSION)
The build UUID is automatically obtained from the compile-time BUILD_UUID
environment variable set by the core crate’s build script.
§Example
use cadmus_core::settings::versioned::SettingsManager;
let manager = SettingsManager::new(env!("GIT_VERSION").to_string());Sourcepub fn load(&self) -> Settings
pub fn load(&self) -> Settings
Loads settings from the versioned storage, migrating if necessary.
This function is designed to be maximally resilient:
- Creates Settings directory if it doesn’t exist
- Attempts to migrate legacy Settings.toml if it exists (non-fatal if it fails)
- Reads the manifest to find the appropriate settings file
- Loads and deserializes the settings
The manifest is searched for an entry matching the current version. If no exact match exists, the entry with the most recent UUID is used. If the manifest is empty, default settings are returned.
§Returns
Returns Settings in all cases:
- Loaded from versioned file if available
- Loaded from most recent version if exact match not found
- Default settings if no versions exist or all file reads fail
Never fails - returns defaults as ultimate fallback.
§Diagnostic Output
This function uses println! and eprintln! for diagnostic messages
instead of tracing::* macros because logging/tracing is not yet
configured at this point in the app startup sequence. Tracing is
configured after settings are loaded, so using tracing macros here
would result in messages being silently dropped or not properly routed.
Sourcepub fn save(&self, settings: &Settings) -> Result<(), Error>
pub fn save(&self, settings: &Settings) -> Result<(), Error>
Saves settings to a versioned file and updates the manifest.
This function:
- Creates a new Settings-
.toml file - Updates the manifest with new entry
- Removes old files exceeding retention limit
§Arguments
settings- The settings to save
§Errors
Returns an error if:
- Settings file cannot be written
- Manifest cannot be updated
- Old files cannot be removed
Sourcefn migrate_legacy_settings(&self)
fn migrate_legacy_settings(&self)
Migrates legacy Settings.toml from the root directory to the new versioned format.
This method is automatically called during load() to handle upgrades from the
old settings system. If a legacy Settings.toml file exists in the application’s
root directory, it is:
- Loaded with all existing settings preserved
- Saved to the new versioned location:
Settings/Settings-v<version>.toml - Registered in the manifest as a historical entry
- Deleted to prevent accidental duplication
§Behavior
This method is fully non-fatal:
- If the legacy file doesn’t exist, returns silently (success)
- If the legacy file can’t be read, logs a warning and returns (failure is acceptable)
- If any write operation fails (save, manifest update, deletion), logs a warning but continues - the important part is reading the legacy settings, not cleanup
Never propagates errors because migration is opportunistic, not required for the app to function.
§Diagnostic Output
This function uses println! and eprintln! for diagnostic messages
instead of tracing::* macros because logging/tracing is not yet
configured during the settings loading phase (called from load()).
Tracing is initialized after settings are fully loaded, so any
tracing calls here would be silently discarded.
Sourcefn read_manifest(&self) -> Result<SettingsManifest, Error>
fn read_manifest(&self) -> Result<SettingsManifest, Error>
Reads the settings manifest from disk.
The manifest file (.cadmus-index.toml) tracks all known settings versions
and their metadata. This method loads the current manifest or returns a default
empty manifest if the file doesn’t exist.
§Returns
Ok(SettingsManifest) containing:
- All known settings file entries in order
- Version information and timestamps for each entry
Err if the manifest file exists but cannot be read or parsed.
Sourcefn write_manifest(&self, manifest: &SettingsManifest) -> Result<(), Error>
fn write_manifest(&self, manifest: &SettingsManifest) -> Result<(), Error>
Writes the settings manifest to disk.
Persists the manifest file (.cadmus-index.toml) with all settings version
entries and their metadata. This is called after any changes to the manifest
(migration, version updates, cleanup).
§Arguments
manifest- The manifest to write to disk
§Returns
Ok(()) if the manifest was successfully written.
Err if the manifest file cannot be written or serialized.
Sourcefn update_manifest_and_cleanup(
&self,
filename: &str,
settings: &Settings,
) -> Result<(), Error>
fn update_manifest_and_cleanup( &self, filename: &str, settings: &Settings, ) -> Result<(), Error>
Updates the manifest with a new settings version entry and cleans up old files.
This is called during save() when settings are persisted to a new versioned file.
Combines manifest update and cleanup into a single I/O pass to minimize filesystem
operations on embedded devices with slow storage.
The process:
- Reads the current manifest (single read)
- Creates a new entry for the current version with timestamp
- Removes any existing entry for the same version (deduplication)
- Appends the new entry
- Partitions entries to protect current version from cleanup
- Removes old files exceeding retention limit (only from other versions)
- Writes the updated manifest once (single write)
§Data Integrity
The current version’s entry is never removed, regardless of its UUID. This prevents silent data loss during version downgrades where an older build UUID would sort to the front and be considered “oldest” for cleanup purposes.
§Arguments
filename- The filename of the new settings file (relative to Settings directory)settings- The settings containing thesettings_retentionconfiguration
§Returns
Ok(()) if the manifest was successfully updated and written.
Err if reading, updating, or writing the manifest fails.
Trait Implementations§
Source§impl Clone for SettingsManager
impl Clone for SettingsManager
Source§fn clone(&self) -> SettingsManager
fn clone(&self) -> SettingsManager
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for SettingsManager
impl RefUnwindSafe for SettingsManager
impl Send for SettingsManager
impl Sync for SettingsManager
impl Unpin for SettingsManager
impl UnwindSafe for SettingsManager
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.