use exonum::{
crypto::Hash,
runtime::{versioning::Version, ExecutionError},
};
use exonum_derive::*;
use exonum_proto::ProtobufConvert;
use serde_derive::{Deserialize, Serialize};
use super::{proto, AsyncEventState, MigrationError};
#[derive(Debug, Clone)]
#[derive(ProtobufConvert, BinaryValue)]
#[derive(Serialize, Deserialize)]
#[protobuf_convert(source = "proto::MigrationState")]
#[non_exhaustive]
pub struct MigrationState {
#[serde(rename = "state")]
pub inner: AsyncEventState,
#[protobuf_convert(with = "exonum::helpers::pb_version")]
pub version: Version,
#[protobuf_convert(with = "exonum::helpers::pb_optional_hash")]
#[serde(skip)]
pub(crate) reference_state_hash: Option<Hash>,
}
impl MigrationState {
pub fn new(inner: AsyncEventState, version: Version) -> Self {
Self {
inner,
version,
reference_state_hash: None,
}
}
pub fn add_state_hash(&mut self, state_hash: Hash) -> Result<(), ExecutionError> {
if let Some(reference_state_hash) = self.reference_state_hash {
if reference_state_hash == state_hash {
} else {
return Err(MigrationError::StateHashDivergence.into());
}
} else {
self.reference_state_hash = Some(state_hash);
}
Ok(())
}
pub fn is_failed(&self) -> bool {
self.inner.is_failed()
}
pub fn is_pending(&self) -> bool {
self.inner.is_pending()
}
pub fn update(&mut self, new_state: AsyncEventState, version: Version) {
self.inner = new_state;
self.version = version;
}
pub fn fail(&mut self, new_state: AsyncEventState) {
debug_assert!(new_state.is_failed());
self.inner = new_state;
}
#[doc(hidden)] pub fn reference_state_hash(&self) -> &Option<Hash> {
&self.reference_state_hash
}
}