use std::sync::atomic::{AtomicU32, Ordering};
static PARTITION_COUNTER: AtomicU32 = AtomicU32::new(1);
pub(crate) fn next_partition_tag() -> u32 {
PARTITION_COUNTER.fetch_add(1, Ordering::Relaxed)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LocalNodeId {
raw: u32,
partition: u32,
}
impl LocalNodeId {
#[inline]
pub fn new(raw: u32, partition: u32) -> Self {
Self { raw, partition }
}
#[inline]
pub fn partition(self) -> u32 {
self.partition
}
#[inline]
#[track_caller]
pub fn raw(self, expected_partition: u32) -> u32 {
assert_eq!(
self.partition, expected_partition,
"LocalNodeId from partition {} used on partition {}",
self.partition, expected_partition
);
self.raw
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn partition_counter_is_monotonic() {
let a = next_partition_tag();
let b = next_partition_tag();
assert!(b > a);
}
#[test]
fn raw_with_matching_partition_returns_id() {
let id = LocalNodeId::new(42, 7);
assert_eq!(id.raw(7), 42);
}
#[test]
#[should_panic(expected = "partition 7 used on partition 9")]
fn raw_with_wrong_partition_panics() {
let id = LocalNodeId::new(42, 7);
let _ = id.raw(9);
}
#[test]
fn tagged_ids_are_copy_and_eq() {
let id = LocalNodeId::new(1, 1);
let copy = id;
assert_eq!(id, copy);
}
}