Skip to main content

vantage_vista/transaction/
wrap.rs

1//! [`Transaction::wrap`] and [`Transaction::resolver`]: how a Vista joins a
2//! transaction.
3
4use std::sync::Arc;
5
6use vantage_core::Result;
7
8use super::{Transaction, cant_take_part, joining::joining, shell::TxShell};
9use crate::{resolver::VistaResolver, vista::Vista};
10
11impl Transaction {
12    /// `vista`, reading and writing through this transaction. Its shell is
13    /// rebound now; a shell that can't rebind errors at the wrapped Vista's
14    /// first use, not here. Every Vista the result returns (`get_ref`
15    /// targets) is wrapped too.
16    ///
17    /// The participants the rebind joins are the ones its writes are
18    /// credited to, for [`committed_before_failure`](Self::committed_before_failure):
19    /// a shell joins in `rebind`, not at its first statement.
20    pub fn wrap(&self, vista: &Vista) -> Vista {
21        let (rebound, joined) = joining(self, || {
22            self.check_open().and_then(|()| vista.shell().rebind(self))
23        });
24        let rebound = rebound.map_err(|err| {
25            if err.is_unsupported() {
26                cant_take_part(vista.name())
27            } else {
28                err
29            }
30        });
31        let name = vista.name().to_string();
32        vista
33            .clone()
34            .map_shell(|original| TxShell::new(original, rebound, joined, name, self.clone()))
35    }
36
37    /// `base`, with every Vista it resolves, or adopts, wrapped in this
38    /// transaction.
39    pub fn resolver(&self, base: Arc<dyn VistaResolver>) -> Arc<dyn VistaResolver> {
40        Arc::new(TxResolver {
41            tx: self.clone(),
42            base,
43        })
44    }
45}
46
47struct TxResolver {
48    tx: Transaction,
49    base: Arc<dyn VistaResolver>,
50}
51
52impl VistaResolver for TxResolver {
53    fn vista(&self, name: &str) -> Result<Vista> {
54        Ok(self.tx.wrap(&self.base.vista(name)?))
55    }
56
57    fn adopt(&self, vista: Vista) -> Vista {
58        self.tx.wrap(&self.base.adopt(vista))
59    }
60}