1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use super::*;
pub struct ExtraMutator<T: Config<I>, I: 'static = ()> {
	id: T::AssetId,
	who: T::AccountId,
	original: T::Extra,
	pending: Option<T::Extra>,
}
impl<T: Config<I>, I: 'static> Drop for ExtraMutator<T, I> {
	fn drop(&mut self) {
		debug_assert!(self.commit().is_ok(), "attempt to write to non-existent asset account");
	}
}
impl<T: Config<I>, I: 'static> sp_std::ops::Deref for ExtraMutator<T, I> {
	type Target = T::Extra;
	fn deref(&self) -> &T::Extra {
		match self.pending {
			Some(ref value) => value,
			None => &self.original,
		}
	}
}
impl<T: Config<I>, I: 'static> sp_std::ops::DerefMut for ExtraMutator<T, I> {
	fn deref_mut(&mut self) -> &mut T::Extra {
		if self.pending.is_none() {
			self.pending = Some(self.original.clone());
		}
		self.pending.as_mut().unwrap()
	}
}
impl<T: Config<I>, I: 'static> ExtraMutator<T, I> {
	pub(super) fn maybe_new(
		id: T::AssetId,
		who: impl sp_std::borrow::Borrow<T::AccountId>,
	) -> Option<ExtraMutator<T, I>> {
		if Account::<T, I>::contains_key(id, who.borrow()) {
			Some(ExtraMutator::<T, I> {
				id,
				who: who.borrow().clone(),
				original: Account::<T, I>::get(id, who.borrow()).extra,
				pending: None,
			})
		} else {
			None
		}
	}
	
	pub fn commit(&mut self) -> Result<(), ()> {
		if let Some(extra) = self.pending.take() {
			Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| {
				if let Some(ref mut account) = maybe_account {
					account.extra = extra;
					Ok(())
				} else {
					Err(())
				}
			})
		} else {
			Ok(())
		}
	}
	
	pub fn revert(mut self) -> Result<(), ()> {
		self.pending = None;
		Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| {
			if let Some(ref mut account) = maybe_account {
				account.extra = self.original.clone();
				Ok(())
			} else {
				Err(())
			}
		})
	}
}