pub struct PersistedLazy<S, K, C>{ /* private fields */ }Expand description
Similar to Persisted, but the value that’s sent to the store is not the same as the value stored in memory. Instead, the value is computed at save time by PersistedContainer::get_to_persist. Similarly, the persisted value that’s loaded at initialization isn’t stored directly in the container. Instead, PersistedContainer::restore_persisted determines how to initialize state based on it.
This is useful if the value you want to store is some derivation of the value you keep in memory. For example, storing which item in a list is selected: if you store the index of the selected item in memory but want to persist the ID of the selected item so it’s resilient to re-ordering, you can use this.
§Generic Params
S: The backend type used to persist data. While we don’t need access to an instance of the backend, we do need to know its type so we can access its static functions on setup/save.K: The type of the persistence keyC: The type of the wrapping container (see PersistedContainer). The type of the container’s persisted value must match the expected value for the key. In other words,K::Valuemust equalC::Value.
§Accessing
The inner value can be accessed immutably via Deref. To get mutable
access, use PersistedLazy::get_mut. This wrapper method returns a guard
that implements DerefMut (similar to RefMut or MutexGuard from std,
without the internal mutability). When your mutable access is complete, this
wrapper will be dropped and the value will be persisted to the store only
if it changed (according to its PartialEq impl).
§Cloning
This type intentionally does not implement Clone. Cloning would result in two containers with the same key. Whenever a modification is made to one it will overwrite the persistence slot. It’s unlikely this is the desired behavior, and therefore is not provided.
§Example
use persisted::{
PersistedContainer, PersistedKey, PersistedLazy, PersistedStore,
};
use core::cell::Cell;
/// Persist just the stored ID
#[derive(Default)]
struct Store(Cell<Option<PersonId>>);
impl Store {
thread_local! {
static INSTANCE: Store = Default::default();
}
}
impl PersistedStore<SelectedIdKey> for Store {
fn load_persisted(_key: &SelectedIdKey) -> Option<PersonId> {
Self::INSTANCE.with(|store| store.0.get())
}
fn store_persisted(_key: &SelectedIdKey, value: &PersonId) {
Self::INSTANCE.with(|store| store.0.set(Some(*value)))
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
struct PersonId(u64);
#[derive(Clone, Debug)]
#[allow(unused)]
struct Person {
id: PersonId,
name: String,
age: u32,
}
#[derive(Debug, PersistedKey)]
#[persisted(PersonId)]
struct SelectedIdKey;
/// A list of items, with one item selected
struct SelectList {
values: Vec<Person>,
selected_index: usize,
}
impl SelectList {
fn selected(&self) -> &Person {
&self.values[self.selected_index]
}
}
impl PersistedContainer for SelectList {
type Value = PersonId;
fn get_to_persist(&self) -> Self::Value {
self.selected().id
}
fn restore_persisted(&mut self, value: Self::Value) {
// Find selected person by ID
self.selected_index = self
.values
.iter()
.enumerate()
.find(|(_, person)| person.id == value)
.map(|(i, _)| i)
.unwrap_or_default();
}
}
let person_list = vec![
Person {
id: PersonId(23089),
name: "Fred".into(),
age: 17,
},
Person {
id: PersonId(28833),
name: "Susan".into(),
age: 29,
},
Person {
id: PersonId(93383),
name: "Ulysses".into(),
age: 40,
},
];
let mut people = PersistedLazy::<Store, _, _>::new(
SelectedIdKey,
SelectList {
values: person_list.clone(),
selected_index: 0,
},
);
people.get_mut().selected_index = 1;
assert_eq!(people.selected().id.0, 28833);
let people = PersistedLazy::<Store, _, _>::new(
SelectedIdKey,
SelectList {
values: person_list,
selected_index: 0,
},
);
// The previous value was restored
assert_eq!(people.selected_index, 1);
assert_eq!(people.selected().id.0, 28833);Implementations§
Source§impl<S, K, C> PersistedLazy<S, K, C>
impl<S, K, C> PersistedLazy<S, K, C>
Sourcepub fn new(key: K, container: C) -> Self
pub fn new(key: K, container: C) -> Self
Initialize a given container whose value will lazily be loaded and persisted. If a persisted value is available in the store, it will be loaded and used to initialize the container via PersistedContainer::restore_persisted.
Sourcepub fn new_default(key: K) -> Selfwhere
C: Default,
pub fn new_default(key: K) -> Selfwhere
C: Default,
Initialize a new default container whose value will lazily be loaded and persisted. If a persisted value is available in the store, it will be loaded and used to initialize the container via PersistedContainer::restore_persisted.
Sourcepub fn get_mut(&mut self) -> PersistedLazyRefMut<'_, S, K, C>
pub fn get_mut(&mut self) -> PersistedLazyRefMut<'_, S, K, C>
Get a mutable reference to the value. This is wrapped by a guard, so
that after mutation when the guard is dropped, the value can be
persisted. PersistedStore::store_persisted will only be called if the
persisted value actually changed, hence the K::Value: PartialEq bound.
This means PersistedContainer::get_to_persist will be called after
event mutable access, but the value will only be written to the store
when it’s been modified.