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