mod adjacent;
mod algo;
use crate::error::Error;
use std::{
cell::RefCell,
fmt::Display,
hash::Hash,
ops::Deref,
rc::{Rc, Weak},
};
use self::{
adjacent::*,
algo::{bfs::*, dfs::*, order::*, pfs::*},
};
#[derive(Clone)]
pub struct Edge<K, N, E>(pub Node<K, N, E>, pub Node<K, N, E>, pub E)
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone;
impl<K, N, E> Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
pub fn source(&self) -> &Node<K, N, E> {
&self.0
}
pub fn target(&self) -> &Node<K, N, E> {
&self.1
}
pub fn value(&self) -> &E {
&self.2
}
pub fn reverse(&self) -> Edge<K, N, E> {
Edge(self.1.clone(), self.0.clone(), self.2.clone())
}
}
impl<K, N, E> PartialEq for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + Ord,
{
fn eq(&self, other: &Edge<K, N, E>) -> bool {
self.2 == other.2
}
}
impl<K, N, E> Eq for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + Ord,
{
}
impl<K, N, E> PartialOrd for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + Ord,
{
fn partial_cmp(&self, other: &Edge<K, N, E>) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<K, N, E> Ord for Edge<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone + Ord,
{
fn cmp(&self, other: &Edge<K, N, E>) -> std::cmp::Ordering {
self.2.cmp(&other.2)
}
}
#[derive(Clone)]
pub struct Node<K = usize, N = (), E = ()>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
inner: Rc<(K, N, RefCell<Adjacent<K, N, E>>)>,
}
impl<K, N, E> Node<K, N, E>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
pub fn new(key: K, value: N) -> Self {
Node {
inner: Rc::new((key, value, Adjacent::new())),
}
}
pub fn key(&self) -> &K {
&self.inner.0
}
pub fn value(&self) -> &N {
&self.inner.1
}
pub fn degree(&self) -> usize {
self.inner.2.borrow().len_outbound() + self.inner.2.borrow().len_inbound()
}
pub fn connect(&self, other: &Self, value: E) {
self.inner
.2
.borrow_mut()
.push_outbound((other.clone(), value.clone()));
other
.inner
.2
.borrow_mut()
.push_inbound((self.clone(), value));
}
pub fn try_connect(&self, other: &Node<K, N, E>, value: E) -> Result<(), Error> {
if self.is_connected(other.key()) {
Err(Error::EdgeAlreadyExists)
} else {
self.connect(other, value);
Ok(())
}
}
pub fn disconnect(&self, other: &K) -> Result<E, Error> {
self.inner.2.borrow_mut().remove_undirected(other)
}
pub fn isolate(&self) {
for Edge(_, v, _) in self.iter() {
if v.inner.2.borrow_mut().remove_inbound(self.key()).is_err() {
v.inner.2.borrow_mut().remove_outbound(self.key()).unwrap();
}
}
self.inner.2.borrow_mut().clear_outbound();
self.inner.2.borrow_mut().clear_inbound();
}
pub fn is_orphan(&self) -> bool {
self.inner.2.borrow().len_outbound() == 0 && self.inner.2.borrow().len_inbound() == 0
}
pub fn is_connected(&self, other: &K) -> bool {
self.find_adjacent(other).is_some()
}
pub fn find_adjacent(&self, other: &K) -> Option<Node<K, N, E>> {
self.inner
.2
.borrow()
.find_adjacent(other)
.map(|(n, _)| n.upgrade().unwrap())
}
pub fn order(&self) -> Order<K, N, E> {
Order::new(self)
}
pub fn dfs(&self) -> Dfs<K, N, E> {
Dfs::new(self)
}
pub fn bfs(&self) -> Bfs<K, N, E> {
Bfs::new(self)
}
pub fn pfs(&self) -> Pfs<K, N, E>
where
N: Ord,
{
Pfs::new(self)
}
pub fn iter(&self) -> NodeIterator<K, N, E> {
NodeIterator {
node: self,
position: 0,
}
}
pub fn sizeof(&self) -> usize {
std::mem::size_of::<Node<K, N, E>>()
+ std::mem::size_of::<K>()
+ std::mem::size_of::<N>()
+ self.inner.2.borrow().sizeof()
+ std::mem::size_of::<Self>()
}
}
impl<K, N, E> Deref for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Target = N;
fn deref(&self) -> &Self::Target {
self.value()
}
}
impl<K, N, E> PartialEq for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
fn eq(&self, other: &Self) -> bool {
self.key() == other.key()
}
}
impl<K, N, E> Eq for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
}
impl<K, N, E> PartialOrd for Node<K, N, E>
where
K: Clone + Hash + PartialEq + Display + Eq,
N: Clone + Ord,
E: Clone,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.value().cmp(other.value()))
}
}
impl<K, N, E> Ord for Node<K, N, E>
where
K: Clone + Hash + PartialEq + Display + Eq,
N: Clone + Ord,
E: Clone,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value().cmp(other.value())
}
}
pub struct NodeIterator<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
node: &'a Node<K, N, E>,
position: usize,
}
impl<'a, K, N, E> Iterator for NodeIterator<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
fn next(&mut self) -> Option<Self::Item> {
let adjacent = &self.node.inner.2.borrow();
match adjacent.get_adjacent(self.position) {
Some((n, e)) => {
self.position += 1;
Some(Edge(self.node.clone(), n.upgrade().unwrap(), e.clone()))
}
None => None,
}
}
}
impl<'a, K, N, E> IntoIterator for &'a Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
type IntoIter = NodeIterator<'a, K, N, E>;
fn into_iter(self) -> Self::IntoIter {
NodeIterator {
node: self,
position: 0,
}
}
}