use core::hash::Hash;
use std::marker::PhantomData;
use std::ops::Deref;
use crate::graph::Graph;
use crate::node::NodeId;
#[derive(Default, Clone, Copy)]
struct InvariantLifetime<'id>(PhantomData<*mut &'id ()>);
pub struct MutableGraph<'id, T: Eq + Hash + Clone> {
graph: &'id mut Graph<T>,
_marker: InvariantLifetime<'id>,
}
#[derive(Clone, Copy)]
pub struct BrandedNodeId<'id> {
inner: NodeId,
_marker: InvariantLifetime<'id>,
}
impl PartialEq for BrandedNodeId<'_> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl Eq for BrandedNodeId<'_> { }
impl Hash for BrandedNodeId<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl PartialOrd for BrandedNodeId<'_> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for BrandedNodeId<'_> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.inner.cmp(&other.inner)
}
}
impl<'id, T: Eq + Hash + Clone> MutableGraph<'id, T> {
#[allow(clippy::new_ret_no_self)]
pub fn new<F, R>(graph: &'id mut Graph<T>, callback: F) -> R
where
for<'new_id> F: FnOnce(MutableGraph<'new_id, T>) -> R,
{
callback(Self {
graph,
_marker: Default::default(),
})
}
pub fn fetch_id_for_data(&mut self, data: &T) -> BrandedNodeId<'id> {
BrandedNodeId {
inner: self.graph.fetch_id_for_data(data),
_marker: Default::default(),
}
}
pub fn get_node_data_for_id(&self, id: BrandedNodeId<'id>) -> Option<&T> {
self.graph.get_node_data_for_id(id.inner)
}
#[inline(always)]
pub fn add_edge(&mut self, from: BrandedNodeId<'id>, to: BrandedNodeId<'id>) {
self.add_edge_weighted(from, to, 1.0);
}
#[inline(always)]
pub fn add_edge_weighted(
&mut self,
from: BrandedNodeId<'id>,
to: BrandedNodeId<'id>,
weight: f32,
) {
self.graph.add_edge_weighted(from.inner, to.inner, weight);
}
}
impl<'id, T: Eq + Hash + Clone> Deref for MutableGraph<'id, T> {
type Target = Graph<T>;
fn deref(&self) -> &Self::Target {
self.graph
}
}