ic_backup/model/ic_update_response/
mod.rs1use crate::model::{
4 artifacts::ArtifactChecksumRecord, attempt_journal::MAX_OPERATION_ATTEMPTS,
5 operation_plan::PlanContextRecord,
6};
7use std::fmt;
8
9#[derive(Clone)]
11pub struct IcUpdateResponseInput {
12 pub authority: ArtifactChecksumRecord,
14 pub mutation_attempt: u32,
16 pub context: PlanContextRecord,
18 pub target: String,
20 pub reply: Vec<u8>,
22 pub evidence: ArtifactChecksumRecord,
24}
25
26pub(crate) enum UpdateResponseAdmissionError {
27 InvalidAttempt,
28 ReplyTooLarge,
29 InvalidTarget,
30}
31
32impl IcUpdateResponseInput {
33 pub(crate) fn admit(
34 &mut self,
35 max_reply_bytes: usize,
36 ) -> Result<(), UpdateResponseAdmissionError> {
37 if self.mutation_attempt == 0 || self.mutation_attempt > MAX_OPERATION_ATTEMPTS {
38 return Err(UpdateResponseAdmissionError::InvalidAttempt);
39 }
40 if self.reply.len() > max_reply_bytes {
41 return Err(UpdateResponseAdmissionError::ReplyTooLarge);
42 }
43 self.target = crate::model::principal::canonical_text(&self.target)
44 .ok_or(UpdateResponseAdmissionError::InvalidTarget)?;
45 Ok(())
46 }
47
48 pub(crate) fn fmt_redacted(
49 &self,
50 formatter: &mut fmt::Formatter<'_>,
51 name: &str,
52 ) -> fmt::Result {
53 formatter
54 .debug_struct(name)
55 .field("authority", &self.authority)
56 .field("mutation_attempt", &self.mutation_attempt)
57 .field("target", &self.target)
58 .field("reply_bytes", &self.reply.len())
59 .finish_non_exhaustive()
60 }
61}
62
63#[cfg(test)]
64mod tests;