use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{LazyLock, Mutex};
use crate::entity::{Entity, EntityId};
#[derive(Copy, Debug, PartialEq)]
pub struct Edge<E: Entity, ET: EdgeType<E>> {
pub neighbor: EntityId<E>,
pub weight: f32,
pub inner: ET,
}
impl<E: Entity, ET: EdgeType<E>> Clone for Edge<E, ET> {
fn clone(&self) -> Self {
Self {
neighbor: self.neighbor,
weight: self.weight,
inner: self.inner.clone(),
}
}
}
pub trait EdgeType<E: Entity>: Clone + 'static {
fn name() -> &'static str {
let full = std::any::type_name::<Self>();
full.rsplit("::").next().unwrap()
}
fn id() -> usize;
}
static NEXT_EDGE_TYPE_ID_BY_ENTITY: LazyLock<Mutex<HashMap<usize, usize>>> =
LazyLock::new(|| Mutex::new(HashMap::default()));
pub fn get_registered_edge_type_count<E: Entity>() -> usize {
let map = NEXT_EDGE_TYPE_ID_BY_ENTITY.lock().unwrap();
*map.get(&E::id()).unwrap_or(&0)
}
pub fn add_to_edge_type_to_registry<E: Entity, ET: EdgeType<E>>() {
let _ = ET::id();
}
pub fn initialize_edge_type_id<E: Entity>(edge_type_id: &AtomicUsize) -> usize {
let mut guard = NEXT_EDGE_TYPE_ID_BY_ENTITY.lock().unwrap();
let candidate = guard.entry(E::id()).or_insert_with(|| 0);
match edge_type_id.compare_exchange(usize::MAX, *candidate, Ordering::AcqRel, Ordering::Acquire)
{
Ok(_) => {
*candidate += 1;
*candidate - 1
}
Err(existing) => {
existing
}
}
}