use super::response_identity::{ResponseIdentity, ResponseIdentityMismatch};
use crate::model::{
attempt_journal::AttemptJournalRecord,
ic_snapshot_data::{IcSnapshotDataError, IcSnapshotDataReply},
ic_snapshot_metadata::{IcSnapshotMetadataError, IcSnapshotMetadataReply},
ic_snapshot_transfer_read::{
IcSnapshotTransferReadError, IcSnapshotTransferReadPayload, IcSnapshotTransferReadRequest,
IcSnapshotTransferReadResponse,
},
};
use thiserror::Error;
#[derive(Debug)]
pub enum IcSnapshotTransferReadReply<'request, 'metadata> {
Metadata(IcSnapshotMetadataReply<'request>),
Data(IcSnapshotDataReply<'request, 'metadata>),
}
#[derive(Debug)]
pub struct IcSnapshotTransferReadView<'request, 'metadata> {
response: &'request IcSnapshotTransferReadResponse,
reply: IcSnapshotTransferReadReply<'request, 'metadata>,
}
impl<'request, 'metadata> IcSnapshotTransferReadView<'request, 'metadata> {
#[must_use]
pub const fn response(&self) -> &'request IcSnapshotTransferReadResponse {
self.response
}
#[must_use]
pub const fn reply(&self) -> &IcSnapshotTransferReadReply<'request, 'metadata> {
&self.reply
}
}
pub fn validate_response<'request, 'metadata>(
request: &IcSnapshotTransferReadRequest<'request, 'metadata>,
journal: &AttemptJournalRecord,
response: &'request IcSnapshotTransferReadResponse,
) -> Result<IcSnapshotTransferReadView<'request, 'metadata>, IcSnapshotTransferReadAssociationError>
{
request.validate_journal(journal)?;
let input = response.input();
ResponseIdentity {
authority: &input.authority,
mutation_attempt: input.mutation_attempt,
context: &input.context,
target: &input.target,
}
.compare(&ResponseIdentity {
authority: &request.authority().digest(),
mutation_attempt: request.mutation_attempt(),
context: request.plan().context(),
target: request.payload().target(),
})
.map_err(|mismatch| match mismatch {
ResponseIdentityMismatch::Authority => {
IcSnapshotTransferReadAssociationError::AuthorityMismatch
}
ResponseIdentityMismatch::Attempt => {
IcSnapshotTransferReadAssociationError::AttemptMismatch
}
ResponseIdentityMismatch::Context => {
IcSnapshotTransferReadAssociationError::ContextMismatch
}
ResponseIdentityMismatch::Target => IcSnapshotTransferReadAssociationError::TargetMismatch,
})?;
let reply = match request.payload() {
IcSnapshotTransferReadPayload::Metadata(payload) => IcSnapshotTransferReadReply::Metadata(
IcSnapshotMetadataReply::decode(payload, &input.reply)?,
),
IcSnapshotTransferReadPayload::Data(payload) => {
IcSnapshotTransferReadReply::Data(IcSnapshotDataReply::decode(payload, &input.reply)?)
}
};
Ok(IcSnapshotTransferReadView { response, reply })
}
#[derive(Debug, Error)]
pub enum IcSnapshotTransferReadAssociationError {
#[error(transparent)]
Reservation(#[from] IcSnapshotTransferReadError),
#[error("snapshot transfer read response authority differs")]
AuthorityMismatch,
#[error("snapshot transfer read response attempt differs")]
AttemptMismatch,
#[error("snapshot transfer read response context differs")]
ContextMismatch,
#[error("snapshot transfer read response target differs")]
TargetMismatch,
#[error(transparent)]
Metadata(#[from] IcSnapshotMetadataError),
#[error(transparent)]
Data(#[from] IcSnapshotDataError),
}
#[cfg(test)]
mod tests;