co_primitives/types/
lazy_transaction.rs1use crate::{BlockStorage, StorageError};
5use async_trait::async_trait;
6use either::Either;
7
8#[async_trait]
10pub trait Transactionable<S>
11where
12 S: BlockStorage + Clone + 'static,
13{
14 type Transaction;
15
16 async fn open(&self, storage: &S) -> Result<Self::Transaction, StorageError>;
17}
18
19#[derive(Debug)]
21pub struct LazyTransaction<S, T>(Either<(S, T), (T::Transaction, bool)>)
22where
23 S: BlockStorage + Clone + 'static,
24 T: Transactionable<S> + 'static;
25impl<S, T> LazyTransaction<S, T>
26where
27 S: BlockStorage + Clone + 'static,
28 T: Transactionable<S> + 'static,
29{
30 pub fn new(storage: S, init: T) -> Self {
31 Self(Either::Left((storage, init)))
32 }
33
34 pub fn is_mut_access(&self) -> bool {
36 match &self.0 {
37 Either::Left(_) => false,
38 Either::Right((_, is_mut)) => *is_mut,
39 }
40 }
41
42 async fn open(&mut self) -> Result<(), StorageError> {
43 match &self.0 {
44 Either::Left((storage, item)) => {
45 self.0 = Either::Right((item.open(storage).await?, false));
46 },
47 Either::Right(_) => {},
48 }
49 Ok(())
50 }
51
52 pub async fn get(&mut self) -> Result<&T::Transaction, StorageError> {
53 self.open().await?;
54 Ok(self.opt().expect("initialized after open"))
55 }
56
57 pub async fn get_mut(&mut self) -> Result<&mut T::Transaction, StorageError> {
58 self.open().await?;
59 Ok(self.opt_mut().expect("initialized after open"))
60 }
61
62 pub fn opt(&self) -> Option<&T::Transaction> {
63 match &self.0 {
64 Either::Left(_) => None,
65 Either::Right((transaction, _is_mut_access)) => Some(transaction),
66 }
67 }
68
69 pub fn opt_mut(&mut self) -> Option<&mut T::Transaction> {
70 match &mut self.0 {
71 Either::Left(_) => None,
72 Either::Right((transaction, is_mut_access)) => {
73 *is_mut_access = true;
74 Some(transaction)
75 },
76 }
77 }
78
79 pub fn opt_if_is_mut_access(&mut self) -> Option<&mut T::Transaction> {
80 match &mut self.0 {
81 Either::Right((transaction, true)) => Some(transaction),
82 _ => None,
83 }
84 }
85}