mod adjacent;
mod algo;
use crate::error::Error;
use self::{
adjacent::*,
algo::{bfs::*, dfs::*, order::*, pfs::*},
};
use std::{
fmt::Display,
hash::Hash,
ops::Deref,
sync::{Arc, RwLock, Weak},
};
enum Transposition {
Outbound,
Inbound,
}
#[derive(Clone, PartialEq)]
pub struct Edge<K = usize, 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())
}
}
#[derive(Clone)]
pub struct Node<K = usize, N = (), E = ()>
where
K: Clone + Hash + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
inner: Arc<(K, N, RwLock<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: Arc::new((key, value, Adjacent::new())),
}
}
pub fn key(&self) -> &K {
&self.inner.0
}
pub fn value(&self) -> &N {
&self.inner.1
}
pub fn out_degree(&self) -> usize {
self.inner.2.read().unwrap().len_outbound()
}
pub fn in_degree(&self) -> usize {
self.inner.2.read().unwrap().len_inbound()
}
pub fn connect(&self, other: &Self, value: E) {
self.inner
.2
.write()
.unwrap()
.push_outbound((other.clone(), value.clone()));
other
.inner
.2
.write()
.unwrap()
.push_inbound((self.clone(), value));
}
pub fn try_connect(&self, other: &Self, 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> {
match self.find_outbound(other) {
Some(other) => match self.inner.2.write().unwrap().remove_outbound(other.key()) {
Ok(edge) => {
other.inner.2.write().unwrap().remove_inbound(self.key())?;
Ok(edge)
}
Err(_) => Err(Error::EdgeNotFound),
},
None => Err(Error::EdgeNotFound),
}
}
pub fn isolate(&self) {
for Edge(_, v, _) in self.iter_out() {
v.inner
.2
.write()
.unwrap()
.remove_inbound(self.key())
.unwrap();
}
for Edge(v, _, _) in self.iter_in() {
v.inner
.2
.write()
.unwrap()
.remove_outbound(self.key())
.unwrap();
}
self.inner.2.write().unwrap().clear_outbound();
self.inner.2.write().unwrap().clear_inbound();
}
pub fn is_root(&self) -> bool {
self.inner.2.read().unwrap().len_inbound() == 0
}
pub fn is_leaf(&self) -> bool {
self.inner.2.read().unwrap().len_outbound() == 0
}
pub fn is_orphan(&self) -> bool {
self.is_root() && self.is_leaf()
}
pub fn is_connected(&self, other: &K) -> bool {
self.find_outbound(other).is_some()
}
pub fn find_outbound(&self, other: &K) -> Option<Node<K, N, E>> {
let edge = self.inner.2.read().unwrap();
let edge = edge.find_outbound(other);
edge.map(|edge| edge.0.upgrade().unwrap())
}
pub fn find_inbound(&self, other: &K) -> Option<Node<K, N, E>> {
let edge = self.inner.2.read().unwrap();
let edge = edge.find_inbound(other);
edge.map(|edge| edge.0.upgrade().unwrap())
}
pub fn preorder(&self) -> Order<K, N, E> {
Order::preorder(self)
}
pub fn postorder(&self) -> Order<K, N, E> {
Order::postroder(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_out(&self) -> IterOut<K, N, E> {
IterOut {
node: self,
position: 0,
}
}
pub fn iter_in(&self) -> IterIn<K, N, E> {
IterIn {
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.read().unwrap().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 IterOut<'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 IterOut<'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> {
match self
.node
.inner
.2
.read()
.unwrap()
.get_outbound(self.position)
{
Some(current) => {
self.position += 1;
Some(Edge(
self.node.clone(),
current.0.upgrade().unwrap(),
current.1.clone(),
))
}
None => None,
}
}
}
pub struct IterIn<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
node: &'a Node<K, N, E>,
position: usize,
}
impl<'a, K, N, E> Iterator for IterIn<'a, K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Display,
N: Clone,
E: Clone,
{
type Item = Edge<K, N, E>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.inner.2.read().unwrap().get_inbound(self.position) {
Some(current) => {
self.position += 1;
Some(Edge(
current.0.upgrade().unwrap(),
self.node.clone(),
current.1.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 = IterOut<'a, K, N, E>;
fn into_iter(self) -> Self::IntoIter {
IterOut {
node: self,
position: 0,
}
}
}
unsafe impl<K, N, E> Send for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Send,
N: Clone + Send,
E: Clone + Send,
{
}
unsafe impl<K, N, E> Sync for Node<K, N, E>
where
K: Clone + Hash + Display + PartialEq + Eq + Sync,
N: Clone + Sync,
E: Clone + Sync,
{
}