fuchsia_inspect_contrib/graph/
vertex.rs
1use super::edge::WeakEdgeRef;
6use super::{Edge, EdgeMetadata, VertexId};
7use fuchsia_inspect as inspect;
8use std::collections::BTreeMap;
9use std::sync::atomic::{AtomicU64, Ordering};
10
11#[derive(Debug)]
14pub struct Vertex<M: VertexMetadata> {
15 _node: inspect::Node,
16 id: M::Id,
17 metadata: M,
18 incoming_edges: BTreeMap<u64, WeakEdgeRef<M::EdgeMeta>>,
19 outgoing_edges: BTreeMap<u64, WeakEdgeRef<M::EdgeMeta>>,
20 pub(crate) outgoing_edges_node: inspect::Node,
21 internal_id: u64,
22}
23
24pub trait VertexMetadata {
26 type Id: VertexId;
27 type EdgeMeta: EdgeMetadata;
28}
29
30static NEXT_ID: AtomicU64 = AtomicU64::new(0);
31
32impl<M: VertexMetadata> Vertex<M>
33where
34 <M as VertexMetadata>::Id: VertexId,
35{
36 pub(crate) fn new(
37 id: M::Id,
38 parent: &inspect::Node,
39 init_metadata: impl FnOnce(inspect::Node) -> M,
40 ) -> Self {
41 let internal_id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
42 parent.atomic_update(|parent| {
43 let id_str = id.get_id();
44 let node = parent.create_child(id_str.as_ref());
45 let outgoing_edges_node = node.create_child("relationships");
46 let metadata = init_metadata(node.create_child("meta"));
47 Vertex {
48 id,
49 internal_id,
50 _node: node,
51 outgoing_edges_node,
52 metadata,
53 incoming_edges: BTreeMap::new(),
54 outgoing_edges: BTreeMap::new(),
55 }
56 })
57 }
58
59 pub fn add_edge(
62 &mut self,
63 to: &mut Vertex<M>,
64 init_metadata: impl FnOnce(inspect::Node) -> M::EdgeMeta,
65 ) -> Edge<M::EdgeMeta> {
66 let edge = Edge::new(self, to, init_metadata);
67
68 let weak_ref = edge.weak_ref();
69
70 self.incoming_edges.retain(|_, n| n.is_valid());
71 to.outgoing_edges.retain(|_, n| n.is_valid());
72
73 to.incoming_edges.insert(self.internal_id, weak_ref.clone());
74 self.outgoing_edges.insert(to.internal_id, weak_ref);
75 edge
76 }
77
78 pub fn meta(&mut self) -> &mut M {
80 &mut self.metadata
81 }
82
83 pub(crate) fn id(&self) -> &M::Id {
84 &self.id
85 }
86}
87
88impl<M> Drop for Vertex<M>
89where
90 M: VertexMetadata,
91{
92 fn drop(&mut self) {
93 self.outgoing_edges.iter().for_each(|(_, n)| n.mark_as_gone());
94 self.incoming_edges.iter().for_each(|(_, n)| n.mark_as_gone());
95 }
96}