ferrum_interfaces/vnext/event/
topology.rs1use serde::Serialize;
2use std::collections::{BTreeMap, BTreeSet};
3
4use super::{
5 canonical_fingerprint, invalid_event, validate_sha256, DeviceId, ExecutionPlan, NodeId,
6 OperationId, PlanHash, PlanId, ProviderId, VNextError,
7};
8use crate::vnext::ProviderExecutionSemantics;
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
11pub struct TrustedNodeTopology {
12 pub(super) operation_id: OperationId,
13 pub(super) provider_id: ProviderId,
14 pub(super) provider_execution_semantics: ProviderExecutionSemantics,
15 pub(super) dependencies: BTreeSet<NodeId>,
16}
17
18impl TrustedNodeTopology {
19 pub fn operation_id(&self) -> &OperationId {
20 &self.operation_id
21 }
22
23 pub fn provider_id(&self) -> &ProviderId {
24 &self.provider_id
25 }
26
27 pub const fn provider_execution_semantics(&self) -> ProviderExecutionSemantics {
28 self.provider_execution_semantics
29 }
30
31 pub fn dependencies(&self) -> &BTreeSet<NodeId> {
32 &self.dependencies
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
37pub struct TrustedExecutionTopology {
38 plan_id: PlanId,
39 plan_hash: PlanHash,
40 device_id: DeviceId,
41 device_runtime_implementation_fingerprint: String,
42 pub(super) nodes: BTreeMap<NodeId, TrustedNodeTopology>,
43 #[serde(skip)]
44 fingerprint: String,
45}
46
47impl TrustedExecutionTopology {
48 pub fn from_plan(plan: &ExecutionPlan) -> Result<Self, VNextError> {
49 let mut nodes = BTreeMap::new();
50 for node in plan.payload().nodes() {
51 if nodes
52 .insert(
53 node.id().clone(),
54 TrustedNodeTopology {
55 operation_id: node.operation_id().clone(),
56 provider_id: node.selection().selected_provider().clone(),
57 provider_execution_semantics: node.provider_execution_semantics(),
58 dependencies: node.dependencies().iter().cloned().collect(),
59 },
60 )
61 .is_some()
62 {
63 return Err(invalid_event("trusted plan has duplicate node ids"));
64 }
65 }
66 if nodes.is_empty() {
67 return Err(invalid_event("trusted execution topology is empty"));
68 }
69 let mut topology = Self {
70 plan_id: plan.payload().plan_id().clone(),
71 plan_hash: plan.plan_hash().clone(),
72 device_id: plan.payload().device_id().clone(),
73 device_runtime_implementation_fingerprint: plan
74 .payload()
75 .device_runtime_implementation_fingerprint()
76 .to_owned(),
77 nodes,
78 fingerprint: String::new(),
79 };
80 validate_sha256(
81 &topology.device_runtime_implementation_fingerprint,
82 "topology runtime implementation fingerprint",
83 )?;
84 topology.fingerprint = canonical_fingerprint(&topology);
85 Ok(topology)
86 }
87
88 pub fn plan_id(&self) -> &PlanId {
89 &self.plan_id
90 }
91
92 pub fn plan_hash(&self) -> &PlanHash {
93 &self.plan_hash
94 }
95
96 pub fn device_id(&self) -> &DeviceId {
97 &self.device_id
98 }
99
100 pub fn device_runtime_implementation_fingerprint(&self) -> &str {
101 &self.device_runtime_implementation_fingerprint
102 }
103
104 pub fn fingerprint(&self) -> &str {
105 &self.fingerprint
106 }
107
108 pub fn node_ids(&self) -> BTreeSet<NodeId> {
109 self.nodes.keys().cloned().collect()
110 }
111
112 pub fn node(&self, node_id: &NodeId) -> Option<&TrustedNodeTopology> {
113 self.nodes.get(node_id)
114 }
115}