sfo_cmd_server/
tunnel_id.rs

1use std::hash::{Hash, Hasher};
2use std::sync::atomic::{AtomicU32, Ordering};
3use std::time::{Duration, SystemTime, UNIX_EPOCH};
4use bucky_raw_codec::{RawDecode, RawEncode};
5
6#[derive(Clone, Copy, Ord, PartialEq, Eq, Debug, RawEncode, RawDecode)]
7pub struct TunnelId(u32);
8
9impl TunnelId {
10    pub fn value(&self) -> u32 {
11        self.0
12    }
13
14    fn now(_now: u64) -> u32 {
15        let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() as u32;
16        let since_2021 = Duration::from_secs((50 * 365 + 9) * 24 * 3600).as_secs() as u32;
17        // TODO: 用10年?
18        (now - since_2021) * 10
19    }
20
21    // fn time_bits() -> usize {
22    //     20
23    // }
24}
25
26impl PartialOrd for TunnelId {
27    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
28        if self.0 == 0 || other.0 == 0 {
29            self.0.partial_cmp(&other.0)
30        } else if (std::cmp::max(self.0, other.0) - std::cmp::min(self.0, other.0)) > (u32::MAX / 2)
31        {
32            Some(if self.0 > other.0 {
33                std::cmp::Ordering::Less
34            } else {
35                std::cmp::Ordering::Greater
36            })
37        } else {
38            self.0.partial_cmp(&other.0)
39        }
40    }
41}
42
43impl Default for TunnelId {
44    fn default() -> Self {
45        Self(0)
46    }
47}
48
49impl From<u32> for TunnelId {
50    fn from(v: u32) -> Self {
51        Self(v)
52    }
53}
54
55impl Hash for TunnelId {
56    fn hash<H: Hasher>(&self, state: &mut H) {
57        state.write_u32(self.0)
58    }
59}
60
61pub struct TunnelIdGenerator {
62    cur: AtomicU32,
63}
64
65
66impl From<TunnelId> for TunnelIdGenerator {
67    fn from(init: TunnelId) -> Self {
68        Self {
69            cur: AtomicU32::new(init.value())
70        }
71    }
72}
73
74
75impl TunnelIdGenerator {
76    pub fn new() -> Self {
77        let now = TunnelId::now(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64);
78        Self {
79            cur: AtomicU32::new(now),
80        }
81    }
82
83    pub fn generate(&self) -> TunnelId {
84        let v = self.cur.fetch_add(1, Ordering::SeqCst);
85        if v == 0 {
86            TunnelId(self.cur.fetch_add(1, Ordering::SeqCst))
87        } else {
88            TunnelId(v)
89        }
90    }
91}