use std::fmt::{Display, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct UniqId(usize);
impl UniqId {
pub(crate) fn new() -> Self {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
assert!(id != usize::MAX, "Exhausted the channel ID namespace");
UniqId(id)
}
}
impl Display for UniqId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Chan {}", self.0)
}
}
#[derive(Debug)]
pub(crate) struct CircUniqIdContext {
next_circ_id: usize,
}
impl CircUniqIdContext {
pub(super) fn new() -> Self {
CircUniqIdContext { next_circ_id: 0 }
}
pub(super) fn next(&mut self, unique_id: UniqId) -> crate::circuit::UniqId {
let circ_unique_id = self.next_circ_id;
self.next_circ_id += 1;
assert!(
self.next_circ_id != 0,
"Exhausted the unique circuit ID namespace on a channel"
);
crate::circuit::UniqId::new(unique_id.0, circ_unique_id)
}
}
#[cfg(test)]
mod test {
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::dbg_macro)]
#![allow(clippy::mixed_attributes_style)]
#![allow(clippy::print_stderr)]
#![allow(clippy::print_stdout)]
#![allow(clippy::single_char_pattern)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::unchecked_duration_subtraction)]
#![allow(clippy::useless_vec)]
#![allow(clippy::needless_pass_by_value)]
use super::*;
#[test]
fn chan_unique_id() {
let ids: Vec<UniqId> = (0..10).map(|_| UniqId::new()).collect();
let mut all_nums: Vec<_> = ids.iter().map(|x| x.0).collect();
all_nums.sort_unstable();
all_nums.dedup();
assert_eq!(all_nums.len(), ids.len());
assert_eq!(format!("{}", ids[3]), format!("Chan {}", ids[3].0));
}
#[test]
fn chan_circid() {
let chan_id99 = UniqId(99);
let mut ctx = CircUniqIdContext::new();
let _id0 = ctx.next(chan_id99);
let _id1 = ctx.next(chan_id99);
let id2 = ctx.next(chan_id99);
assert_eq!(format!("{}", id2), "Circ 99.2");
}
}