use std;
use std::fmt::Debug;
use std::str::FromStr;
use util;
type AdjacencyMap<T> = util::HashMap<String, Option<T>>;
type AdjacencyMatrix<T> = util::HashMap<String, AdjacencyMap<T>>;
pub struct Adjacency<M: Clone> {
edges: AdjacencyMatrix<M>,
}
impl<M: Clone + Debug> Default for Adjacency<M> {
fn default() -> Adjacency<M> {
Adjacency {
edges: Default::default(),
}
}
}
impl<M: Clone + Debug> Adjacency<M> {
pub fn new() -> Self {
Adjacency {
edges: Default::default(),
}
}
pub fn add_asymmetric_edge(
&mut self,
from_str: &str,
to_str: &str,
metadata: Option<M>,
) {
let to = String::from_str(to_str).unwrap();
let from = String::from_str(from_str).unwrap();
let vec = self.edges.entry(from).or_insert_with(Default::default);
vec.insert(to, metadata);
}
pub fn add_edges(
&mut self,
from_str: &str,
to_strs: Vec<String>,
metadata: Option<M>,
) {
for to_str in to_strs {
self.add_asymmetric_edge(from_str, &to_str, metadata.clone());
self.add_asymmetric_edge(&to_str, from_str, metadata.clone())
}
drop(metadata);
}
pub fn num_edges(&mut self, id: &str) -> usize {
match self.edges.get(id) {
Some(value) => value.keys().len(),
None => 0,
}
}
pub fn contains_node(&self, id: &str) -> bool {
self.edges.contains_key(id)
}
pub fn filter_nodes<F>(&self, id: &str, f: F) -> Vec<String>
where
for<'r> F: FnMut(&'r (&String, &Option<M>)) -> bool,
{
self.edges[id]
.iter()
.filter(f)
.map(|(k, _v)| k.clone())
.collect()
}
pub fn iter(&self) -> std::collections::hash_map::Iter<String, AdjacencyMap<M>> {
self.edges.iter()
}
pub fn pop(&mut self, id: &str) -> Option<AdjacencyMap<M>> {
self.edges.remove(id)
}
pub fn pop_nodes(&mut self, id: &str) -> Vec<String> {
match self.pop(id) {
Some(map) => map.into_iter().map(|(k, _v)| k).collect(),
None => Vec::new(),
}
}
pub fn pop_metadata(&mut self, id: &str) -> Vec<M> {
match self.pop(id) {
Some(map) => map.into_iter()
.filter(|&(ref _k, ref option_v)| option_v.is_some())
.map(|(_, some_v)| some_v.unwrap())
.collect(),
None => Vec::new(),
}
}
}