Trait veloren_server::settings::EditableSetting
source · pub trait EditableSetting: Clone + Default {
type Error: Debug;
type Legacy: Serialize + DeserializeOwned + Into<Self>;
type Setting: Serialize + DeserializeOwned + TryInto<(Version, Self), Error = Self::Error> + From<Self>;
const FILENAME: &'static str;
// Provided methods
fn load(data_dir: &Path) -> Self { ... }
fn edit<R>(
&mut self,
data_dir: &Path,
f: impl FnOnce(&mut Self) -> Option<R>,
) -> Option<(R, Result<(), Error<Self>>)> { ... }
fn get_path(data_dir: &Path) -> PathBuf { ... }
}
Required Associated Types§
sourcetype Error: Debug
type Error: Debug
Please use this error sparingly, since we ideally want to preserve forwards compatibility for all migrations. In particular, this error should be used to fail validation of the original settings file that cannot be caught with ordinary parsing, rather than used to signal errors that occurred during migrations.
The best error type is Infallible.
sourcetype Legacy: Serialize + DeserializeOwned + Into<Self>
type Legacy: Serialize + DeserializeOwned + Into<Self>
IntoInto
here
rather than TryInto is intended (together with the expected use of
chaining) to prevent migrations from invalidating old save files
without warning; there should always be a non-failing migration path
from the oldest to latest format (if the migration path fails, we can
panic).
sourcetype Setting: Serialize + DeserializeOwned + TryInto<(Version, Self), Error = Self::Error> + From<Self>
type Setting: Serialize + DeserializeOwned + TryInto<(Version, Self), Error = Self::Error> + From<Self>
TryInto<(Version, Self)> is expected to migrate to the latest version from any older version, using “chaining” (see super::banlist for examples).
From
The error should be used to fail validation of the original settings file that cannot be caught with parsing. If we can possibly avoid it, we should not create errors in valid settings files during migration, to ensure forwards compatibility.
Required Associated Constants§
Provided Methods§
fn load(data_dir: &Path) -> Self
sourcefn edit<R>(
&mut self,
data_dir: &Path,
f: impl FnOnce(&mut Self) -> Option<R>,
) -> Option<(R, Result<(), Error<Self>>)>
fn edit<R>( &mut self, data_dir: &Path, f: impl FnOnce(&mut Self) -> Option<R>, ) -> Option<(R, Result<(), Error<Self>>)>
If the result of calling f is None, we return None (this constitutes an early return and lets us abandon the in-progress edit). For example, this can be used to avoid adding a new ban entry if someone is already banned and the user didn’t explicitly specify that they wanted to add a new ban record, even though it would be completely valid to attach one.
Otherwise (the result of calling f was Some(r)), we always return Some((r, res)), where:
If res is Ok(()), validation succeeded for the edited, and changes made inside the closure are applied both in memory (to self) and atomically on disk.
Otherwise (res is Err(e)), some step in the edit process failed. Specifically:
- If e is Integrity, validation failed and the settings were not updated.
- If e is Io, validation succeeded and the settings were updated in memory, but they could not be saved to storage (and a warning was logged). The reason we return an error even though the operation was partially successful is so we can alert the player who ran the command about the failure, as they will often be an administrator who can usefully act upon that information.