diff options
Diffstat (limited to 'graph/src/adlist.rs')
-rw-r--r-- | graph/src/adlist.rs | 104 |
1 files changed, 102 insertions, 2 deletions
diff --git a/graph/src/adlist.rs b/graph/src/adlist.rs index ba3077e..d36b250 100644 --- a/graph/src/adlist.rs +++ b/graph/src/adlist.rs @@ -3,9 +3,16 @@ //! [`Graph`][super::Graph]. This data type represents graphs using //! adjacency lists internally. -use std::ops::{Deref, DerefMut}; +use std::{ + borrow::{Borrow, BorrowMut}, + ops::{Deref, DerefMut}, +}; -use crate::{builder::Builder, error::Error, ExtGraph, Graph}; +use crate::{ + builder::{Builder, BuilderMut}, + error::Error, + ExtGraph, Graph, +}; // #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] // struct ALEdge { @@ -118,6 +125,99 @@ impl From<Vec<Vec<usize>>> for ALGraph { } } +/// A builder that modifies ALGraph in place. +#[derive(Debug)] +pub struct ALGBuilderMut<'a> { + graph: &'a mut ALGraph, +} + +impl<'a> std::ops::Deref for ALGBuilderMut<'a> { + type Target = ALGraph; + + fn deref(&self) -> &Self::Target { + self.graph.borrow() + } +} + +impl<'a> std::ops::DerefMut for ALGBuilderMut<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.graph.borrow_mut() + } +} + +impl<'a> BuilderMut for ALGBuilderMut<'a> { + type Label = (); + + type Graph = ALGraph; + + type ResultBuilder<'b> = ALGBuilderMut<'b> + where + Self::Label: 'b; + + fn from_graph_mut(graph: &mut Self::Graph) -> Self::ResultBuilder<'_> { + ALGBuilderMut { graph } + } + + fn add_vertex(&mut self, _label: Self::Label) -> usize { + self.nodes.push(Default::default()); + + self.nodes.len() - 1 + } + + fn add_edge(&mut self, source: usize, target: usize, _label: Self::Label) -> Result<(), Error> { + if self.graph.has_edge(source, target)? { + return Ok(()); + } + + self.graph + .nodes + .get_mut(source) + .unwrap() + .children + .push(target); + + Ok(()) + } + + fn append(&mut self, other: Self::Graph) { + let self_len = self.nodes_len(); + + self.graph + .nodes + .extend(other.nodes.into_iter().map(|mut node| { + for child in node.children.iter_mut() { + *child += self_len; + } + + node + })); + } + + fn set_label(&mut self, _node_id: usize, _label: Self::Label) -> Result<(), Error> { + Ok(()) + } + + fn remove_edge<F>(&mut self, source: usize, target: usize, _predicate: F) -> Result<(), Error> + where + F: FnMut(Self::Label) -> bool, + { + let nodes_len = self.nodes.len(); + + let source_children = self + .nodes + .get_mut(source) + .ok_or(Error::IndexOutOfBounds(source, nodes_len))?; + + if !(0..nodes_len).contains(&target) { + return Err(Error::IndexOutOfBounds(target, nodes_len)); + } + + source_children.children.retain(|child| *child != target); + + Ok(()) + } +} + // Builder for this implementation of graph /// A builder for adjacency list graphs. |