Added the view module and a few basic tests.

This commit is contained in:
Stu Black 2019-07-23 01:09:56 -04:00
parent 50bdbb41a7
commit 154e49c9f0
6 changed files with 419 additions and 99 deletions

View File

@ -5,6 +5,7 @@ authors = ["Stu Black"]
edition = "2018"
[dependencies]
r4 = "1.0"
symbol-map = "1.0"
[dev-dependencies]

View File

@ -2,6 +2,7 @@ pub(crate) mod base;
pub mod mutators;
pub mod nav;
pub mod search;
pub mod view;
use std::cell::UnsafeCell;
use std::error::Error;
@ -29,12 +30,9 @@ use symbol_map::SymbolId;
/// - `A`: The type of graph edge data.
///
/// Vertices are addressed by content. To examine graph contents, obtain a node
/// handle with `get_node`. To modify graph contents, add new root vertices with
/// `add_node` and retrieve extant vertices with `get_node_mut`.
pub struct Graph<T, S, A>
where
T: Hash + Eq + Clone,
{
/// handle with `find_node`. To modify graph contents, add new root vertices with
/// `add_node` and retrieve extant vertices with `find_node_mut`.
pub struct Graph<T: Hash + Eq + Clone, S, A> {
/// Lookup table that maps from game states to `VertexId`.
state_ids: symbol_map::indexing::HashIndexing<T, VertexId>,
vertices: Vec<RawVertex<S>>, // Indexed by VertexId.
@ -110,7 +108,7 @@ where
/// Gets a node handle for the given game state.
///
/// If `state` does not correspond to a known game state, returns `None`.
pub fn get_node<'s>(&'s self, state: &T) -> Option<Node<'s, T, S, A>> {
pub fn find_node<'s>(&'s self, state: &T) -> Option<Node<'s, T, S, A>> {
match self.state_ids.get(state) {
Some(symbol) => Some(Node::new(self, *symbol.id())),
None => None,
@ -120,7 +118,7 @@ where
/// Gets a mutable node handle for the given game state.
///
/// If `state` does not correspond to a known game state, returns `None`.
pub fn get_node_mut<'s>(&'s mut self, state: &T) -> Option<MutNode<'s, T, S, A>> {
pub fn find_node_mut<'s>(&'s mut self, state: &T) -> Option<MutNode<'s, T, S, A>> {
match self.state_ids.get(state).map(|s| s.id().clone()) {
Some(id) => Some(MutNode::new(self, id)),
None => None,
@ -195,27 +193,6 @@ where
// TODO: This is actually the number of edges we have allocated.
self.arcs.len()
}
/// Deletes all graph components that are not reachable by traversal
/// starting from each vertex corresponding to the game states in `roots`.
///
/// Game states in `roots` which do not have a corresponding vertex are
/// ignored.
pub fn retain_reachable_from(&mut self, roots: &[&T]) {
let mut root_ids = Vec::with_capacity(roots.len());
for state in roots.iter() {
if let Some(symbol) = self.state_ids.get(state) {
root_ids.push(*symbol.id());
}
}
self.retain_reachable_from_ids(&root_ids);
}
/// As `retain_reachable_from`, but working over raw `VertexId`s instead of
/// root data.
fn retain_reachable_from_ids(&mut self, root_ids: &[VertexId]) {
mutators::mark_compact::Collector::retain_reachable(self, root_ids);
}
}
/// Allows both read-only references into a `Graph` and operations that modify
@ -239,7 +216,7 @@ where
/// let root1 = appendable.append_node(0, "data1".to_string());
/// // If appendable were a Graph, we could not call append_node while root1 is alive.
/// let root2 = appendable.append_node(1, "data2".to_string());
/// assert_eq!("data1", appendable.get_node(&0).unwrap().get_data());
/// assert_eq!("data1", appendable.find_node(&0).unwrap().get_data());
/// assert!(root1.is_leaf());
/// let edge = appendable.append_edge(root1.clone(), root2.clone(), 3.3).unwrap();
/// assert_eq!(*edge.get_source().get_label(), 0);
@ -346,9 +323,9 @@ mod test {
let graph = Arc::new(g);
thread::scope(move |s| {
let g = graph.clone();
let t1 = s.spawn(move |_| g.get_node(&"root").map(|n| n.get_id()));
let t1 = s.spawn(move |_| g.find_node(&"root").map(|n| n.get_id()));
let g = graph.clone();
let t2 = s.spawn(move |_| g.get_node(&"1").map(|n| n.get_id()));
let t2 = s.spawn(move |_| g.find_node(&"1").map(|n| n.get_id()));
match t1.join() {
Ok(Some(id)) => assert_eq!(id, 0),
_ => panic!(),
@ -368,8 +345,8 @@ mod test {
g.add_edge("root", |_| "root_data", "1", |_| "1_data", "root_1_data");
let g = &g;
thread::scope(|s| {
let t1 = s.spawn(move |_| g.get_node(&"root").map(|n| n.get_id()));
let t2 = s.spawn(move |_| g.get_node(&"1").map(|n| n.get_id()));
let t1 = s.spawn(move |_| g.find_node(&"root").map(|n| n.get_id()));
let t2 = s.spawn(move |_| g.find_node(&"1").map(|n| n.get_id()));
match t1.join() {
Ok(Some(id)) => assert_eq!(id, 0),
_ => panic!(),

View File

@ -11,7 +11,9 @@ use std::hash::Hash;
use crate::base::{EdgeId, RawEdge, RawVertex, VertexId};
use crate::nav::{ChildList, ChildListIter, Edge, Node, ParentList, ParentListIter};
use crate::view;
use crate::Graph;
use r4::iterate;
use symbol_map::indexing::{Indexing, Insertion};
use symbol_map::SymbolId;
@ -25,22 +27,12 @@ pub(crate) mod mark_compact;
/// It enables local graph mutation, whether via mutation of vertex data or
/// mutation of graph topology (adding edges). Edges may be added
/// using the handle returned by `get_child_adder` or `to_child_adder`.
pub struct MutNode<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
pub struct MutNode<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> {
pub(crate) graph: &'a mut Graph<T, S, A>,
pub(crate) id: VertexId,
}
impl<'a, T, S, A> MutNode<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
impl<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> MutNode<'a, T, S, A> {
/// Creates a new `MutNode` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details.
pub(crate) fn new(graph: &'a mut Graph<T, S, A>, id: VertexId) -> Self {
@ -155,29 +147,24 @@ where
/// Prunes the underlying graph by removing components not reachable from
/// this node.
pub fn retain_reachable(&mut self) {
self.graph.retain_reachable_from_ids(&[self.id]);
self.id = VertexId(0);
pub fn retain_reachable(self) -> MutNode<'a, T, S, A>{
MutNode {
id: VertexId(0),
graph: view::of_node(self, |mut v, n| {
v.retain_reachable_from(iterate!(yield n));
v.into()
}),
}
}
}
/// A traversible list of a vertex's outgoing edges.
pub struct MutChildList<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
pub struct MutChildList<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> {
graph: &'a mut Graph<T, S, A>,
id: VertexId,
}
impl<'a, T, S, A> MutChildList<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
impl<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> MutChildList<'a, T, S, A> {
fn vertex<'s>(&'s self) -> &'s RawVertex<S> {
self.graph.get_vertex(self.id)
}
@ -302,22 +289,12 @@ where
}
/// A traversible list of a vertex's incoming edges.
pub struct MutParentList<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
pub struct MutParentList<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> {
graph: &'a mut Graph<T, S, A>,
id: VertexId,
}
impl<'a, T, S, A> MutParentList<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
impl<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> MutParentList<'a, T, S, A> {
fn vertex<'s>(&'s self) -> &'s RawVertex<S> {
self.graph.get_vertex(self.id)
}
@ -457,22 +434,12 @@ where
/// mutation of graph topology (adding vertices). Vertices may be added to
/// unexpanded edges using the handle returned by `get_target_mut` or
/// `to_target`.
pub struct MutEdge<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
graph: &'a mut Graph<T, S, A>,
id: EdgeId,
pub struct MutEdge<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> {
pub(crate) graph: &'a mut Graph<T, S, A>,
pub(crate) id: EdgeId,
}
impl<'a, T, S, A> MutEdge<'a, T, S, A>
where
T: Hash + Eq + Clone + 'a,
S: 'a,
A: 'a,
{
impl<'a, T: Hash + Eq + Clone + 'a, S: 'a, A: 'a> MutEdge<'a, T, S, A> {
/// Creates a new `MutEdge` for the given graph and gamestate. This method is
/// not exported by the crate because it exposes implementation details.
pub(crate) fn new(graph: &'a mut Graph<T, S, A>, id: EdgeId) -> Self {

View File

@ -69,8 +69,7 @@ where
&self.graph.get_vertex(self.id).data
}
/// Returns true iff this vertex has no outgoing edges (regardless of
/// whether they are expanded).
/// Returns true iff this vertex has no outgoing edges.
pub fn is_leaf(&self) -> bool {
self.children().is_empty()
}
@ -380,8 +379,7 @@ where
}
}
/// Returns the target of this edge. If the edge is unexpanded, no data will
/// be available. If it is expanded, a node handle will be available.
/// Returns the target of this edge.
pub fn get_target(&self) -> Node<'a, T, S, A> {
Node {
graph: self.graph,

View File

@ -420,7 +420,7 @@ mod test {
Ok(Some(Traversal::Child(1)))
}
let mut path = Stack::new(g.get_node_mut(&"A").unwrap());
let mut path = Stack::new(g.find_node_mut(&"A").unwrap());
assert_eq!(1, path.len());
match path.push(traverse_second_child) {
@ -464,7 +464,7 @@ mod test {
Err(MockError(()))
}
let mut path = Stack::new(g.get_node_mut(&"A").unwrap());
let mut path = Stack::new(g.find_node_mut(&"A").unwrap());
assert_eq!(1, path.len());
match path.push(traverse_err) {
@ -544,7 +544,7 @@ mod test {
Ok(Some(Traversal::Child(1)))
}
let mut path = Stack::new(g.get_node_mut(&"A").unwrap());
let mut path = Stack::new(g.find_node_mut(&"A").unwrap());
assert_eq!(1, path.len());
match path.push(traverse_second_child) {
@ -619,7 +619,7 @@ mod test {
Err(MockError(()))
}
let mut path = Stack::new(g.get_node_mut(&"A").unwrap());
let mut path = Stack::new(g.find_node_mut(&"A").unwrap());
assert_eq!(1, path.len());
match path.push(traverse_err) {
@ -659,7 +659,7 @@ mod test {
Ok(Some(Traversal::Child(0)))
}
let mut path = Stack::new(g.get_node_mut(&"root").unwrap());
let mut path = Stack::new(g.find_node_mut(&"root").unwrap());
match path.push(traverse_first_child) {
Ok(Some(e)) => assert_eq!("root", *e.get_source().get_data()),
_ => panic!(),
@ -716,7 +716,7 @@ mod test {
let mut g = Graph::new();
add_edge(&mut g, "root", "A");
let mut path = Stack::new(g.get_node_mut(&"root").unwrap());
let mut path = Stack::new(g.find_node_mut(&"root").unwrap());
assert_eq!(1, path.len());
fn traverse_first_child<'a>(n: &Node<'a>) -> Result<Option<Traversal>, MockError> {
@ -746,7 +746,7 @@ mod test {
let mut g = Graph::new();
add_edge(&mut g, "root", "A");
let path = Stack::new(g.get_node_mut(&"root").unwrap());
let path = Stack::new(g.find_node_mut(&"root").unwrap());
assert_eq!(1, path.len());
assert_eq!("root", *path.to_head().get_data());
@ -757,7 +757,7 @@ mod test {
let mut g = Graph::new();
add_edge(&mut g, "root", "A");
let mut path = Stack::new(g.get_node_mut(&"root").unwrap());
let mut path = Stack::new(g.find_node_mut(&"root").unwrap());
assert_eq!(1, path.len());
fn traverse_first_child<'a>(n: &Node<'a>) -> Result<Option<Traversal>, MockError> {

377
src/view.rs Normal file
View File

@ -0,0 +1,377 @@
use r4::iterate;
use symbol_map::indexing::Indexing;
use crate::base::{EdgeId, RawEdge, RawVertex, VertexId};
use crate::mutators;
use crate::Graph;
use std::hash::Hash;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
#[derive(Clone, Copy)]
pub(crate) struct InvariantLifetime<'id>(pub(crate) PhantomData<*mut &'id ()>);
/// An editable view of a graph.
///
/// A `View` wraps around a mutable borrow of a `Graph` and enables taking
/// references into the graph and performing mutation operations on
/// it. Mutations that invalidate references into the graph consume the view
/// entirely. Generally speaking, it is possible to grow the graph (add nodes or
/// edges) without invalidating references into it.
///
/// To create a `View`, use one of the functions defined in this module
/// (`of_graph`, `of_node`, or `of_edge`).
pub struct View<'a, T: Hash + Eq + Clone, S, A> {
graph: &'a mut Graph<T, S, A>,
lifetime: InvariantLifetime<'a>,
}
/// Applies a function over a view of `graph` and returns its result.
///
/// ```rust
/// # use search_graph::Graph;
/// # use search_graph::view;
/// # fn main() {
/// let mut graph: Graph<String, String, String> = Graph::new();
/// assert_eq!(graph.vertex_count(), 0);
/// assert_eq!(graph.edge_count(), 0);
/// view::of_graph(&mut graph, |mut v| v.append_node("state".into(), "data".into()));
/// assert_eq!(graph.vertex_count(), 1);
/// assert_eq!(graph.edge_count(), 0);
/// assert_eq!(graph.find_node(&"state".into()).unwrap().get_data(), "data");
/// # }
/// ```
pub fn of_graph<'a, T: Hash + Eq + Clone, S, A, U, F: FnOnce(View<'a, T, S, A>) -> U>(
graph: &'a mut Graph<T, S, A>,
closure: F,
) -> U {
closure(View {
graph,
lifetime: InvariantLifetime(PhantomData),
})
}
/// Applies a function over a `MutNode` and a view of its containing graph,
/// returning its result.
///
/// ```rust
/// # use search_graph::Graph;
/// # use search_graph::view;
/// # fn main() {
/// let mut graph: Graph<String, String, String> = Graph::new();
/// let node = graph.add_node("state".into(), "data".into());
/// view::of_node(node, |v, n| {
/// assert_eq!(v.node_state(n), "state");
/// assert_eq!(v.node_data(n), "data");
/// });
/// # }
pub fn of_node<
'a,
T: Hash + Eq + Clone,
S,
A,
U,
F: FnOnce(View<'a, T, S, A>, NodeRef<'a>) -> U,
>(
node: mutators::MutNode<'a, T, S, A>,
closure: F,
) -> U {
let lifetime = InvariantLifetime(PhantomData);
closure(
View {
graph: node.graph,
lifetime,
},
NodeRef {
id: node.id,
_lifetime: lifetime,
},
)
}
/// Applies a function over a `MutEdge` and a view of its containing graph,
/// returning its result.
///
/// ```rust
/// # use search_graph::Graph;
/// # use search_graph::view;
/// # fn main() {
/// let mut graph: Graph<String, String, String> = Graph::new();
/// let node = graph.add_node("state".into(), "data".into());
/// let edge = view::of_node(node, |mut v, root| {
/// let child = v.append_node("child_state".into(), "child_data".into());
/// v.into_append_edge(root, child, "edge_data".into())
/// });
/// view::of_edge(edge, |v, e| assert_eq!(v.edge_data(e), "edge_data"));
/// # }
/// ```
pub fn of_edge<
'a,
T: Hash + Eq + Clone,
S,
A,
U,
F: FnOnce(View<'a, T, S, A>, EdgeRef<'a>) -> U,
>(
edge: mutators::MutEdge<'a, T, S, A>,
closure: F,
) -> U {
let lifetime = InvariantLifetime(PhantomData);
closure(
View {
graph: edge.graph,
lifetime,
},
EdgeRef {
id: edge.id,
_lifetime: lifetime,
},
)
}
impl<'a, T: Hash + Eq + Clone, S, A> View<'a, T, S, A> {
// Unsafe operations that reference into the underlying graph structure. A
// NodeRef or EdgeRef will only have the same invariant lifetime as a View if
// it was created for that view, and we only create NodeRef/EdgeRef instances
// with valid indices.
//
// Because vertices/edges cannot be deleted or re-ordered without consuming a
// View, it should always be safe to follow reference indices without doing
// bounds-checking.
fn raw_vertex(&self, node: NodeRef<'a>) -> &RawVertex<S> {
unsafe { self.graph.vertices.get_unchecked(node.id.0) }
}
fn raw_vertex_mut(&mut self, node: NodeRef<'a>) -> &mut RawVertex<S> {
unsafe { self.graph.vertices.get_unchecked_mut(node.id.0) }
}
fn raw_edge(&self, edge: EdgeRef<'a>) -> &RawEdge<A> {
unsafe { self.graph.arcs.get_unchecked(edge.id.0) }
}
fn raw_edge_mut(&mut self, edge: EdgeRef<'a>) -> &mut RawEdge<A> {
unsafe { self.graph.arcs.get_unchecked_mut(edge.id.0) }
}
/// Returns a reference to the node for the given game state that is already
/// in the graph, or `None` if there is no such node.
pub fn find_node(&self, state: &T) -> Option<NodeRef<'a>> {
self.graph.find_node(state).map(|n| NodeRef {
id: n.id,
_lifetime: self.lifetime,
})
}
/// Adds a node for the given game state with the given data, returning a
/// reference to it after it is added. If such a node already exists, no node
/// is added to the graph, and a reference to the existing node is returned.
pub fn append_node(&mut self, state: T, data: S) -> NodeRef<'a> {
NodeRef {
id: self.graph.add_node(state, data).id,
_lifetime: self.lifetime,
}
}
/// Consumes this view and adds a node as if `append_node` had been
/// called. Returns a `MutNode` that points to the node that is created.
pub fn into_append_node(self, state: T, data: S) -> mutators::MutNode<'a, T, S, A> {
let id = self.graph.add_node(state, data).id;
mutators::MutNode {
graph: self.graph,
id,
}
}
/// Adds an edge between the given nodes, returning a reference to it after it
/// is added.
pub fn append_edge(
&mut self,
source: NodeRef<'a>,
target: NodeRef<'a>,
edge_data: A,
) -> EdgeRef<'a> {
let id = self.graph.add_raw_edge(edge_data, source.id, target.id);
EdgeRef {
id,
_lifetime: self.lifetime,
}
}
/// Consumes this view and adds an edge as if `append_edge` had been
/// called. Returns a `MutEdge` that points to the edge that is created.
pub fn into_append_edge(
self,
source: NodeRef<'a>,
target: NodeRef<'a>,
edge_data: A,
) -> mutators::MutEdge<'a, T, S, A> {
let id = self.graph.add_raw_edge(edge_data, source.id, target.id);
mutators::MutEdge {
graph: self.graph,
id,
}
}
/// Returns a reference to the game state that `node` is associated with.
pub fn node_state(&self, node: NodeRef<'a>) -> &T {
&self
.graph
.state_ids
.get_symbol(&node.id)
.as_ref()
.map(|x| x.data())
.unwrap()
}
/// Returns a reference to the data (usually statistics or payout information)
/// for `node`.
pub fn node_data(&self, node: NodeRef<'a>) -> &S {
&self.raw_vertex(node).data
}
/// Returns a mutable reference to the data (usually statistics or payout
/// information) for `node`.
pub fn node_data_mut(&mut self, node: NodeRef<'a>) -> &mut S {
&mut self.raw_vertex_mut(node).data
}
/// Returns a reference to the data (usually statistics or payout information)
/// for `edge`.
pub fn edge_data(&self, edge: EdgeRef<'a>) -> &A {
&self.raw_edge(edge).data
}
/// Returns a mutable reference to the data (usually statistics or payout
/// information) for `edge`.
pub fn edge_data_mut(&mut self, edge: EdgeRef<'a>) -> &mut A {
&mut self.raw_edge_mut(edge).data
}
/// Returns a reference to the node that `edge` originates from.
pub fn edge_source(&self, edge: EdgeRef<'a>) -> NodeRef<'a> {
NodeRef {
id: self.raw_edge(edge).source,
_lifetime: self.lifetime,
}
}
/// Returns a reference to the node that `edge` terminates on.
pub fn edge_target(&self, edge: EdgeRef<'a>) -> NodeRef<'a> {
NodeRef {
id: self.raw_edge(edge).target,
_lifetime: self.lifetime,
}
}
/// Returns the number of children (outgoing edges) that `node` has.
pub fn child_count(&self, node: NodeRef<'a>) -> usize {
self.raw_vertex(node).children.len()
}
/// Returns an iterator over the children (outgoing edges) that `node` has.
///
/// ```rust
/// # use search_graph::Graph;
/// # use search_graph::view;
/// # fn main() {
/// let mut g: Graph<String, String, String> = Graph::new();
/// view::of_graph(&mut g, |mut v| {
/// let root = v.append_node("root_state".into(), "root_data".into());
/// let child1 = v.append_node("child1_state".into(), "child1_data".into());
/// let child2 = v.append_node("child2_state".into(), "child2_data".into());
/// let child3 = v.append_node("child3_state".into(), "child3_data".into());
/// v.append_edge(root, child1, "edge1_data".into());
/// v.append_edge(root, child2, "edge2_data".into());
/// v.append_edge(root, child3, "edge3_data".into());
/// let edge_data: Vec<&String> = v.children(root).map(|e| v.edge_data(e)).collect();
/// assert_eq!(edge_data, vec!["edge1_data", "edge2_data", "edge3_data"]);
/// let child_data: Vec<&String> =
/// v.children(root).map(|e| v.node_data(v.edge_target(e))).collect();
/// assert_eq!(child_data, vec!["child1_data", "child2_data", "child3_data"]);
/// });
/// # }
/// ```
pub fn children<'s>(&'s self, node: NodeRef<'a>) -> impl Iterator<Item = EdgeRef<'a>> + 's {
iterate!(for id in self.raw_vertex(node).children.iter();
yield EdgeRef { id: *id, _lifetime: self.lifetime, })
}
/// Returns the number of parents (incoming edges) that `node` has.
pub fn parent_count(&self, node: NodeRef<'a>) -> usize {
self.raw_vertex(node).parents.len()
}
/// Returns an iterator over the parents (incoming edges) that `node` has.
///
/// ```rust
/// # use search_graph::Graph;
/// # use search_graph::view;
/// # fn main() {
/// let mut g: Graph<String, String, String> = Graph::new();
/// view::of_graph(&mut g, |mut v| {
/// let child = v.append_node("child_state".into(), "child_data".into());
/// let parent1 = v.append_node("parent1_state".into(), "parent1_data".into());
/// let parent2 = v.append_node("parent2_state".into(), "parent2_data".into());
/// let parent3 = v.append_node("parent3_state".into(), "parent3_data".into());
/// v.append_edge(parent1, child, "edge1_data".into());
/// v.append_edge(parent2, child, "edge2_data".into());
/// v.append_edge(parent3, child, "edge3_data".into());
/// let edge_data: Vec<&String> = v.parents(child).map(|e| v.edge_data(e)).collect();
/// assert_eq!(edge_data, vec!["edge1_data", "edge2_data", "edge3_data"]);
/// let parent_data: Vec<&String> =
/// v.parents(child).map(|e| v.node_data(v.edge_source(e))).collect();
/// assert_eq!(parent_data, vec!["parent1_data", "parent2_data", "parent3_data"]);
/// });
/// # }
/// ```
pub fn parents<'s>(&'s self, node: NodeRef<'a>) -> impl Iterator<Item = EdgeRef<'a>> + 's {
iterate!(for id in self.raw_vertex(node).parents.iter();
yield EdgeRef { id: *id, _lifetime: self.lifetime, })
}
/// Deletes all graph components that are not reachable by a traversal
/// starting from each of `roots`.
pub fn retain_reachable_from<I: IntoIterator<Item = NodeRef<'a>>>(&mut self, roots: I) {
let root_ids: Vec<VertexId> = roots.into_iter().map(|n| n.id).collect();
self.retain_reachable_from_ids(&root_ids);
}
/// As `retain_reachable_from`, but working over raw `VertexId`s.
fn retain_reachable_from_ids(&mut self, root_ids: &[VertexId]) {
mutators::mark_compact::Collector::retain_reachable(self, root_ids);
}
}
impl<'a, T: Hash + Eq + Clone, S, A> Deref for View<'a, T, S, A> {
type Target = Graph<T, S, A>;
fn deref(&self) -> &Graph<T, S, A> {
self.graph
}
}
impl<'a, T: Hash + Eq + Clone, S, A> DerefMut for View<'a, T, S, A> {
fn deref_mut(&mut self) -> &mut Graph<T, S, A> {
self.graph
}
}
impl<'a, T: Hash + Eq + Clone, S, A> From<View<'a, T, S, A>> for &'a mut Graph<T, S, A> {
fn from(view: View<'a, T, S, A>) -> &'a mut Graph<T, S, A> {
view.graph
}
}
#[derive(Clone, Copy)]
pub struct NodeRef<'a> {
pub(crate) id: VertexId,
pub(crate) _lifetime: InvariantLifetime<'a>,
}
#[derive(Clone, Copy)]
pub struct EdgeRef<'a> {
pub(crate) id: EdgeId,
pub(crate) _lifetime: InvariantLifetime<'a>,
}