#![allow(dead_code)]
use std::{
cell::RefCell,
rc::Rc,
};
pub(crate) struct EdgeData;
pub(crate) struct NodeData;
pub(crate) trait Edge<T = Option<EdgeData>, U = Option<NodeData>> {}
impl<T, U> std::fmt::Debug for dyn Edge<T, U> {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(f, "Edge")
}
}
pub(crate) struct Node<T, U> {
pub(crate) edges: Vec<Rc<RefCell<dyn Edge<U, T>>>>,
pub(crate) data: T,
}
impl<T: std::fmt::Debug, U> std::fmt::Debug for Node<T, U> {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
write!(f, "Node {{ data: {:?}, edegs: {:?}}}", self.data, self.edges)
}
}
impl<T: Default, U> Default for Node<T, U> {
fn default() -> Self {
Self { edges: Vec::new(), data: T::default() }
}
}
#[derive(Debug)]
pub(crate) struct DirectedEdge<T, U> {
pub(crate) from: Rc<RefCell<Node<U, T>>>,
pub(crate) to: Rc<RefCell<Node<U, T>>>,
pub(crate) data: T,
}
impl<T, U> Edge<T, U> for DirectedEdge<T, U> {}
impl<T: Default, U> From<(Rc<RefCell<Node<U, T>>>, Rc<RefCell<Node<U, T>>>)>
for DirectedEdge<T, U>
{
fn from(nodes: (Rc<RefCell<Node<U, T>>>, Rc<RefCell<Node<U, T>>>)) -> Self {
Self { from: nodes.0, to: nodes.1, data: T::default() }
}
}
impl<T, U> DirectedEdge<T, U> {
pub(crate) fn new(
from: Rc<RefCell<Node<U, T>>>,
to: Rc<RefCell<Node<U, T>>>,
data: T,
) -> Self {
Self { from, to, data }
}
}
#[derive(Debug)]
pub(crate) struct UndirectedEdge<T, U> {
pub(crate) left: Rc<RefCell<Node<U, T>>>,
pub(crate) right: Rc<RefCell<Node<U, T>>>,
pub(crate) data: T,
}
impl<T, U> Edge<T, U> for UndirectedEdge<T, U> {}
impl<T: Default, U> From<(Rc<RefCell<Node<U, T>>>, Rc<RefCell<Node<U, T>>>)>
for UndirectedEdge<T, U>
{
fn from(nodes: (Rc<RefCell<Node<U, T>>>, Rc<RefCell<Node<U, T>>>)) -> Self {
Self { left: nodes.0, right: nodes.1, data: T::default() }
}
}
impl<T: Clone, U> From<&DirectedEdge<T, U>> for UndirectedEdge<T, U> {
fn from(edge: &DirectedEdge<T, U>) -> Self {
Self {
left: edge.from.clone(),
right: edge.to.clone(),
data: edge.data.clone(),
}
}
}
impl<T, U> UndirectedEdge<T, U> {
pub(crate) fn new(
left: Rc<RefCell<Node<U, T>>>,
right: Rc<RefCell<Node<U, T>>>,
data: T,
) -> Self {
Self { left, right, data }
}
}
#[derive(Debug)]
pub struct MixedGraph<T, U> {
pub(crate) nodes: Vec<Rc<RefCell<Node<T, U>>>>,
}
impl<T, U> MixedGraph<T, U> {
pub fn size(&self) -> usize {
self.nodes.len()
}
pub fn new(size: usize) -> Self
where
T: Default,
{
Self {
nodes: (0..size)
.map(|_| Rc::new(RefCell::new(Node::default())))
.collect(),
}
}
pub fn add_node(&mut self)
where
T: Default,
{
self.nodes.push(Rc::new(RefCell::new(Node::default())));
}
pub fn add_directed_edge(
&mut self,
from: usize,
to: usize,
data: U,
) where
T: 'static,
U: 'static,
{
assert!(from < self.size() && to < self.size());
self.nodes[from].borrow_mut().edges.push(Rc::new(RefCell::new(
DirectedEdge::new(
self.nodes[from].clone(),
self.nodes[to].clone(),
data,
),
)));
}
pub fn add_undirected_edge(
&mut self,
left: usize,
right: usize,
data: U,
) where
T: 'static,
U: 'static,
{
assert!(left < self.size() && right < self.size());
let edge = Rc::new(RefCell::new(UndirectedEdge::new(
self.nodes[left].clone(),
self.nodes[right].clone(),
data,
)));
self.nodes[left].borrow_mut().edges.push(edge.clone());
self.nodes[right].borrow_mut().edges.push(edge.clone());
}
}
#[cfg(test)]
mod tests {
#[test]
fn test() {
use std::{
cell::RefCell,
rc::Rc,
};
#[derive(Debug, Default, Clone)]
struct PureNone;
let node_left = Rc::new(RefCell::new(super::Node::default()));
let node_right = Rc::new(RefCell::new(super::Node::default()));
let edge =
Rc::new(RefCell::new(super::DirectedEdge::<PureNone, usize>::new(
node_left.clone(),
node_right.clone(),
PureNone,
)));
println!("{:?}", edge);
println!("{:?}", node_left);
node_left.borrow_mut().edges.push(edge.clone());
println!("{:?}", edge);
println!("{:?}", node_left);
let edge = Rc::new(RefCell::new(
super::DirectedEdge::<PureNone, usize>::from((
node_left.clone(),
node_right.clone(),
)),
));
println!("{:?}", edge);
println!("{:?}", node_left);
let mut graph = super::MixedGraph::<PureNone, usize>::new(2);
println!("{:?}", graph);
graph.add_directed_edge(0, 1, 3);
println!("{:?}", graph);
graph.add_undirected_edge(0, 1, 2);
println!("{:?}", graph);
}
}