wd_sonyflake/
sonyflake.rs1use std::sync::atomic::{AtomicU64, AtomicU32,Ordering};
8use chrono::Utc;
9use std::net::UdpSocket;
10
11pub struct SonyFlakeEntity{
12 time_stamp:AtomicU64,
13 counter:AtomicU32,
14 node_id:u16,
15}
16
17impl SonyFlakeEntity{
18 pub fn new(nodeid:u16)->Self{
19 SonyFlakeEntity{
20 time_stamp:AtomicU64::new(0),
21 counter:AtomicU32::new(0),
22 node_id:nodeid,
23 }
24 }
25 pub fn new_default()->Self{
27 let mut nodeid = 1;
28 if let Some(s)=get_ip(){
29 let ips:Vec<_> = s.split('.').collect();
30 let a = ips[2].parse::<u8>().unwrap();
31 let b = ips[3].parse::<u8>().unwrap();
32 nodeid = u16::from_be_bytes([a,b]);
33 }
34 SonyFlakeEntity{
35 time_stamp:AtomicU64::new(0),
36 counter:AtomicU32::new(0),
37 node_id:nodeid,
38 }
39 }
40
41 pub fn get_id(&self)->i64{
42 let (ts,sid) = self.get_ts_sid();
43 return Self::generate_id(ts,sid,self.node_id);
44 }
45
46 #[allow(unused_assignments)]
47 fn get_ts_sid(&self)->(u64,u32){
48 let mut timestamp = 0;
49 let mut sequence:u32 = 0;
50 let ntime = Utc::now().timestamp_millis() as u64;
51 let otime = self.time_stamp.load(Ordering::Acquire);
52 if ntime <= otime{
53 sequence = self.counter.fetch_add(1,Ordering::Relaxed);
54 timestamp = otime; }else{
56 self.counter.store(1,Ordering::Relaxed);
57 timestamp = ntime;
58 self.time_stamp.store(ntime,Ordering::Release);
59 }
60 return (timestamp,sequence);
61 }
62 fn generate_id(ts:u64,sid:u32,nid:u16)->i64{
63 let mut res:Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0];
64 let ts = ts << 22;
65 let vts = Vec::from(ts.to_be_bytes());
66 for i in 0..6{
67 res[i] = res[i] | vts[i];
68 }
69 res[0] = res[0]&0x7F;
70 let mut vnid = Vec::from(nid.to_be_bytes());
72 vnid[0] = vnid[0] & 0x03;
73 res[5] = res[5]|vnid[0];
74 res[6] = res[6]|vnid[1];
75 let mut vsid = Vec::from(sid.to_be_bytes());
76 vsid[2] = vsid[2]&0x0F;
77 res[6] = res[6]|vsid[2];
78 res[7] = res[7]|vsid[3];
79 i64::from_be_bytes([res[0],res[1],res[2],res[3],res[4],res[5],res[6],res[7]])
80 }
81}
82
83pub fn get_ip() -> Option<String> {
84 let socket = match UdpSocket::bind("0.0.0.0:0") {
85 Ok(s) => s,
86 Err(_) => return None,
87 };
88
89 match socket.connect("8.8.8.8:80") {
90 Ok(()) => (),
91 Err(_) => return None,
92 };
93
94 match socket.local_addr() {
95 Ok(addr) => return Some(addr.ip().to_string()),
96 Err(_) => return None,
97 };
98}