Skip to main content

pedant_graph/
edge.rs

1//! A graph edge, how certain it is, and the evidence that produced it.
2
3use std::sync::Arc;
4
5use serde::Serialize;
6
7use crate::id::{GraphEdgeId, GraphNodeId, GraphReferenceId};
8
9/// What relation an edge states.
10#[derive(Serialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[serde(rename_all = "snake_case")]
12pub enum GraphEdgeKind {
13    /// The source calls the target.
14    Call,
15    /// The source imports the target.
16    Import,
17    /// The source implements the target.
18    Implementation,
19    /// Any other source relation between the two.
20    Reference,
21    /// The source's build unit depends on the target's build unit.
22    DependsOn,
23}
24
25/// How much an edge is known.
26///
27/// A projection maps a producer's certainty one for one and never upgrades a
28/// possible answer to a resolved one.
29#[derive(Serialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
30#[serde(rename_all = "snake_case")]
31pub enum GraphCertainty {
32    /// Language rules identify this one target without inference.
33    Resolved,
34    /// Source evidence identifies the target, but proof is not available.
35    Possible,
36}
37
38/// Which dependency table declared a build-unit edge.
39///
40/// Graph-owned vocabulary rather than the consumed build-system enum, so a
41/// second producer cannot widen the wire contract from outside this crate.
42#[derive(Serialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
43#[serde(rename_all = "snake_case")]
44pub enum GraphDependencyKind {
45    /// An ordinary dependency edge.
46    Normal,
47    /// A development-only dependency edge.
48    Development,
49    /// A build-time dependency edge.
50    Build,
51}
52
53/// What one build-unit dependency edge retained from its declaration.
54#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
55pub struct DependencyEvidence {
56    alias: Arc<str>,
57    kind: GraphDependencyKind,
58    predicate: Option<Arc<str>>,
59}
60
61impl DependencyEvidence {
62    pub(crate) fn new(
63        alias: Arc<str>,
64        kind: GraphDependencyKind,
65        predicate: Option<Arc<str>>,
66    ) -> Self {
67        Self {
68            alias,
69            kind,
70            predicate,
71        }
72    }
73
74    /// The namespace-local name the declaring unit sees the target under.
75    pub fn alias(&self) -> &str {
76        &self.alias
77    }
78
79    /// Which dependency table declared the edge.
80    pub fn kind(&self) -> GraphDependencyKind {
81        self.kind
82    }
83
84    /// The unevaluated activation predicate, when the edge is conditional.
85    pub fn predicate(&self) -> Option<&str> {
86        self.predicate.as_deref()
87    }
88}
89
90/// Why an edge exists. No edge exists without one of these.
91#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
92#[serde(tag = "kind", rename_all = "snake_case")]
93pub enum GraphEdgeOrigin {
94    /// One candidate of one reference record produced the edge.
95    Reference {
96        /// The record that produced it, for the reverse evidence link.
97        reference: GraphReferenceId,
98    },
99    /// One declared build-unit dependency produced the edge.
100    Dependency {
101        /// What the declaration stated.
102        evidence: DependencyEvidence,
103    },
104}
105
106/// One directed relation between two graph nodes.
107#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
108pub struct GraphEdge {
109    id: GraphEdgeId,
110    source: GraphNodeId,
111    target: GraphNodeId,
112    kind: GraphEdgeKind,
113    certainty: GraphCertainty,
114    origin: GraphEdgeOrigin,
115}
116
117/// Everything a projection states about one edge before it has an identity.
118pub(crate) struct EdgeDraft {
119    /// The node the relation starts at.
120    pub(crate) source: GraphNodeId,
121    /// The node the relation ends at.
122    pub(crate) target: GraphNodeId,
123    /// What relation the edge states.
124    pub(crate) kind: GraphEdgeKind,
125    /// How much the relation is known.
126    pub(crate) certainty: GraphCertainty,
127    /// Why the edge exists.
128    pub(crate) origin: GraphEdgeOrigin,
129}
130
131impl GraphEdge {
132    pub(crate) fn new(id: GraphEdgeId, draft: EdgeDraft) -> Self {
133        Self {
134            id,
135            source: draft.source,
136            target: draft.target,
137            kind: draft.kind,
138            certainty: draft.certainty,
139            origin: draft.origin,
140        }
141    }
142
143    /// This edge's dense identity, equal to its position in the graph.
144    pub fn id(&self) -> GraphEdgeId {
145        self.id
146    }
147
148    /// The node the relation starts at.
149    pub fn source(&self) -> GraphNodeId {
150        self.source
151    }
152
153    /// The node the relation ends at.
154    pub fn target(&self) -> GraphNodeId {
155        self.target
156    }
157
158    /// What relation this edge states.
159    pub fn kind(&self) -> GraphEdgeKind {
160        self.kind
161    }
162
163    /// How much this relation is known.
164    pub fn certainty(&self) -> GraphCertainty {
165        self.certainty
166    }
167
168    /// Why this edge exists.
169    pub fn origin(&self) -> &GraphEdgeOrigin {
170        &self.origin
171    }
172}