use crate::DatabaseCommit;
use core::{convert::Infallible, error::Error, fmt};
use primitives::AddressMap;
use state::Account;
use std::sync::Arc;
pub trait TryDatabaseCommit {
type Error: Error;
fn try_commit(&mut self, changes: AddressMap<Account>) -> Result<(), Self::Error>;
}
impl<Db> TryDatabaseCommit for Db
where
Db: DatabaseCommit,
{
type Error = Infallible;
#[inline]
fn try_commit(&mut self, changes: AddressMap<Account>) -> Result<(), Self::Error> {
self.commit(changes);
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArcUpgradeError;
impl fmt::Display for ArcUpgradeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Arc reference is not unique, cannot mutate")
}
}
impl Error for ArcUpgradeError {}
impl<Db> TryDatabaseCommit for Arc<Db>
where
Db: DatabaseCommit,
{
type Error = ArcUpgradeError;
#[inline]
fn try_commit(&mut self, changes: AddressMap<Account>) -> Result<(), Self::Error> {
Arc::get_mut(self)
.map(|db| db.commit(changes))
.ok_or(ArcUpgradeError)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::DatabaseCommit;
use std::sync::Arc;
struct MockDb;
impl DatabaseCommit for MockDb {
fn commit(&mut self, _changes: AddressMap<Account>) {}
}
#[test]
fn arc_try_commit() {
let mut db = Arc::new(MockDb);
let db_2 = Arc::clone(&db);
assert_eq!(
db.try_commit(Default::default()).unwrap_err(),
ArcUpgradeError
);
drop(db_2);
db.try_commit(Default::default()).unwrap();
}
}