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