revm_database_interface/
try_commit.rs1use crate::DatabaseCommit;
3use core::{convert::Infallible, error::Error, fmt};
4use primitives::{Address, HashMap};
5use state::Account;
6use std::sync::Arc;
7
8pub trait TryDatabaseCommit {
14 type Error: Error;
16
17 fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error>;
19}
20
21impl<Db> TryDatabaseCommit for Db
22where
23 Db: DatabaseCommit,
24{
25 type Error = Infallible;
26
27 #[inline]
28 fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error> {
29 self.commit(changes);
30 Ok(())
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub struct ArcUpgradeError;
38
39impl fmt::Display for ArcUpgradeError {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "Arc reference is not unique, cannot mutate")
42 }
43}
44
45impl Error for ArcUpgradeError {}
46
47impl<Db> TryDatabaseCommit for Arc<Db>
48where
49 Db: DatabaseCommit + Send + Sync,
50{
51 type Error = ArcUpgradeError;
52
53 #[inline]
54 fn try_commit(&mut self, changes: HashMap<Address, Account>) -> Result<(), Self::Error> {
55 Arc::get_mut(self)
56 .map(|db| db.commit(changes))
57 .ok_or(ArcUpgradeError)
58 }
59}
60
61#[cfg(test)]
62mod test {
63 use super::*;
64 use crate::DatabaseCommit;
65 use std::sync::Arc;
66
67 struct MockDb;
68
69 impl DatabaseCommit for MockDb {
70 fn commit(&mut self, _changes: HashMap<Address, Account>) {}
71 }
72
73 #[test]
74 fn arc_try_commit() {
75 let mut db = Arc::new(MockDb);
76 let db_2 = Arc::clone(&db);
77
78 assert_eq!(
79 db.try_commit(Default::default()).unwrap_err(),
80 ArcUpgradeError
81 );
82 drop(db_2);
83 db.try_commit(Default::default()).unwrap();
84 }
85}