revert(ariadne): remove graph artifact implementation
This commit is contained in:
@@ -1,192 +0,0 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
pub type Metadata = BTreeMap<String, Value>;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct NodeId(String);
|
||||
|
||||
impl NodeId {
|
||||
pub fn new(value: impl Into<String>) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for NodeId {
|
||||
fn from(value: &str) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for NodeId {
|
||||
fn from(value: String) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SourceRef {
|
||||
pub path: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub line: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub column: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Node {
|
||||
pub id: NodeId,
|
||||
pub kind: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub source: Option<SourceRef>,
|
||||
pub payload: Value,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct Edge {
|
||||
pub from: NodeId,
|
||||
pub to: NodeId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "op", rename_all = "snake_case")]
|
||||
pub enum Delta {
|
||||
AddNode { node: Node },
|
||||
RemoveNode { node: Node },
|
||||
ReplaceNode { old: Node, new: Node },
|
||||
AddEdge { edge: Edge },
|
||||
RemoveEdge { edge: Edge },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Graph {
|
||||
pub metadata: Metadata,
|
||||
pub nodes: BTreeMap<NodeId, Node>,
|
||||
pub edges: BTreeSet<Edge>,
|
||||
}
|
||||
|
||||
impl Graph {
|
||||
pub fn new(metadata: Metadata) -> Self {
|
||||
Self {
|
||||
metadata,
|
||||
nodes: BTreeMap::new(),
|
||||
edges: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_node(&mut self, node: Node) -> Result<Delta, GraphError> {
|
||||
if self.nodes.contains_key(&node.id) {
|
||||
return Err(GraphError::DuplicateNode { id: node.id });
|
||||
}
|
||||
|
||||
self.nodes.insert(node.id.clone(), node.clone());
|
||||
Ok(Delta::AddNode { node })
|
||||
}
|
||||
|
||||
pub fn remove_node(&mut self, id: &NodeId) -> Result<Vec<Delta>, GraphError> {
|
||||
let node = self
|
||||
.nodes
|
||||
.remove(id)
|
||||
.ok_or_else(|| GraphError::MissingNode { id: id.clone() })?;
|
||||
|
||||
let incident_edges: Vec<_> = self
|
||||
.edges
|
||||
.iter()
|
||||
.filter(|edge| edge.from == *id || edge.to == *id)
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let mut deltas = Vec::with_capacity(incident_edges.len() + 1);
|
||||
for edge in incident_edges {
|
||||
self.edges.remove(&edge);
|
||||
deltas.push(Delta::RemoveEdge { edge });
|
||||
}
|
||||
deltas.push(Delta::RemoveNode { node });
|
||||
|
||||
Ok(deltas)
|
||||
}
|
||||
|
||||
pub fn replace_node(&mut self, node: Node) -> Result<Delta, GraphError> {
|
||||
let old = self
|
||||
.nodes
|
||||
.get_mut(&node.id)
|
||||
.ok_or_else(|| GraphError::MissingNode {
|
||||
id: node.id.clone(),
|
||||
})?;
|
||||
let previous = std::mem::replace(old, node.clone());
|
||||
|
||||
Ok(Delta::ReplaceNode {
|
||||
old: previous,
|
||||
new: node,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_edge(&mut self, edge: Edge) -> Result<Delta, GraphError> {
|
||||
self.require_node(&edge.from)?;
|
||||
self.require_node(&edge.to)?;
|
||||
|
||||
if !self.edges.insert(edge.clone()) {
|
||||
return Err(GraphError::DuplicateEdge { edge });
|
||||
}
|
||||
|
||||
Ok(Delta::AddEdge { edge })
|
||||
}
|
||||
|
||||
pub fn remove_edge(&mut self, edge: &Edge) -> Result<Delta, GraphError> {
|
||||
if !self.edges.remove(edge) {
|
||||
return Err(GraphError::MissingEdge { edge: edge.clone() });
|
||||
}
|
||||
|
||||
Ok(Delta::RemoveEdge { edge: edge.clone() })
|
||||
}
|
||||
|
||||
fn require_node(&self, id: &NodeId) -> Result<(), GraphError> {
|
||||
if self.nodes.contains_key(id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(GraphError::MissingNode { id: id.clone() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum GraphError {
|
||||
DuplicateNode { id: NodeId },
|
||||
MissingNode { id: NodeId },
|
||||
DuplicateEdge { edge: Edge },
|
||||
MissingEdge { edge: Edge },
|
||||
}
|
||||
|
||||
impl Display for GraphError {
|
||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GraphError::DuplicateNode { id } => {
|
||||
write!(formatter, "duplicate node `{}`", id.as_str())
|
||||
}
|
||||
GraphError::MissingNode { id } => write!(formatter, "missing node `{}`", id.as_str()),
|
||||
GraphError::DuplicateEdge { edge } => write!(
|
||||
formatter,
|
||||
"duplicate edge `{} -> {}`",
|
||||
edge.from.as_str(),
|
||||
edge.to.as_str()
|
||||
),
|
||||
GraphError::MissingEdge { edge } => write!(
|
||||
formatter,
|
||||
"missing edge `{} -> {}`",
|
||||
edge.from.as_str(),
|
||||
edge.to.as_str()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for GraphError {}
|
||||
Reference in New Issue
Block a user