use serde::{Deserialize, Serialize};
use crate::node::{NodeId, Span};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Relation {
Calls,
Uses,
Imports,
Contains,
Implements,
Extends,
Reads,
Writes,
Creates,
Alters,
Drops,
}
impl Relation {
pub fn as_str(self) -> &'static str {
match self {
Self::Calls => "calls",
Self::Uses => "uses",
Self::Imports => "imports",
Self::Contains => "contains",
Self::Implements => "implements",
Self::Extends => "extends",
Self::Reads => "reads",
Self::Writes => "writes",
Self::Creates => "creates",
Self::Alters => "alters",
Self::Drops => "drops",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Evidence {
Structural,
Scope,
Import,
Scip,
Declared,
Dynamic,
}
impl Evidence {
pub fn as_str(self) -> &'static str {
match self {
Self::Structural => "structural",
Self::Scope => "scope",
Self::Import => "import",
Self::Scip => "scip",
Self::Declared => "declared",
Self::Dynamic => "dynamic",
}
}
pub fn confidence(self) -> Confidence {
match self {
Self::Structural | Self::Scip | Self::Declared => Confidence::Certain,
Self::Scope | Self::Import | Self::Dynamic => Confidence::Inferred,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Confidence {
Certain,
Inferred,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Edge {
pub src: NodeId,
pub dst: NodeId,
pub relation: Relation,
pub evidence: Evidence,
pub confidence: Confidence,
pub site: Option<Span>,
pub extra_sites: Vec<Span>,
pub sites_total: u32,
}
pub const MAX_SITES: usize = 8;
impl Edge {
pub fn single(
src: NodeId,
dst: NodeId,
relation: Relation,
evidence: Evidence,
confidence: Confidence,
site: Option<Span>,
) -> Self {
Self {
src,
dst,
relation,
evidence,
confidence,
site,
extra_sites: Vec::new(),
sites_total: u32::from(site.is_some()),
}
}
pub fn sites(&self) -> impl Iterator<Item = Span> + '_ {
self.site
.into_iter()
.chain(self.extra_sites.iter().copied())
}
pub fn sites_omitted(&self) -> u32 {
self.sites_total.saturating_sub(self.sites().count() as u32)
}
pub fn identity(&self) -> (&NodeId, &NodeId, Relation, Evidence, Confidence) {
(
&self.src,
&self.dst,
self.relation,
self.evidence,
self.confidence,
)
}
}