Skip to main content

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
10cfg_if::cfg_if! {
11    if #[cfg(feature = "fs")] {
12        pub mod file;
13        pub use file::File;
14    }
15}
16
17pub mod memory;
18use std::ops::Deref;
19
20pub use memory::Memory;
21
22/// The `Persist` trait provides a wrapper around a value that can be saved in a
23/// persistent way. A minimal implementation provides an `Error` type, a `persist`
24/// function to persist the value, and an `as_mut` function to get a mutable reference to
25/// the value in memory.
26#[cfg_attr(not(web), trait_variant::make(Send))]
27pub trait Persist: Deref {
28    type Error: std::error::Error + Send + Sync + 'static;
29
30    /// Gets a mutable reference to the value. This is not expressed as a
31    /// [`DerefMut`](std::ops::DerefMut) bound because it is discouraged to use this
32    /// function! Instead, use `mutate`.
33    fn as_mut(&mut self) -> &mut Self::Target;
34
35    /// Saves the value to persistent storage.
36    async fn persist(&mut self) -> Result<(), Self::Error>;
37
38    /// Takes the value out.
39    fn into_value(self) -> Self::Target
40    where
41        Self::Target: Sized;
42}
43
44pub trait PersistExt: Persist {
45    /// Applies a mutation to the value, persisting when done.
46    async fn mutate<R>(
47        &mut self,
48        mutation: impl FnOnce(&mut Self::Target) -> R,
49    ) -> Result<R, Self::Error>;
50}
51
52impl<T: Persist> PersistExt for T {
53    async fn mutate<R>(
54        &mut self,
55        mutation: impl FnOnce(&mut Self::Target) -> R,
56    ) -> Result<R, Self::Error> {
57        let output = mutation(self.as_mut());
58        self.persist().await?;
59        Ok(output)
60    }
61}