use std::collections::HashMap;
use crate::{
errors::LatticeError,
graph::graph_prepared::PreparedGraph,
properties::PropertyHandle,
utils::{
generational_vector::{GenVec, Handle},
values::{Primitive, Value},
},
};
pub(crate) type GlobalVertexId = u64;
pub(crate) type GraphId = u64;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct VertexHandle(pub(crate) Handle);
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct EdgeHandle(Handle);
pub struct VertexData {
pub global_id: Option<GlobalVertexId>,
pub attributes: Vec<(PropertyHandle, Primitive)>,
pub incoming_edges: Vec<EdgeHandle>,
pub outgoing_edges: Vec<EdgeHandle>,
}
pub struct EdgeData {
pub from: VertexHandle,
pub to: VertexHandle,
pub label: PropertyHandle,
}
pub(crate) struct OldGraphData {
pub(crate) id: GraphId,
pub(crate) graph: PreparedGraph,
}
pub struct GraphBuilder {
new_vertex_count: u64,
pub(crate) old_graph_data: Option<OldGraphData>,
pub(crate) vertices: GenVec<VertexData>,
pub(crate) edges: GenVec<EdgeData>,
}
impl Default for GraphBuilder {
fn default() -> Self {
Self::new()
}
}
impl GraphBuilder {
pub fn new_vertex<'a>(&'a mut self) -> VertexBuilder<'a> {
self.new_vertex_count += 1;
let handle = self.vertices.add(VertexData {
global_id: None,
attributes: vec![],
incoming_edges: vec![],
outgoing_edges: vec![],
});
VertexBuilder::new(self, handle)
}
pub fn remove_vertex(&mut self, handle: VertexHandle) -> Result<(), LatticeError> {
let removed = self
.vertices
.remove(handle.0)
.ok_or(LatticeError::VertexNotFound)?;
if removed.global_id.is_none() {
self.new_vertex_count -= 1;
}
let edges = [removed.incoming_edges, removed.outgoing_edges].concat();
for edge in edges {
let _ = self.remove_edge(edge);
}
Ok(())
}
pub fn edit_vertex<'a>(
&'a mut self,
handle: VertexHandle,
) -> Result<VertexBuilder<'a>, LatticeError> {
self.vertices
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?;
Ok(VertexBuilder::new(self, handle.0))
}
pub fn get_vertex(&self, handle: VertexHandle) -> Option<&VertexData> {
self.vertices.get(handle.0)
}
pub fn new_edge(
&mut self,
from: VertexHandle,
label: PropertyHandle,
to: VertexHandle,
) -> Result<&mut Self, LatticeError> {
self.vertices
.get(from.0)
.ok_or(LatticeError::VertexNotFound)?; let to_vertex = self
.vertices
.get_mut(to.0)
.ok_or(LatticeError::VertexNotFound)?;
let edge_handle = EdgeHandle(self.edges.add(EdgeData { from, label, to }));
to_vertex.incoming_edges.push(edge_handle);
let from_vertex = self.vertices.get_mut(from.0).unwrap();
from_vertex.outgoing_edges.push(edge_handle);
Ok(self)
}
pub fn remove_edge(&mut self, handle: EdgeHandle) -> Result<(), LatticeError> {
let edge = self
.edges
.remove(handle.0)
.ok_or(LatticeError::EdgeNotFound)?;
if let Some(from) = self.vertices.get_mut(edge.from.0)
&& let Some(idx) = from.outgoing_edges.iter().position(|p| *p == handle)
{
from.outgoing_edges.swap_remove(idx);
}
if let Some(to) = self.vertices.get_mut(edge.to.0)
&& let Some(idx) = to.incoming_edges.iter().position(|p| *p == handle)
{
to.incoming_edges.swap_remove(idx);
}
Ok(())
}
pub fn edit_edge<'a>(
&'a mut self,
handle: EdgeHandle,
) -> Result<EdgeBuilder<'a>, LatticeError> {
self.edges.get(handle.0).ok_or(LatticeError::EdgeNotFound)?;
Ok(EdgeBuilder::new(self, handle.0))
}
pub fn get_edge(&self, handle: EdgeHandle) -> Option<&EdgeData> {
self.edges.get(handle.0)
}
}
pub struct EdgeBuilder<'a> {
graph: &'a mut GraphBuilder,
handle: Handle,
}
impl<'a> EdgeBuilder<'a> {
fn new(graph: &'a mut GraphBuilder, handle: Handle) -> Self {
Self { graph, handle }
}
fn get_self(&mut self) -> &mut EdgeData {
self.graph.edges.get_mut(self.handle).unwrap() }
pub fn set_source(&mut self, handle: VertexHandle) -> Result<&mut Self, LatticeError> {
self.graph
.edges
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?;
self.get_self().from = handle;
Ok(self)
}
pub fn set_destination(&mut self, handle: VertexHandle) -> Result<&mut Self, LatticeError> {
self.graph
.edges
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?;
self.get_self().to = handle;
Ok(self)
}
pub fn set_label(&mut self, label: PropertyHandle) -> Result<&mut Self, LatticeError> {
self.get_self().label = label;
Ok(self)
}
}
pub struct VertexBuilder<'a> {
graph: &'a mut GraphBuilder,
handle: Handle,
}
impl<'a> VertexBuilder<'a> {
fn new(graph: &'a mut GraphBuilder, handle: Handle) -> Self {
Self { graph, handle }
}
fn get_self(&mut self) -> &mut VertexData {
self.graph.vertices.get_mut(self.handle).unwrap() }
pub fn new_attribute<V: Value>(
&mut self,
attr: PropertyHandle,
value: V,
) -> Result<&mut Self, LatticeError> {
let v = value.to_primitive();
v.verify()?;
self.get_self().attributes.push((attr, v));
Ok(self)
}
pub fn new_edge(
&mut self,
label: PropertyHandle,
handle: VertexHandle,
) -> Result<&mut Self, LatticeError> {
let to = self
.graph
.vertices
.get_mut(handle.0)
.ok_or(LatticeError::VertexNotFound)?;
let edge_handle = EdgeHandle(self.graph.edges.add(EdgeData {
from: VertexHandle(self.handle),
label,
to: handle,
}));
to.incoming_edges.push(edge_handle);
self.get_self().outgoing_edges.push(edge_handle);
Ok(self)
}
pub fn handle(&self) -> VertexHandle {
VertexHandle(self.handle)
}
}
impl GraphBuilder {
pub fn get_vertex_global_id(
&self,
handle: VertexHandle,
) -> Result<Option<GlobalVertexId>, LatticeError> {
Ok(self
.vertices
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?
.global_id)
}
pub fn get_mut_attributes(
&mut self,
handle: VertexHandle,
) -> Result<&mut Vec<(PropertyHandle, Primitive)>, LatticeError> {
Ok(&mut self
.vertices
.get_mut(handle.0)
.ok_or(LatticeError::VertexNotFound)?
.attributes)
}
pub fn get_incoming_edges(
&self,
handle: VertexHandle,
) -> Result<&Vec<EdgeHandle>, LatticeError> {
Ok(&self
.vertices
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?
.incoming_edges)
}
pub fn get_outgoing_edges(
&self,
handle: VertexHandle,
) -> Result<&Vec<EdgeHandle>, LatticeError> {
Ok(&self
.vertices
.get(handle.0)
.ok_or(LatticeError::VertexNotFound)?
.outgoing_edges)
}
pub fn iter_vertices(&self) -> impl Iterator<Item = (Handle, &VertexData)> {
self.vertices.iter()
}
pub fn iter_edges(&self) -> impl Iterator<Item = (Handle, &EdgeData)> {
self.edges.iter()
}
}
impl GraphBuilder {
pub fn new() -> Self {
Self {
new_vertex_count: 0,
old_graph_data: None,
vertices: GenVec::new(),
edges: GenVec::new(),
}
}
pub(crate) fn count_new_vertices(&self) -> u64 {
self.new_vertex_count
}
pub(crate) fn from_prepared(graph: PreparedGraph) -> Self {
let mut builder = Self::new();
let mut id_map = HashMap::new();
for v in &graph.vertices {
let handle = builder.vertices.add(VertexData {
global_id: Some(v.id),
attributes: v.attrs.clone(),
incoming_edges: vec![],
outgoing_edges: vec![],
});
id_map.insert(v.id, VertexHandle(handle));
}
for e in &graph.edges {
let from = *id_map.get(&e.from).expect("Edge source vertex missing");
let to = *id_map.get(&e.to).expect("Edge destination vertex missing");
let handle = builder.edges.add(EdgeData {
from,
to,
label: e.label,
});
builder
.vertices
.get_mut(from.0)
.unwrap()
.outgoing_edges
.push(EdgeHandle(handle));
builder
.vertices
.get_mut(to.0)
.unwrap()
.incoming_edges
.push(EdgeHandle(handle));
}
builder.old_graph_data = Some(OldGraphData {
id: graph.id,
graph,
});
builder
}
}