ic_backup/model/effect_graph/node/
mod.rs1use super::EffectGraphError;
4use serde::{Deserialize, Deserializer, Serialize, de};
5use std::fmt;
6
7pub const MAX_EFFECT_DEPENDENCIES: usize = 1024;
9
10#[derive(Clone, Debug)]
12pub struct EffectNodeRequest {
13 pub operation_sequence: u64,
15 pub depends_on: Vec<u64>,
17}
18
19#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
21#[serde(try_from = "NodeFields")]
22pub struct EffectNodeRecord {
23 operation_sequence: u64,
24 depends_on: Vec<u64>,
25}
26#[derive(Deserialize)]
27#[serde(deny_unknown_fields)]
28struct NodeFields {
29 operation_sequence: u64,
30 #[serde(deserialize_with = "bounded_dependencies")]
31 depends_on: Vec<u64>,
32}
33impl TryFrom<NodeFields> for EffectNodeRecord {
34 type Error = EffectGraphError;
35 fn try_from(fields: NodeFields) -> Result<Self, Self::Error> {
36 Self::new(EffectNodeRequest {
37 operation_sequence: fields.operation_sequence,
38 depends_on: fields.depends_on,
39 })
40 }
41}
42impl EffectNodeRecord {
43 pub fn new(mut request: EffectNodeRequest) -> Result<Self, EffectGraphError> {
48 if request.depends_on.len() > MAX_EFFECT_DEPENDENCIES {
49 return Err(EffectGraphError::TooManyDependencies);
50 }
51 request.depends_on.sort_unstable();
52 for pair in request.depends_on.windows(2) {
53 if pair[0] == pair[1] {
54 return Err(EffectGraphError::DuplicateDependency {
55 operation_sequence: request.operation_sequence,
56 dependency: pair[0],
57 });
58 }
59 }
60 Ok(Self {
61 operation_sequence: request.operation_sequence,
62 depends_on: request.depends_on,
63 })
64 }
65 #[must_use]
67 pub const fn operation_sequence(&self) -> u64 {
68 self.operation_sequence
69 }
70 #[must_use]
72 pub fn depends_on(&self) -> &[u64] {
73 &self.depends_on
74 }
75}
76
77fn bounded_dependencies<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u64>, D::Error> {
78 struct DependenciesVisitor;
79 impl<'de> de::Visitor<'de> for DependenciesVisitor {
80 type Value = Vec<u64>;
81 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.write_str("bounded exact effect dependencies")
83 }
84 fn visit_seq<A: de::SeqAccess<'de>>(
85 self,
86 mut sequence: A,
87 ) -> Result<Self::Value, A::Error> {
88 let mut dependencies = Vec::new();
89 while dependencies.len() < MAX_EFFECT_DEPENDENCIES {
90 match sequence.next_element()? {
91 Some(dependency) => dependencies.push(dependency),
92 None => return Ok(dependencies),
93 }
94 }
95 if sequence.next_element::<de::IgnoredAny>()?.is_some() {
96 return Err(de::Error::custom(EffectGraphError::TooManyDependencies));
97 }
98 Ok(dependencies)
99 }
100 }
101 deserializer.deserialize_seq(DependenciesVisitor)
102}