use core::fmt;
use core::hash::{Hash, Hasher};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct NodeIndex {
pub(crate) index: usize,
pub(crate) generation: u32,
}
impl NodeIndex {
#[inline]
pub(crate) fn new(index: usize, generation: u32) -> Self {
Self { index, generation }
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
#[inline]
pub fn generation(&self) -> u32 {
self.generation
}
#[inline]
#[allow(dead_code)]
pub(crate) fn is_valid(&self) -> bool {
self.index != usize::MAX
}
#[inline]
#[allow(dead_code)]
pub(crate) fn invalid() -> Self {
Self {
index: usize::MAX,
generation: 0,
}
}
}
impl fmt::Debug for NodeIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NodeIndex({}, {})", self.index, self.generation)
}
}
impl fmt::Display for NodeIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.index)
}
}
impl Hash for NodeIndex {
fn hash<H: Hasher>(&self, state: &mut H) {
self.index.hash(state);
self.generation.hash(state);
}
}
pub struct NodeRef<'a, T> {
pub index: NodeIndex,
pub data: &'a T,
}
impl<'a, T> NodeRef<'a, T> {
#[inline]
pub fn new(index: NodeIndex, data: &'a T) -> Self {
Self { index, data }
}
#[inline]
pub fn index(&self) -> NodeIndex {
self.index
}
#[inline]
pub fn data(&self) -> &'a T {
self.data
}
#[inline]
pub fn get(&self) -> &'a T {
self.data
}
}
impl<'a, T> Clone for NodeRef<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> Copy for NodeRef<'a, T> {}
impl<'a, T> fmt::Debug for NodeRef<'a, T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeRef")
.field("index", &self.index)
.field("data", self.data)
.finish()
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>"))
)]
#[repr(align(64))]
pub(crate) struct NodeSlot<T> {
pub generation: u32,
pub data: Option<T>,
}
impl<T> Clone for NodeSlot<T> {
fn clone(&self) -> Self {
Self {
generation: self.generation,
data: None, }
}
}
impl<T> NodeSlot<T> {
#[inline]
pub(crate) fn new(generation: u32, data: T) -> Self {
Self {
generation,
data: Some(data),
}
}
#[inline]
#[allow(dead_code)]
pub(crate) fn deleted(generation: u32) -> Self {
Self {
generation,
data: None,
}
}
#[inline]
pub(crate) fn is_occupied(&self) -> bool {
self.data.is_some()
}
#[inline]
pub(crate) fn data(&self) -> Option<&T> {
self.data.as_ref()
}
#[inline]
#[allow(dead_code)]
pub(crate) fn data_mut(&mut self) -> Option<&mut T> {
self.data.as_mut()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_index_creation() {
let idx = NodeIndex::new(42, 1);
assert_eq!(idx.index(), 42);
assert_eq!(idx.generation(), 1);
assert!(idx.is_valid());
}
#[test]
fn test_node_index_invalid() {
let idx = NodeIndex::invalid();
assert!(!idx.is_valid());
assert_eq!(idx.index(), usize::MAX);
}
#[test]
fn test_node_index_hash() {
use core::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
let idx1 = NodeIndex::new(42, 1);
let idx2 = NodeIndex::new(42, 1);
let idx3 = NodeIndex::new(42, 2);
let mut h1 = DefaultHasher::new();
let mut h2 = DefaultHasher::new();
let mut h3 = DefaultHasher::new();
idx1.hash(&mut h1);
idx2.hash(&mut h2);
idx3.hash(&mut h3);
assert_eq!(h1.finish(), h2.finish());
assert_ne!(h1.finish(), h3.finish());
}
#[test]
fn test_node_slot() {
let mut slot = NodeSlot::new(1, "test");
assert!(slot.is_occupied());
assert_eq!(slot.data(), Some(&"test"));
assert_eq!(slot.data_mut(), Some(&mut "test"));
let deleted: NodeSlot<&str> = NodeSlot::deleted(1);
assert!(!deleted.is_occupied());
assert_eq!(deleted.data(), None);
}
}