tor_proto/channel/
unique_id.rs1use std::fmt::{Display, Formatter};
4use std::sync::atomic::{AtomicUsize, Ordering};
5
6static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct UniqId(usize);
17
18impl UniqId {
19 pub(crate) fn new() -> Self {
21 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
24 assert!(id != usize::MAX, "Exhausted the channel ID namespace");
25 UniqId(id)
26 }
27}
28
29impl Display for UniqId {
30 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31 write!(f, "Chan {}", self.0)
32 }
33}
34
35#[derive(Debug)]
40pub(crate) struct CircUniqIdContext {
41 next_circ_id: usize,
43}
44
45impl CircUniqIdContext {
46 pub(super) fn new() -> Self {
48 CircUniqIdContext { next_circ_id: 0 }
49 }
50 pub(super) fn next(&mut self, unique_id: UniqId) -> crate::tunnel::circuit::UniqId {
52 let circ_unique_id = self.next_circ_id;
53 self.next_circ_id += 1;
54 assert!(
55 self.next_circ_id != 0,
56 "Exhausted the unique circuit ID namespace on a channel"
57 );
58 crate::tunnel::circuit::UniqId::new(unique_id.0, circ_unique_id)
59 }
60}
61
62#[cfg(test)]
63mod test {
64 #![allow(clippy::bool_assert_comparison)]
66 #![allow(clippy::clone_on_copy)]
67 #![allow(clippy::dbg_macro)]
68 #![allow(clippy::mixed_attributes_style)]
69 #![allow(clippy::print_stderr)]
70 #![allow(clippy::print_stdout)]
71 #![allow(clippy::single_char_pattern)]
72 #![allow(clippy::unwrap_used)]
73 #![allow(clippy::unchecked_duration_subtraction)]
74 #![allow(clippy::useless_vec)]
75 #![allow(clippy::needless_pass_by_value)]
76 use super::*;
78 #[test]
79 fn chan_unique_id() {
80 let ids: Vec<UniqId> = (0..10).map(|_| UniqId::new()).collect();
81
82 let mut all_nums: Vec<_> = ids.iter().map(|x| x.0).collect();
84 all_nums.sort_unstable();
85 all_nums.dedup();
86 assert_eq!(all_nums.len(), ids.len());
87
88 assert_eq!(format!("{}", ids[3]), format!("Chan {}", ids[3].0));
89 }
90
91 #[test]
92 fn chan_circid() {
93 let chan_id99 = UniqId(99);
94 let mut ctx = CircUniqIdContext::new();
95
96 let _id0 = ctx.next(chan_id99);
97 let _id1 = ctx.next(chan_id99);
98 let id2 = ctx.next(chan_id99);
99 assert_eq!(format!("{}", id2), "Circ 99.2");
100 }
101}