Skip to main content

fuchsia_inspect_contrib/graph/
vertex.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::edge::WeakEdgeRef;
6use super::{Edge, EdgeMetadata, VertexId};
7use fuchsia_inspect as inspect;
8use std::collections::BTreeMap;
9
10/// A vertex of the graph. When this is dropped, all the outgoing edges and metadata fields will
11/// removed from Inspect.
12#[derive(Debug)]
13pub struct Vertex<M: VertexMetadata> {
14    _node: inspect::Node,
15    id: M::Id,
16    metadata: M,
17    incoming_edges: BTreeMap<u64, WeakEdgeRef<M::EdgeMeta>>,
18    outgoing_edges: BTreeMap<u64, WeakEdgeRef<M::EdgeMeta>>,
19    pub(crate) outgoing_edges_node: inspect::Node,
20}
21
22/// Trait implemented by types that hold a vertex metadata.
23pub trait VertexMetadata {
24    type Id: VertexId;
25    type EdgeMeta: EdgeMetadata;
26}
27
28impl<M: VertexMetadata> Vertex<M>
29where
30    <M as VertexMetadata>::Id: VertexId,
31{
32    pub(crate) fn new(
33        id: M::Id,
34        parent: &inspect::Node,
35        init_metadata: impl FnOnce(inspect::Node) -> M,
36    ) -> Self {
37        parent.atomic_update(|parent| {
38            let id_str = id.get_id();
39            let node = parent.create_child(id_str.as_ref());
40            let outgoing_edges_node = node.create_child("relationships");
41            let metadata = init_metadata(node.create_child("meta"));
42            Vertex {
43                id,
44                _node: node,
45                outgoing_edges_node,
46                metadata,
47                incoming_edges: BTreeMap::new(),
48                outgoing_edges: BTreeMap::new(),
49            }
50        })
51    }
52
53    /// Add a new edge to the graph originating at this vertex and going to the vertex `to` with the
54    /// given metadata.
55    pub fn add_edge(
56        &mut self,
57        to: &mut Vertex<M>,
58        init_metadata: impl FnOnce(inspect::Node) -> M::EdgeMeta,
59    ) -> Edge<M::EdgeMeta> {
60        let edge = Edge::new(self, to, init_metadata);
61
62        let weak_ref = edge.weak_ref();
63        let edge_id = edge.id();
64
65        self.outgoing_edges.retain(|_, n| n.is_valid());
66        to.incoming_edges.retain(|_, n| n.is_valid());
67
68        to.incoming_edges.insert(edge_id, weak_ref.clone());
69        self.outgoing_edges.insert(edge_id, weak_ref);
70        edge
71    }
72
73    /// Get an exclusive reference to the metadata to modify it.
74    pub fn meta(&mut self) -> &mut M {
75        &mut self.metadata
76    }
77
78    pub(crate) fn id(&self) -> &M::Id {
79        &self.id
80    }
81}
82
83impl<M> Drop for Vertex<M>
84where
85    M: VertexMetadata,
86{
87    fn drop(&mut self) {
88        self.outgoing_edges.iter().for_each(|(_, n)| n.mark_as_gone());
89        self.incoming_edges.iter().for_each(|(_, n)| n.mark_as_gone());
90    }
91}