use crate::model::{
attempt_journal::AttemptJournalRecord,
ic_lifecycle_reply::{IcLifecycleReply, IcLifecycleReplyError},
ic_mutation::{IcMutationAcknowledgement, IcMutationRequest, IcMutationRequestError},
ic_request::IcManagementMethodRecord,
ic_snapshot_reply::{IcSnapshotReply, IcSnapshotReplyError},
};
use thiserror::Error;
#[derive(Debug)]
pub enum IcMutationReplyView<'a> {
Capture(IcSnapshotReply<'a>),
Lifecycle(IcLifecycleReply<'a>),
}
#[derive(Debug)]
pub struct IcMutationAcknowledgementView<'a> {
acknowledgement: &'a IcMutationAcknowledgement,
reply: IcMutationReplyView<'a>,
}
impl<'a> IcMutationAcknowledgementView<'a> {
#[must_use]
pub const fn acknowledgement(&self) -> &'a IcMutationAcknowledgement {
self.acknowledgement
}
#[must_use]
pub const fn reply(&self) -> &IcMutationReplyView<'a> {
&self.reply
}
}
pub fn validate_acknowledgement<'a>(
request: &IcMutationRequest<'a>,
journal: &AttemptJournalRecord,
acknowledgement: &'a IcMutationAcknowledgement,
) -> Result<IcMutationAcknowledgementView<'a>, IcMutationAssociationError> {
request.validate_journal(journal)?;
let input = acknowledgement.input();
if input.authority != request.authority().digest() {
return Err(IcMutationAssociationError::AuthorityMismatch);
}
if input.mutation_attempt != request.mutation_attempt() {
return Err(IcMutationAssociationError::AttemptMismatch);
}
if &input.context != request.plan().context() {
return Err(IcMutationAssociationError::ContextMismatch);
}
if input.target != request.payload().target() {
return Err(IcMutationAssociationError::TargetMismatch);
}
let reply = match request.payload().method() {
IcManagementMethodRecord::TakeCanisterSnapshot => {
IcMutationReplyView::Capture(IcSnapshotReply::decode(request.payload(), &input.reply)?)
}
_ => IcMutationReplyView::Lifecycle(IcLifecycleReply::decode(
request.payload(),
&input.reply,
)?),
};
Ok(IcMutationAcknowledgementView {
acknowledgement,
reply,
})
}
#[derive(Debug, Error)]
pub enum IcMutationAssociationError {
#[error(transparent)]
Reservation(#[from] IcMutationRequestError),
#[error("IC mutation acknowledgement authority mismatch")]
AuthorityMismatch,
#[error("IC mutation acknowledgement attempt mismatch")]
AttemptMismatch,
#[error("IC mutation acknowledgement context mismatch")]
ContextMismatch,
#[error("IC mutation acknowledgement target mismatch")]
TargetMismatch,
#[error(transparent)]
Snapshot(#[from] IcSnapshotReplyError),
#[error(transparent)]
Lifecycle(#[from] IcLifecycleReplyError),
}
#[cfg(test)]
mod tests;