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