use crate::model::{
artifacts::ArtifactChecksumRecord, attempt_journal::MAX_OPERATION_ATTEMPTS,
operation_plan::PlanContextRecord,
};
use std::fmt;
use thiserror::Error;
#[derive(Clone)]
pub struct IcUpdateResponseInput {
pub authority: ArtifactChecksumRecord,
pub mutation_attempt: u32,
pub context: PlanContextRecord,
pub target: String,
pub reply: Vec<u8>,
pub evidence: ArtifactChecksumRecord,
}
#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
pub enum IcUpdateResponseError {
#[error("invalid IC update response attempt")]
InvalidAttempt,
#[error("IC update response reply too large")]
ReplyTooLarge,
#[error("invalid IC update response target")]
InvalidTarget,
}
impl IcUpdateResponseInput {
pub(crate) fn admit(&mut self, max_reply_bytes: usize) -> Result<(), IcUpdateResponseError> {
if self.mutation_attempt == 0 || self.mutation_attempt > MAX_OPERATION_ATTEMPTS {
return Err(IcUpdateResponseError::InvalidAttempt);
}
if self.reply.len() > max_reply_bytes {
return Err(IcUpdateResponseError::ReplyTooLarge);
}
self.target = crate::model::principal::canonical_text(&self.target)
.ok_or(IcUpdateResponseError::InvalidTarget)?;
Ok(())
}
pub(crate) fn fmt_redacted(
&self,
formatter: &mut fmt::Formatter<'_>,
name: &str,
) -> fmt::Result {
formatter
.debug_struct(name)
.field("authority", &self.authority)
.field("mutation_attempt", &self.mutation_attempt)
.field("target", &self.target)
.field("reply_bytes", &self.reply.len())
.finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests;