use crate::edge::{GraphCertainty, GraphEdge, GraphEdgeKind};
const EVERY_KIND: &[GraphEdgeKind] = &[
GraphEdgeKind::Call,
GraphEdgeKind::Import,
GraphEdgeKind::Implementation,
GraphEdgeKind::Reference,
GraphEdgeKind::DependsOn,
];
const EVERY_CERTAINTY: &[GraphCertainty] = &[GraphCertainty::Resolved, GraphCertainty::Possible];
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GraphEdgeSelection {
kinds: u8,
certainties: u8,
}
impl GraphEdgeSelection {
pub fn new(kinds: &[GraphEdgeKind], certainties: &[GraphCertainty]) -> Self {
Self {
kinds: kinds.iter().fold(0, |mask, kind| mask | kind_bit(*kind)),
certainties: certainties
.iter()
.fold(0, |mask, certainty| mask | certainty_bit(*certainty)),
}
}
pub fn all() -> Self {
Self::new(EVERY_KIND, EVERY_CERTAINTY)
}
pub fn code_relations() -> Self {
Self {
kinds: EVERY_KIND
.iter()
.filter(|kind| is_code_relation(**kind))
.fold(0, |mask, kind| mask | kind_bit(*kind)),
certainties: Self::all().certainties,
}
}
pub fn allows(self, edge: &GraphEdge) -> bool {
self.kinds & kind_bit(edge.kind()) != 0
&& self.certainties & certainty_bit(edge.certainty()) != 0
}
}
fn is_code_relation(kind: GraphEdgeKind) -> bool {
match kind {
GraphEdgeKind::Call
| GraphEdgeKind::Import
| GraphEdgeKind::Implementation
| GraphEdgeKind::Reference => true,
GraphEdgeKind::DependsOn => false,
}
}
fn kind_bit(kind: GraphEdgeKind) -> u8 {
match kind {
GraphEdgeKind::Call => 1,
GraphEdgeKind::Import => 1 << 1,
GraphEdgeKind::Implementation => 1 << 2,
GraphEdgeKind::Reference => 1 << 3,
GraphEdgeKind::DependsOn => 1 << 4,
}
}
fn certainty_bit(certainty: GraphCertainty) -> u8 {
match certainty {
GraphCertainty::Resolved => 1,
GraphCertainty::Possible => 1 << 1,
}
}