use core::borrow::Borrow;
use core::marker::PhantomData;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use crate::collection::{
Collection, CollectionBiject, DrainEntries, InsertableCollection, RandomAccess,
RandomAccessRef, RemovableRandomAccess, StableCollection, UpdatableRandomAccess,
};
use crate::graph::capability::{
Bigraph, Directed, InsertEdge, InsertNode, RemoveEdge, RemoveNode, StableEdge, StableNode,
UniqueNode, UpdateEdge, UpdateNode,
};
use crate::graph::operation::GraphOperation;
use crate::graph::walk_item::{WalkItem, WalkItemMut, WalkItemTo};
use crate::graph::{GraphMap, GraphProperty};
pub use super::hyper_edge::{IncidenceSet, IncidenceSetRef};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct EdgeIx<VIx, EIx>(pub VIx, pub EIx);
impl<VIx: Display, EIx: Display> Display for EdgeIx<VIx, EIx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "e({},{})", self.0, self.1)
}
}
#[derive(Copy, Clone, Debug, Default)]
pub struct TNone;
pub trait IncomingOps<EC, IS, VIx, EIx>
where
EC: RandomAccess<Index = EIx, Storage = VIx>,
{
const MAINTAINED: bool;
unsafe fn record_insert(&mut self, tail: VIx, eix: EdgeIx<VIx, EIx>);
unsafe fn record_remove(&mut self, at: VIx, eix: &EdgeIx<VIx, EIx>);
unsafe fn record_contains(&self, at: VIx, eix: &EdgeIx<VIx, EIx>) -> bool;
unsafe fn collect_incoming(&self, node_ix: VIx) -> Vec<EdgeIx<VIx, EIx>>;
}
impl<NC, EC, V, E, VIx, EIx, IS> IncomingOps<EC, IS, VIx, EIx> for NC
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ UpdatableRandomAccess,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
IS: IncidenceSet<EdgeIx<VIx, EIx>> + for<'a> IncidenceSetRef<'a, EdgeIx<VIx, EIx>>,
VIx: Copy + Eq + 'static,
EIx: Copy + Eq + 'static,
{
const MAINTAINED: bool = true;
#[inline]
unsafe fn record_insert(&mut self, tail: VIx, eix: EdgeIx<VIx, EIx>) {
let inc = &mut unsafe { self.get_storage_unchecked_mut(&tail) }.incoming;
IncidenceSet::insert(inc, eix);
}
#[inline]
unsafe fn record_remove(&mut self, at: VIx, eix: &EdgeIx<VIx, EIx>) {
let inc = &mut unsafe { self.get_storage_unchecked_mut(&at) }.incoming;
IncidenceSet::remove(inc, eix);
}
#[inline]
unsafe fn record_contains(&self, at: VIx, eix: &EdgeIx<VIx, EIx>) -> bool {
let inc = &unsafe { self.get_storage_unchecked(&at) }.incoming;
IncidenceSet::contains(inc, eix)
}
unsafe fn collect_incoming(&self, node_ix: VIx) -> Vec<EdgeIx<VIx, EIx>> {
let inc = &unsafe { self.get_storage_unchecked(&node_ix) }.incoming;
IncidenceSetRef::iter(inc).collect()
}
}
impl<NC, EC, V, E, VIx, EIx> IncomingOps<EC, TNone, VIx, EIx> for NC
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, TNone>>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
for<'a> NC: RandomAccessRef<'a>,
for<'a> EC: RandomAccessRef<'a>,
VIx: Copy + Eq + 'static,
EIx: Copy + Eq + 'static,
{
const MAINTAINED: bool = false;
#[inline]
unsafe fn record_insert(&mut self, _tail: VIx, _eix: EdgeIx<VIx, EIx>) {}
#[inline]
unsafe fn record_remove(&mut self, _at: VIx, _eix: &EdgeIx<VIx, EIx>) {}
#[inline]
unsafe fn record_contains(&self, _at: VIx, _eix: &EdgeIx<VIx, EIx>) -> bool {
false
}
unsafe fn collect_incoming(&self, node_ix: VIx) -> Vec<EdgeIx<VIx, EIx>> {
let mut out = Vec::new();
for head in self.indices() {
let inner = &unsafe { self.get_storage_unchecked(&head) }.outgoing;
for eix in inner.indices() {
let target = unsafe { inner.get_storage_unchecked(&eix) };
if *target == node_ix {
out.push(EdgeIx(head, eix));
}
}
}
out
}
}
#[derive(Clone, Debug)]
pub struct NodeRepr<EC, IS> {
pub(crate) outgoing: EC,
pub(crate) incoming: IS,
}
#[derive(Clone, Debug)]
pub struct FlatAdjEdgeGraph<NC> {
pub(crate) nodes: NC,
}
impl<NC: Default> Default for FlatAdjEdgeGraph<NC> {
fn default() -> Self {
Self {
nodes: NC::default(),
}
}
}
impl<NC: Default> FlatAdjEdgeGraph<NC> {
pub fn new() -> Self {
Self::default()
}
}
pub struct EdgeIndicesFromIter<VIx, II> {
head: VIx,
inner: II,
}
impl<VIx: Copy, EIx, II> Iterator for EdgeIndicesFromIter<VIx, II>
where
II: Iterator<Item = EIx>,
{
type Item = EdgeIx<VIx, EIx>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|eix| EdgeIx(self.head, eix))
}
}
pub struct WalksFromIter<'r, VIx, EC, II> {
head: VIx,
inner_collection: &'r EC,
inner_indices: II,
}
impl<'r, VIx, EC, II> Iterator for WalksFromIter<'r, VIx, EC, II>
where
VIx: Copy + 'r,
EC: RandomAccess<Storage = VIx>,
EC::Value: 'r,
II: Iterator<Item = EC::Index>,
{
type Item = WalkItem<'r, EdgeIx<VIx, EC::Index>, EC::Value, VIx>;
fn next(&mut self) -> Option<Self::Item> {
let eix = self.inner_indices.next()?;
let (edge_val, target) = unsafe { self.inner_collection.get_both_unchecked(&eix) };
Some(WalkItem::new(EdgeIx(self.head, eix), edge_val, *target))
}
}
pub struct WalksToIter<'r, NC, E, II> {
nodes: &'r NC,
incoming_iter: II,
_marker: PhantomData<&'r E>,
}
impl<'r, NC, EC, V, E, VIx, EIx, IS, II> Iterator for WalksToIter<'r, NC, E, II>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>> + 'r,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx> + 'r,
IS: 'r,
VIx: Copy + Eq + 'r,
EIx: Copy + Eq + 'r,
E: 'r,
II: Iterator<Item = EdgeIx<VIx, EIx>>,
{
type Item = WalkItemTo<'r, VIx, EdgeIx<VIx, EIx>, E>;
fn next(&mut self) -> Option<Self::Item> {
let edge_ix = self.incoming_iter.next()?;
let inner = &unsafe { self.nodes.get_storage_unchecked(&edge_ix.0) }.outgoing;
let edge = unsafe { inner.get_value_unchecked(&edge_ix.1) };
Some(WalkItemTo::new(edge_ix.0, edge_ix, edge))
}
}
pub struct EdgeIndicesToIter<II> {
incoming_iter: II,
}
impl<VIx: Copy, EIx: Copy, II> Iterator for EdgeIndicesToIter<II>
where
II: Iterator<Item = EdgeIx<VIx, EIx>>,
{
type Item = EdgeIx<VIx, EIx>;
fn next(&mut self) -> Option<Self::Item> {
self.incoming_iter.next()
}
}
impl<NC, EC, V, E, VIx, EIx, IS> GraphProperty for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
type Node = V;
type Edge = E;
type NodeIx = VIx;
type EdgeIx = EdgeIx<VIx, EIx>;
type Endpoints = [VIx; 2];
const DIRECTED: bool = true;
}
impl<NC, EC, V, E, VIx, EIx, IS> Bigraph for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
fn endpoints_as_array(endpoints: Self::Endpoints) -> [Self::NodeIx; 2] {
endpoints
}
fn endpoints_from_array(nodes: [Self::NodeIx; 2]) -> Self::Endpoints {
nodes
}
}
impl<'r, NC, EC, V, E, VIx, EIx, IS> GraphOperation<'r> for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ IncomingOps<EC, IS, VIx, EIx>
+ InsertableCollection<InsertedIndex = VIx>
+ DrainEntries
+ Default
+ 'r,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>
+ InsertableCollection<InsertedIndex = EIx>
+ DrainEntries
+ Default
+ 'r,
for<'a> NC: RandomAccessRef<'a>,
for<'a> EC: RandomAccessRef<'a>,
IS: Default + 'static,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
V: 'r,
E: 'r,
{
fn contains_node_index(&self, node_ix: Self::NodeIx) -> bool {
self.nodes.contains_index(&node_ix)
}
fn contains_edge_index(&self, edge_ix: Self::EdgeIx) -> bool {
if !self.nodes.contains_index(&edge_ix.0) {
return false;
}
let inner = &unsafe { self.nodes.get_storage_unchecked(&edge_ix.0) }.outgoing;
inner.contains_index(&edge_ix.1)
}
fn len_node(&self) -> usize {
Collection::len(&self.nodes)
}
fn len_edge(&self) -> usize {
let mut total = 0;
for nix in self.nodes.indices() {
let inner = &unsafe { self.nodes.get_storage_unchecked(&nix) }.outgoing;
total += Collection::len(inner);
}
total
}
type NodeIndices = <NC as RandomAccessRef<'r>>::Indices;
fn node_indices(&'r self) -> Self::NodeIndices {
self.nodes.indices()
}
type EdgeIndices = std::vec::IntoIter<EdgeIx<VIx, EIx>>;
fn edge_indices(&'r self) -> Self::EdgeIndices {
let mut out = Vec::new();
for head in self.nodes.indices() {
let inner = &unsafe { self.nodes.get_storage_unchecked(&head) }.outgoing;
for eix in inner.indices() {
out.push(EdgeIx(head, eix));
}
}
out.into_iter()
}
unsafe fn node_unchecked(&self, node_ix: Self::NodeIx) -> &Self::Node {
unsafe { self.nodes.get_value_unchecked(&node_ix) }
}
unsafe fn edge_unchecked(&self, edge_ix: Self::EdgeIx) -> &Self::Edge {
let inner = &unsafe { self.nodes.get_storage_unchecked(&edge_ix.0) }.outgoing;
let val: *const E = unsafe { inner.get_value_unchecked(&edge_ix.1) };
unsafe { &*val }
}
unsafe fn endpoints_unchecked(&self, edge_ix: Self::EdgeIx) -> Self::Endpoints {
let inner = &unsafe { self.nodes.get_storage_unchecked(&edge_ix.0) }.outgoing;
let target = unsafe { inner.get_storage_unchecked(&edge_ix.1) };
[edge_ix.0, *target]
}
type EdgeIndicesFrom = EdgeIndicesFromIter<VIx, <EC as RandomAccessRef<'r>>::Indices>;
unsafe fn edge_indices_from_unchecked(
&'r self,
node_ix: Self::NodeIx,
) -> Self::EdgeIndicesFrom {
let inner = &unsafe { self.nodes.get_storage_unchecked(&node_ix) }.outgoing;
EdgeIndicesFromIter {
head: node_ix,
inner: inner.indices(),
}
}
type EdgeIndicesOf = std::vec::IntoIter<EdgeIx<VIx, EIx>>;
unsafe fn edge_indices_of_unchecked(
&'r self,
node_ix: Self::NodeIx,
) -> Self::EdgeIndicesOf {
let mut out = Vec::new();
let inner = &unsafe { self.nodes.get_storage_unchecked(&node_ix) }.outgoing;
for eix in inner.indices() {
out.push(EdgeIx(node_ix, eix));
}
for eix in unsafe { IncomingOps::collect_incoming(&self.nodes, node_ix) } {
if eix.0 != node_ix {
out.push(eix);
}
}
out.into_iter()
}
type WalksFrom = WalksFromIter<'r, VIx, EC, <EC as RandomAccessRef<'r>>::Indices>;
unsafe fn walks_from_unchecked(&'r self, node_ix: Self::NodeIx) -> Self::WalksFrom {
let inner = &unsafe { self.nodes.get_storage_unchecked(&node_ix) }.outgoing;
WalksFromIter {
head: node_ix,
inner_collection: inner,
inner_indices: inner.indices(),
}
}
type WalksOf = std::vec::IntoIter<WalkItem<'r, EdgeIx<VIx, EIx>, E, VIx>>;
unsafe fn walks_of_unchecked(&'r self, node_ix: Self::NodeIx) -> Self::WalksOf {
let mut out = Vec::new();
let inner = &unsafe { self.nodes.get_storage_unchecked(&node_ix) }.outgoing;
for eix in inner.indices() {
let (edge_val, target) = unsafe { inner.get_both_unchecked(&eix) };
out.push(WalkItem::new(EdgeIx(node_ix, eix), edge_val, *target));
}
for eix in unsafe { IncomingOps::collect_incoming(&self.nodes, node_ix) } {
if eix.0 == node_ix {
continue;
}
let other = &unsafe { self.nodes.get_storage_unchecked(&eix.0) }.outgoing;
let edge_val = unsafe { other.get_value_unchecked(&eix.1) };
out.push(WalkItem::new(eix, edge_val, eix.0));
}
out.into_iter()
}
type DrainNode = std::vec::IntoIter<V>;
type DrainEdge = std::vec::IntoIter<E>;
fn drain(self) -> (Self::DrainNode, Self::DrainEdge) {
let mut node_vals: Vec<V> = Vec::with_capacity(self.nodes.len());
let mut edge_vals: Vec<E> = Vec::new();
for (value, repr) in self.nodes.into_entries() {
node_vals.push(value);
edge_vals.extend(repr.outgoing.into_values());
}
(node_vals.into_iter(), edge_vals.into_iter())
}
fn reverse(&mut self) {
let old = std::mem::take(self);
let mut reversed: Vec<(VIx, VIx, E)> = Vec::new();
for (value, repr) in old.nodes.into_entries() {
let head = unsafe {
crate::unwrap_unchecked(
<Self as InsertNode>::insert_node_unchecked(self, value).ok(),
)
};
for (edge, target) in repr.outgoing.into_entries() {
reversed.push((target, head, edge));
}
}
for (new_head, new_tail, edge) in reversed {
unsafe {
let _ =
<Self as InsertEdge>::insert_edge_unchecked(self, edge, [new_head, new_tail]);
}
}
}
}
impl<'r, NC, EC, V, E, VIx, EIx, IS> Directed<'r> for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ IncomingOps<EC, IS, VIx, EIx>
+ 'r,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx> + 'r,
for<'a> NC: RandomAccessRef<'a>,
for<'a> EC: RandomAccessRef<'a>,
IS: 'static,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
V: 'r,
E: 'r,
{
type EdgeIndicesTo = std::vec::IntoIter<EdgeIx<VIx, EIx>>;
unsafe fn edge_indices_to_unchecked(
&'r self,
node_ix: Self::NodeIx,
) -> Self::EdgeIndicesTo {
unsafe { IncomingOps::collect_incoming(&self.nodes, node_ix) }.into_iter()
}
type WalksTo = std::vec::IntoIter<WalkItemTo<'r, VIx, EdgeIx<VIx, EIx>, E>>;
unsafe fn walks_to_unchecked(&'r self, node_ix: Self::NodeIx) -> Self::WalksTo {
let eixs = unsafe { IncomingOps::collect_incoming(&self.nodes, node_ix) };
let mut out = Vec::with_capacity(eixs.len());
for eix in eixs {
let inner = &unsafe { self.nodes.get_storage_unchecked(&eix.0) }.outgoing;
let edge = unsafe { inner.get_value_unchecked(&eix.1) };
out.push(WalkItemTo::new(eix.0, eix, edge));
}
out.into_iter()
}
type EdgeTailIndices = core::iter::Once<VIx>;
unsafe fn edge_tail_indices_unchecked(
&'r self,
edge_ix: Self::EdgeIx,
) -> Self::EdgeTailIndices {
core::iter::once(edge_ix.0)
}
type EdgeHeadIndices = core::iter::Once<VIx>;
unsafe fn edge_head_indices_unchecked(
&'r self,
edge_ix: Self::EdgeIx,
) -> Self::EdgeHeadIndices {
let inner = &unsafe { self.nodes.get_storage_unchecked(&edge_ix.0) }.outgoing;
let target = unsafe { inner.get_storage_unchecked(&edge_ix.1) };
core::iter::once(*target)
}
}
impl<NC, EC, V, E, VIx, EIx, IS> InsertNode for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ InsertableCollection<InsertedIndex = VIx>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx> + Default,
IS: Default,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
unsafe fn insert_node_unchecked(
&mut self,
node: Self::Node,
) -> Result<Self::NodeIx, Self::Node> {
let storage = NodeRepr {
outgoing: EC::default(),
incoming: IS::default(),
};
self.nodes.insert(node, storage).map_err(|(v, _)| v)
}
}
impl<NC, EC, V, E, VIx, EIx, IS> InsertEdge for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ IncomingOps<EC, IS, VIx, EIx>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>
+ InsertableCollection<InsertedIndex = EIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
unsafe fn insert_edge_unchecked(
&mut self,
edge: Self::Edge,
endpoints: Self::Endpoints,
) -> Result<Self::EdgeIx, Self::Edge> {
let [head, tail] = endpoints;
let inner = &mut unsafe { self.nodes.get_storage_unchecked_mut(&head) }.outgoing;
let eix = match inner.insert(edge, tail) {
Ok(eix) => eix,
Err((v, _)) => return Err(v),
};
let new_edge_ix = EdgeIx(head, eix);
unsafe { IncomingOps::record_insert(&mut self.nodes, tail, new_edge_ix) };
Ok(new_edge_ix)
}
}
impl<'r, NC, EC, V, E, VIx, EIx, IS> UpdateNode<'r> for FlatAdjEdgeGraph<NC>
where
NC: UpdatableRandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ 'r,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx> + 'r,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
V: 'r,
E: 'r,
{
unsafe fn node_unchecked_mut(&mut self, node_ix: Self::NodeIx) -> &mut Self::Node {
unsafe { self.nodes.get_value_unchecked_mut(&node_ix) }
}
type WalksFromMut = std::iter::Empty<WalkItemMut<'r, EdgeIx<VIx, EIx>, E, VIx>>;
unsafe fn walks_from_unchecked_mut(
&'r mut self,
_node_ix: Self::NodeIx,
) -> Self::WalksFromMut {
std::iter::empty()
}
type WalksOfMut = std::iter::Empty<WalkItemMut<'r, EdgeIx<VIx, EIx>, E, VIx>>;
unsafe fn walks_of_unchecked_mut(
&'r mut self,
_node_ix: Self::NodeIx,
) -> Self::WalksOfMut {
std::iter::empty()
}
}
impl<NC, EC, V, E, VIx, EIx, IS> UpdateEdge for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>,
EC: UpdatableRandomAccess<Index = EIx, Value = E, Storage = VIx> + 'static,
IS: 'static,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
unsafe fn edge_unchecked_mut(&mut self, edge_ix: Self::EdgeIx) -> &mut Self::Edge {
let inner = &mut unsafe { self.nodes.get_storage_unchecked_mut(&edge_ix.0) }.outgoing;
unsafe { inner.get_value_unchecked_mut(&edge_ix.1) }
}
}
impl<NC, EC, V, E, VIx, EIx, IS> RemoveEdge for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ IncomingOps<EC, IS, VIx, EIx>,
EC: RemovableRandomAccess<Index = EIx, Value = E, Storage = VIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
unsafe fn take_edge_unchecked(&mut self, edge_ix: Self::EdgeIx) -> Self::Edge {
let head = edge_ix.0;
let node_storage = unsafe { self.nodes.get_storage_unchecked_mut(&head) };
let (edge_value, target, swapped) =
unsafe { node_storage.outgoing.take_unchecked(&edge_ix.1) };
unsafe { IncomingOps::record_remove(&mut self.nodes, target, &edge_ix) };
if let Some(old_last) = swapped {
let old_edge_ix = EdgeIx(head, old_last);
let new_edge_ix = EdgeIx(head, edge_ix.1);
let relocated_target = *unsafe {
self.nodes
.get_storage_unchecked(&head)
.outgoing
.get_storage_unchecked(&edge_ix.1)
};
if unsafe {
IncomingOps::record_contains(&self.nodes, relocated_target, &old_edge_ix)
} {
unsafe {
IncomingOps::record_remove(&mut self.nodes, relocated_target, &old_edge_ix)
};
unsafe {
IncomingOps::record_insert(&mut self.nodes, relocated_target, new_edge_ix)
};
}
}
edge_value
}
}
impl<NC, EC, V, E, VIx, EIx, IS> RemoveNode for FlatAdjEdgeGraph<NC>
where
NC: RemovableRandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ IncomingOps<EC, IS, VIx, EIx>,
EC: RemovableRandomAccess<Index = EIx, Value = E, Storage = VIx>,
for<'a> NC: RandomAccessRef<'a>,
for<'a> EC: RandomAccessRef<'a>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
unsafe fn take_node_unchecked(&mut self, node_ix: Self::NodeIx) -> Self::Node {
let mut incoming_snapshot: Vec<EdgeIx<VIx, EIx>> =
unsafe { IncomingOps::collect_incoming(&self.nodes, node_ix) };
incoming_snapshot.sort_unstable_by(|a, b| b.cmp(a));
for eix in incoming_snapshot.into_iter().filter(|e| e.0 != node_ix) {
let _ = unsafe { self.take_edge_unchecked(eix) };
}
let mut outgoing_eixs: Vec<EIx> = {
let storage = unsafe { self.nodes.get_storage_unchecked(&node_ix) };
storage.outgoing.indices().collect()
};
outgoing_eixs.sort_unstable_by(|a, b| b.cmp(a));
for eix in outgoing_eixs {
let _ = unsafe { self.take_edge_unchecked(EdgeIx(node_ix, eix)) };
}
let (data, _storage, swapped) = unsafe { self.nodes.take_unchecked(&node_ix) };
if let Some(old_last) = swapped {
let heads: Vec<VIx> = self.nodes.indices().collect();
for head in heads {
let storage = unsafe { self.nodes.get_storage_unchecked_mut(&head) };
let eixs: Vec<EIx> = storage.outgoing.indices().collect();
for eix in eixs {
let target = unsafe { storage.outgoing.get_storage_unchecked_mut(&eix) };
if *target == old_last {
*target = node_ix;
}
}
if NC::MAINTAINED {
let entries: Vec<EdgeIx<VIx, EIx>> =
unsafe { IncomingOps::collect_incoming(&self.nodes, head) };
for entry in &entries {
if entry.0 == old_last {
unsafe {
IncomingOps::record_remove(&mut self.nodes, head, entry)
};
}
}
for entry in entries {
if entry.0 == old_last {
unsafe {
IncomingOps::record_insert(
&mut self.nodes,
head,
EdgeIx(node_ix, entry.1),
)
};
}
}
}
}
}
data
}
unsafe fn take_nodes_edges_unchecked<IN, IE>(
&mut self,
node_indices: impl IntoIterator<Item = Self::NodeIx>,
edge_indices: impl IntoIterator<Item = Self::EdgeIx>,
) -> (IN, IE)
where
IN: Default + Extend<Self::Node>,
IE: Default + Extend<Self::Edge>,
{
let mut edges_to_remove: Vec<Self::EdgeIx> = edge_indices.into_iter().collect();
edges_to_remove.sort_unstable_by(|a, b| b.cmp(a));
edges_to_remove.dedup();
let mut edges_out = IE::default();
for eix in edges_to_remove {
let data = unsafe { <Self as RemoveEdge>::take_edge_unchecked(self, eix) };
edges_out.extend(core::iter::once(data));
}
let mut nodes_to_remove: Vec<Self::NodeIx> = node_indices.into_iter().collect();
nodes_to_remove.sort_unstable_by(|a, b| b.cmp(a));
let mut nodes_out = IN::default();
for nix in nodes_to_remove {
let data = unsafe { <Self as RemoveNode>::take_node_unchecked(self, nix) };
nodes_out.extend(core::iter::once(data));
}
(nodes_out, edges_out)
}
}
unsafe impl<NC, EC, V, E, VIx, EIx, IS> StableNode for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ StableCollection,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
}
unsafe impl<NC, EC, V, E, VIx, EIx, IS> StableEdge for FlatAdjEdgeGraph<NC>
where
NC: RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>
+ StableCollection,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx> + StableCollection,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
{
}
impl<NC, EC, V, E, VIx, EIx, IS> UniqueNode for FlatAdjEdgeGraph<NC>
where
NC: StableCollection
+ CollectionBiject
+ RandomAccess<Index = VIx, Value = V, Storage = NodeRepr<EC, IS>>,
EC: RandomAccess<Index = EIx, Value = E, Storage = VIx>,
VIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
EIx: Copy + Eq + Ord + Hash + Display + Debug + 'static,
V: PartialEq,
{
fn node_index(&self, node: impl Borrow<Self::Node>) -> Option<Self::NodeIx> {
unsafe { self.nodes.value_to_key_unchecked(node.borrow()) }.copied()
}
}
impl<'r, N, E, NewN, NewE, IS> GraphMap<'r, NewN, NewE>
for FlatAdjEdgeGraph<Vec<(N, NodeRepr<Vec<(E, u32)>, IS>)>>
{
type Mapped = FlatAdjEdgeGraph<Vec<(NewN, NodeRepr<Vec<(NewE, u32)>, IS>)>>;
fn map<FN, FE>(self, mut fn_node: FN, mut fn_edge: FE) -> Self::Mapped
where
FN: FnMut(Self::Node) -> NewN,
FE: FnMut(Self::Edge) -> NewE,
{
let nodes: Vec<_> = self
.nodes
.into_iter()
.map(|(v, NodeRepr { outgoing, incoming })| {
let new_outgoing: Vec<(NewE, u32)> =
outgoing.into_iter().map(|(e, t)| (fn_edge(e), t)).collect();
(
fn_node(v),
NodeRepr {
outgoing: new_outgoing,
incoming,
},
)
})
.collect();
FlatAdjEdgeGraph { nodes }
}
}