aboutsummaryrefslogtreecommitdiff
path: root/graph/src/labelled/binary.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graph/src/labelled/binary.rs')
-rw-r--r--graph/src/labelled/binary.rs78
1 files changed, 76 insertions, 2 deletions
diff --git a/graph/src/labelled/binary.rs b/graph/src/labelled/binary.rs
index 862f25b..fecc295 100644
--- a/graph/src/labelled/binary.rs
+++ b/graph/src/labelled/binary.rs
@@ -2,7 +2,7 @@
//! labels and each node knows about its parents.
use super::*;
-use crate::{Parent, ParentsGraph, RedirectGraph};
+use crate::{Parent, ParentsGraph, RedirectGraph, VLabelGraph};
use std::{
collections::{hash_map::Iter as MapIter, HashMap as Map},
@@ -223,7 +223,7 @@ impl<T: GraphLabel> Graph for PLGraph<T> {
for node in self.nodes() {
post.push_str(&format!(
" {node} [label = \"{node}:{}\"]\n",
- match self.vertex_label(node) {
+ match VLabelGraph::vertex_label(self, node) {
Ok(Some(label)) => {
format!("{label}")
}
@@ -249,6 +249,7 @@ impl<T: GraphLabel> Graph for PLGraph<T> {
let mut file = std::fs::File::options()
.write(true)
.create(true)
+ .truncate(true)
.open(&filename)?;
use std::io::Write;
@@ -405,6 +406,79 @@ impl<T: GraphLabel> RedirectGraph for PLGraph<T> {
}
}
+/// A delegation of iterators.
+///
+/// This is used to avoid a boxed pointer to an iterator.
+#[derive(Debug, Clone)]
+pub struct PLVIter<'a, T: GraphLabel> {
+ iter: Iter<'a, usize>,
+ graph: &'a PLGraph<T>,
+}
+
+impl<'a, T: GraphLabel> PLVIter<'a, T> {
+ /// Return an iterator from a graph and a node.
+ pub fn try_new(graph: &'a PLGraph<T>, node: usize) -> Result<Self, Error> {
+ let iter = graph
+ .nodes
+ .get(node)
+ .ok_or(Error::IndexOutOfBounds(node, graph.nodes.len()))?
+ .children
+ .iter();
+
+ Ok(Self { iter, graph })
+ }
+}
+
+impl<'a, T: GraphLabel> Iterator for PLVIter<'a, T> {
+ type Item = (T, usize);
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().and_then(|child| {
+ VLabelGraph::vertex_label(self.graph, *child)
+ .ok()
+ .flatten()
+ .map(|label| (label, *child))
+ })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.iter.len();
+
+ (len, Some(len))
+ }
+}
+
+impl<'a, T: GraphLabel> ExactSizeIterator for PLVIter<'a, T> {
+ #[inline]
+ fn len(&self) -> usize {
+ self.iter.len()
+ }
+}
+
+impl<T: GraphLabel> VLabelGraph<T> for PLGraph<T> {
+ type TupleIter<'a> = PLVIter<'a,T>
+ where
+ Self: 'a,
+ T: 'a;
+
+ fn vertex_label(&self, node_id: usize) -> Result<Option<T>, Error> {
+ self.nodes
+ .get(node_id)
+ .ok_or(Error::IndexOutOfBounds(node_id, self.nodes.len()))
+ .map(|node| Some(node.label))
+ }
+
+ fn query_label(&self, label: T) -> Option<usize> {
+ self.label_index_map.get(&label).copied()
+ }
+
+ fn verlabren_of(&self, node_id: usize) -> Result<Self::TupleIter<'_>, Error> {
+ PLVIter::try_new(self, node_id)
+ }
+}
+
impl<T: GraphLabel> LabelGraph<T> for PLGraph<T> {
type Iter<'a> = std::iter::Empty<usize>
where