#![forbid(unsafe_code)]
use crate::core::tds::VertexKey;
use slotmap::Key;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct EdgeKey {
v0: VertexKey,
v1: VertexKey,
}
impl EdgeKey {
#[must_use]
pub fn new(a: VertexKey, b: VertexKey) -> Self {
let a_raw = a.data().as_ffi();
let b_raw = b.data().as_ffi();
if a_raw <= b_raw {
Self { v0: a, v1: b }
} else {
Self { v0: b, v1: a }
}
}
#[inline]
#[must_use]
pub const fn v0(self) -> VertexKey {
self.v0
}
#[inline]
#[must_use]
pub const fn v1(self) -> VertexKey {
self.v1
}
#[inline]
#[must_use]
pub const fn endpoints(self) -> (VertexKey, VertexKey) {
(self.v0, self.v1)
}
}
impl From<(VertexKey, VertexKey)> for EdgeKey {
#[inline]
fn from((a, b): (VertexKey, VertexKey)) -> Self {
Self::new(a, b)
}
}
#[cfg(test)]
mod tests {
use super::*;
use slotmap::SlotMap;
#[test]
fn edge_key_is_canonical() {
let mut vertices: SlotMap<VertexKey, ()> = SlotMap::with_key();
let a = vertices.insert(());
let b = vertices.insert(());
let e1 = EdgeKey::new(a, b);
let e2 = EdgeKey::new(b, a);
assert_eq!(e1, e2);
assert!(e1.v0().data().as_ffi() <= e1.v1().data().as_ffi());
}
#[test]
fn edge_key_endpoints_roundtrip() {
let mut vertices: SlotMap<VertexKey, ()> = SlotMap::with_key();
let a = vertices.insert(());
let b = vertices.insert(());
let e = EdgeKey::new(b, a);
let (v0, v1) = e.endpoints();
assert_eq!(v0, e.v0());
assert_eq!(v1, e.v1());
assert!(v0.data().as_ffi() <= v1.data().as_ffi());
assert_eq!(EdgeKey::from((a, b)), EdgeKey::new(a, b));
}
#[test]
fn edge_key_is_hashable_and_orderable() {
let mut vertices: SlotMap<VertexKey, ()> = SlotMap::with_key();
let a = vertices.insert(());
let b = vertices.insert(());
let c = vertices.insert(());
let mut hash_set: std::collections::HashSet<EdgeKey> = std::collections::HashSet::new();
hash_set.insert(EdgeKey::new(a, b));
hash_set.insert(EdgeKey::new(b, a));
hash_set.insert(EdgeKey::new(a, c));
assert_eq!(hash_set.len(), 2);
let mut btree_set: std::collections::BTreeSet<EdgeKey> = std::collections::BTreeSet::new();
btree_set.insert(EdgeKey::new(a, b));
btree_set.insert(EdgeKey::new(b, a));
btree_set.insert(EdgeKey::new(a, c));
assert_eq!(btree_set.len(), 2);
}
}