use std::any::Any;
use crate::entity::{Entity, EntityId};
use crate::network::edge::{Edge, EdgeType};
use crate::IxaError;
pub(super) type AdjacencyList<E, ET> = Vec<Edge<E, ET>>;
pub(super) type AdjacencyListVec<E, ET> = Vec<AdjacencyList<E, ET>>;
pub(super) struct Network<E: Entity, ET: EdgeType<E>> {
pub(super) adjacency_lists: AdjacencyListVec<E, ET>,
}
impl<E: Entity, ET: EdgeType<E>> Default for Network<E, ET> {
fn default() -> Self {
Self {
adjacency_lists: AdjacencyListVec::default(),
}
}
}
#[allow(unused)]
impl<E: Entity, ET: EdgeType<E> + 'static> Network<E, ET> {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn new_boxed() -> Box<dyn Any> {
Box::new(Self::new())
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
adjacency_lists: AdjacencyListVec::with_capacity(capacity),
}
}
pub fn reserve(&mut self, additional: usize) {
self.adjacency_lists.reserve(additional);
}
pub fn get_list_cloned(&self, entity_id: EntityId<E>) -> AdjacencyList<E, ET> {
self.adjacency_lists
.get(entity_id.0)
.cloned()
.unwrap_or_default()
}
pub fn get_list(&self, entity_id: EntityId<E>) -> Option<&AdjacencyList<E, ET>> {
self.adjacency_lists.get(entity_id.0)
}
pub fn get_list_mut(&mut self, entity_id: EntityId<E>) -> Option<&mut AdjacencyList<E, ET>> {
self.adjacency_lists.get_mut(entity_id.0)
}
pub fn add_edge(&mut self, entity_id: EntityId<E>, edge: Edge<E, ET>) -> Result<(), IxaError> {
let index = entity_id.0;
if index >= self.adjacency_lists.len() {
self.adjacency_lists
.resize_with(index + 1, Default::default);
}
let edges = &mut self.adjacency_lists[index];
if edges.iter().any(|e| e.neighbor == edge.neighbor) {
return Err(IxaError::EdgeAlreadyExists);
}
edges.push(edge);
Ok(())
}
pub fn remove_edge(
&mut self,
entity_id: EntityId<E>,
neighbor: EntityId<E>,
) -> Option<Edge<E, ET>> {
self.adjacency_lists.get_mut(entity_id.0).and_then(|edges| {
edges
.iter()
.position(|edge| edge.neighbor == neighbor)
.map(|pos| edges.swap_remove(pos))
})
}
pub fn get_edge(&self, entity_id: EntityId<E>, neighbor: EntityId<E>) -> Option<&Edge<E, ET>> {
let index = entity_id.0;
self.adjacency_lists
.get(index)
.and_then(|edges| edges.iter().find(|edge| edge.neighbor == neighbor))
}
pub fn get_edge_mut(
&mut self,
entity_id: EntityId<E>,
neighbor: EntityId<E>,
) -> Option<&mut Edge<E, ET>> {
let index = entity_id.0;
self.adjacency_lists
.get_mut(index)
.and_then(|edges| edges.iter_mut().find(|edge| edge.neighbor == neighbor))
}
pub fn find_entities_by_degree(&self, degree: usize) -> Vec<EntityId<E>> {
self.adjacency_lists
.iter()
.enumerate()
.filter_map(|(pos, edges)| (edges.len() == degree).then_some(EntityId::new(pos)))
.collect()
}
}