1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::builder::Builder;
use crate::error::*;
use chrono::prelude::*;
use std::{
collections::HashMap,
sync::{Arc, Mutex},
thread,
time::Duration,
};
pub(crate) const BIT_LEN_TIME: u64 = 39;
pub(crate) const BIT_LEN_SEQUENCE: u64 = 8;
pub(crate) const BIT_LEN_MACHINE_ID: u64 = 63 - BIT_LEN_TIME - BIT_LEN_SEQUENCE;
#[derive(Debug)]
pub(crate) struct Internals {
pub(crate) elapsed_time: i64,
pub(crate) sequence: u16,
}
pub(crate) struct SharedSonyflake {
pub(crate) start_time: i64,
pub(crate) machine_id: u16,
pub(crate) internals: Mutex<Internals>,
}
pub struct Sonyflake(Arc<SharedSonyflake>);
impl Sonyflake {
pub fn new() -> Result<Sonyflake, Error> {
Builder::new().finalize()
}
pub fn builder<'a>() -> Builder<'a> {
Builder::new()
}
pub(crate) fn new_inner(shared: Arc<SharedSonyflake>) -> Sonyflake {
Sonyflake(shared)
}
pub fn next_id(&mut self) -> Result<u64, Error> {
let mask_sequence = (1 << BIT_LEN_SEQUENCE) - 1;
let mut internals = self.0.internals.lock().map_err(|_| Error::MutexPoisoned)?;
let current = current_elapsed_time(self.0.start_time);
if internals.elapsed_time < current {
internals.elapsed_time = current;
internals.sequence = 0;
} else {
internals.sequence = (internals.sequence + 1) & mask_sequence;
if internals.sequence == 0 {
internals.elapsed_time += 1;
let overtime = internals.elapsed_time - current;
thread::sleep(sleep_time(overtime));
}
}
if internals.elapsed_time >= 1 << BIT_LEN_TIME {
return Err(Error::OverTimeLimit);
}
Ok(
(internals.elapsed_time as u64) << (BIT_LEN_SEQUENCE + BIT_LEN_MACHINE_ID)
| (internals.sequence as u64) << BIT_LEN_MACHINE_ID
| (self.0.machine_id as u64),
)
}
}
impl Clone for Sonyflake {
fn clone(&self) -> Sonyflake {
Sonyflake(self.0.clone())
}
}
const SONYFLAKE_TIME_UNIT: i64 = 10_000_000;
pub(crate) fn to_sonyflake_time(time: DateTime<Utc>) -> i64 {
time.timestamp_nanos() / SONYFLAKE_TIME_UNIT
}
fn current_elapsed_time(start_time: i64) -> i64 {
to_sonyflake_time(Utc::now()) - start_time
}
fn sleep_time(overtime: i64) -> Duration {
Duration::from_millis(overtime as u64 * 10)
- Duration::from_nanos((Utc::now().timestamp_nanos() % SONYFLAKE_TIME_UNIT) as u64)
}
pub fn decompose(id: u64) -> HashMap<String, u64> {
let mut map = HashMap::new();
let mask_sequence = (1 << BIT_LEN_SEQUENCE) - 1 << BIT_LEN_MACHINE_ID;
let mask_machine_id = (1 << BIT_LEN_MACHINE_ID) - 1;
map.insert("id".into(), id);
map.insert("msb".into(), id >> 63);
map.insert("time".into(), id >> (BIT_LEN_SEQUENCE + BIT_LEN_MACHINE_ID));
map.insert(
"sequence".into(),
(id & mask_sequence) >> BIT_LEN_MACHINE_ID,
);
map.insert("machine-id".into(), id & mask_machine_id);
map
}