use std::{
any::{Any, TypeId, type_name},
hash::Hash,
mem,
};
use dyn_clone::DynClone;
pub trait MultiplexEdgeType: DynClone + Any {
fn type_name(&self) -> &'static str;
}
impl<T: Any + Clone> MultiplexEdgeType for T {
fn type_name(&self) -> &'static str {
type_name::<T>()
}
}
pub struct UndirectedMultiplexEdge {
pub(crate) weight: Box<dyn MultiplexEdgeType>,
pub(crate) weight_type: TypeId,
pub(crate) nodes: Vec<usize>,
}
pub struct DirectedMultiplexEdge {
pub(crate) weight: Box<dyn MultiplexEdgeType>,
pub(crate) weight_type: TypeId,
pub(crate) source: Vec<usize>,
pub(crate) target: Vec<usize>,
}
impl DirectedMultiplexEdge {
pub fn remap(&self, map: &Vec<Option<usize>>) -> Option<Self> {
if self.source.iter().any(|&s| map[s].is_none())
|| self.target.iter().any(|&t| map[t].is_none())
{
return None;
}
let source = self.source.iter().map(|&s| map[s].unwrap()).collect();
let target = self.target.iter().map(|&t| map[t].unwrap()).collect();
Some(DirectedMultiplexEdge {
weight: dyn_clone::clone_box(&*self.weight),
weight_type: self.weight_type,
source,
target,
})
}
}
impl UndirectedMultiplexEdge {
pub fn remap(&self, map: &Vec<Option<usize>>) -> Option<Self> {
if self.nodes.iter().any(|&s| map[s].is_none()) {
return None;
}
let nodes = self.nodes.iter().map(|&s| map[s].unwrap()).collect();
Some(UndirectedMultiplexEdge {
weight: dyn_clone::clone_box(&*self.weight),
weight_type: self.weight_type,
nodes,
})
}
}
impl Clone for DirectedMultiplexEdge {
fn clone(&self) -> Self {
Self {
weight: dyn_clone::clone_box(&*self.weight),
weight_type: self.weight_type,
source: self.source.clone(),
target: self.target.clone(),
}
}
}
impl PartialEq for DirectedMultiplexEdge {
fn eq(&self, other: &Self) -> bool {
self.weight_type == other.weight_type
&& self.source == other.source
&& self.target == other.target
&& unsafe { mem::transmute::<_, &[u8]>(&*self.weight) }
== unsafe { mem::transmute::<_, &[u8]>(&*other.weight) }
}
}
impl Eq for DirectedMultiplexEdge {}
impl Hash for DirectedMultiplexEdge {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.weight_type.hash(state);
self.source.hash(state);
self.target.hash(state);
unsafe { mem::transmute::<_, &[u8]>(&*self.weight) }.hash(state);
}
}
impl Clone for UndirectedMultiplexEdge {
fn clone(&self) -> Self {
Self {
weight: dyn_clone::clone_box(&*self.weight),
weight_type: self.weight_type,
nodes: self.nodes.clone(),
}
}
}
impl PartialEq for UndirectedMultiplexEdge {
fn eq(&self, other: &Self) -> bool {
self.weight_type == other.weight_type
&& self.nodes == other.nodes
&& unsafe { mem::transmute::<_, &[u8]>(&*self.weight) }
== unsafe { mem::transmute::<_, &[u8]>(&*other.weight) }
}
}
impl Eq for UndirectedMultiplexEdge {}
impl Hash for UndirectedMultiplexEdge {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.weight_type.hash(state);
self.nodes.hash(state);
unsafe { mem::transmute::<_, &[u8]>(&*self.weight) }.hash(state);
}
}
#[derive(Clone, PartialEq, Eq, Hash, Copy)]
pub enum MultiplexEdge<'a> {
Directed(usize, &'a DirectedMultiplexEdge),
Undirected(usize, &'a UndirectedMultiplexEdge),
}