tor_persist/
handle.rs

1//! Object-safe, type-safe wrappers for [`StateMgr`].
2
3use crate::{Result, StateMgr};
4use serde::{de::DeserializeOwned, Serialize};
5use std::marker::PhantomData;
6use std::sync::Arc;
7
8/// A handle to a storage system that stores objects of a single
9/// type to a single location.
10///
11/// To get an object of this type, call [`StateMgr::create_handle`].
12///
13/// Unlike StateMgr, this trait is object-safe.
14pub trait StorageHandle<T: Serialize + DeserializeOwned> {
15    /// Try to load the object from storage.
16    ///
17    /// If no object exists, return Ok(None).
18    fn load(&self) -> Result<Option<T>>;
19
20    /// Try to store a value into storage.
21    fn store(&self, val: &T) -> Result<()>;
22
23    /// Return true if we have the lock; see [`StateMgr::can_store`].
24    fn can_store(&self) -> bool;
25}
26
27/// Type wrapper for a reference-counted `dyn` [`StorageHandle`].
28///
29/// Most users of this crate will want to access storage via a handle
30/// of this kind, so that they don't have to parameterize over
31/// [`StateMgr`].  The cost of using a fat pointer here should be
32/// pretty small compared to the overhead of persistent storage in
33/// general.
34pub type DynStorageHandle<T> = Arc<dyn StorageHandle<T> + Send + Sync + 'static>;
35
36/// Concrete implementation of [`StorageHandle`].
37#[derive(Debug)]
38pub(crate) struct StorageHandleImpl<M, T> {
39    /// An underlying [`StateMgr`] to use.
40    ///
41    /// The type `M` should probably implement Clone, since we store it
42    /// here and don't give it back.
43    mgr: M,
44    /// The key to use when loading and storing from the [`StateMgr`].
45    key: String,
46    /// A zero-sized type to please the type checker, which will otherwise
47    /// complain about the absence of anything in the struct that uses T.
48    ///
49    /// This uses `fn(T) -> T` to ensure that the type T is mentioned and
50    /// has the correct variance, without forcing this type to have
51    /// the same `Send`/`Sync` status as T.
52    phantom: PhantomData<fn(T) -> T>,
53}
54
55impl<M, T> StorageHandle<T> for StorageHandleImpl<M, T>
56where
57    M: StateMgr,
58    T: Serialize + DeserializeOwned + 'static,
59{
60    fn load(&self) -> Result<Option<T>> {
61        self.mgr.load(&self.key)
62    }
63    fn store(&self, val: &T) -> Result<()> {
64        self.mgr.store(&self.key, val)
65    }
66    fn can_store(&self) -> bool {
67        self.mgr.can_store()
68    }
69}
70
71impl<M, T> StorageHandleImpl<M, T>
72where
73    M: Send + Sync + 'static,
74    T: Serialize + DeserializeOwned + 'static,
75{
76    /// Construct a new StorageHandleImpl.
77    pub(crate) fn new(mgr: M, key: String) -> StorageHandleImpl<M, T> {
78        StorageHandleImpl {
79            mgr,
80            key,
81            phantom: PhantomData,
82        }
83    }
84}