linera_persistent/
lib.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5This crate handles persisting data types to disk with a variety of backends.
6*/
7
8#![allow(async_fn_in_trait)]
9
10mod dirty;
11use dirty::Dirty;
12
13cfg_if::cfg_if! {
14    if #[cfg(with_indexed_db)] {
15        pub mod indexed_db;
16        pub use indexed_db::IndexedDb;
17    }
18}
19
20cfg_if::cfg_if! {
21    if #[cfg(feature = "fs")] {
22        pub mod file;
23        pub use file::File;
24    }
25}
26
27pub mod memory;
28use std::ops::Deref;
29
30pub use memory::Memory;
31
32/// The `Persist` trait provides a wrapper around a value that can be saved in a
33/// persistent way. A minimal implementation provides an `Error` type, a `persist`
34/// function to persist the value, and an `as_mut` function to get a mutable reference to
35/// the value in memory.
36#[cfg_attr(not(web), trait_variant::make(Send))]
37pub trait Persist: Deref {
38    type Error: std::error::Error + Send + Sync + 'static;
39
40    /// Gets a mutable reference to the value. This is not expressed as a
41    /// [`DerefMut`](std::ops::DerefMut) bound because it is discouraged to use this
42    /// function! Instead, use `mutate`.
43    fn as_mut(&mut self) -> &mut Self::Target;
44
45    /// Saves the value to persistent storage.
46    async fn persist(&mut self) -> Result<(), Self::Error>;
47
48    /// Takes the value out.
49    fn into_value(self) -> Self::Target
50    where
51        Self::Target: Sized;
52}
53
54#[cfg_attr(not(web), trait_variant::make(Send))]
55pub trait PersistExt: Persist {
56    /// Applies a mutation to the value, persisting when done.
57    async fn mutate<R: Send>(
58        &mut self,
59        mutation: impl FnOnce(&mut Self::Target) -> R + Send,
60    ) -> Result<R, Self::Error>;
61}
62
63impl<T: Persist> PersistExt for T {
64    async fn mutate<R>(
65        &mut self,
66        mutation: impl FnOnce(&mut Self::Target) -> R + Send,
67    ) -> Result<R, Self::Error> {
68        let output = mutation(self.as_mut());
69        self.persist().await?;
70        Ok(output)
71    }
72}