Skip to main content

ic_backup/model/operation_plan/operation/
mod.rs

1//! Exact declared target/request and original per-operation finite allowance.
2
3use super::{OperationPlanError, canonical_hash};
4use crate::model::attempt_journal::AttemptBudgetRecord;
5use serde::{Deserialize, Serialize};
6
7/// Passive exact operation binding supplied by its qualified request codec owner.
8#[derive(Clone, Debug)]
9pub struct PlannedOperationRequest {
10    /// Exact graph operation identity, including zero/nonconsecutive sequences.
11    pub operation_sequence: u64,
12    /// Exact physical principal, admitted against explicit selection by the plan.
13    pub target: String,
14    /// Canonical exact mutating request digest from its owner; not rendered text.
15    pub request: String,
16    /// Original finite mutation/observation limits, never replenished on derivation.
17    pub budget: AttemptBudgetRecord,
18}
19/// Immutable canonical declared target/request/allowance for one exact graph node.
20#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
21#[serde(try_from = "OperationFields")]
22pub struct PlannedOperationRecord {
23    operation_sequence: u64,
24    target: String,
25    request: String,
26    budget: AttemptBudgetRecord,
27}
28#[derive(Deserialize)]
29#[serde(deny_unknown_fields)]
30struct OperationFields {
31    operation_sequence: u64,
32    target: String,
33    request: String,
34    budget: AttemptBudgetRecord,
35}
36impl TryFrom<OperationFields> for PlannedOperationRecord {
37    type Error = OperationPlanError;
38    fn try_from(fields: OperationFields) -> Result<Self, Self::Error> {
39        Self::new(PlannedOperationRequest {
40            operation_sequence: fields.operation_sequence,
41            target: fields.target,
42            request: fields.request,
43            budget: fields.budget,
44        })
45    }
46}
47impl PlannedOperationRecord {
48    /// Admit canonical declared operation identity; the plan validates selection/graph binding.
49    ///
50    /// # Errors
51    /// Rejects malformed principal and request SHA-256 digest text.
52    pub fn new(request: PlannedOperationRequest) -> Result<Self, OperationPlanError> {
53        Ok(Self {
54            operation_sequence: request.operation_sequence,
55            target: crate::model::principal::canonical_text(&request.target)
56                .ok_or(OperationPlanError::InvalidPrincipal("target"))?,
57            request: canonical_hash(&request.request)?,
58            budget: request.budget,
59        })
60    }
61    /// Read the exact opaque graph operation sequence.
62    #[must_use]
63    pub const fn operation_sequence(&self) -> u64 {
64        self.operation_sequence
65    }
66    /// Read the exact canonical physical target principal.
67    #[must_use]
68    pub fn target(&self) -> &str {
69        &self.target
70    }
71    /// Read the exact canonical integration-owned request digest.
72    #[must_use]
73    pub fn request(&self) -> &str {
74        &self.request
75    }
76    /// Read the original finite operation attempt limits.
77    #[must_use]
78    pub const fn budget(&self) -> &AttemptBudgetRecord {
79        &self.budget
80    }
81}