df_hyperliquid_core/utils/
nonce.rs1#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
6pub struct NonceClock {
7 last: u64,
8}
9
10impl NonceClock {
11 #[must_use]
12 pub const fn new() -> Self {
13 NonceClock { last: 0 }
14 }
15
16 #[must_use]
18 pub const fn after(last: u64) -> Self {
19 NonceClock { last }
20 }
21
22 pub fn next(&mut self, now_ms: u64) -> u64 {
24 let nonce = now_ms.max(self.last.saturating_add(1));
25 self.last = nonce;
26 nonce
27 }
28
29 #[must_use]
30 pub const fn last(&self) -> u64 {
31 self.last
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn a_nonce_follows_the_clock_and_never_repeats() {
41 let mut clock = NonceClock::new();
42 assert_eq!(clock.next(10), 10);
43 assert_eq!(clock.next(10), 11);
44 assert_eq!(clock.next(10), 12);
45 assert_eq!(clock.next(5), 13, "a clock that steps back does not take the nonce with it");
46 assert_eq!(clock.next(100), 100);
47 assert_eq!(clock.last(), 100);
48 }
49
50 #[test]
51 fn two_accounts_keep_their_own_counts() {
52 let mut one = NonceClock::new();
53 let mut two = NonceClock::after(1_790_000_000_000);
54 assert_eq!(one.next(1_790_000_000_000), 1_790_000_000_000);
55 assert_eq!(two.next(1_790_000_000_000), 1_790_000_000_001);
56 assert_eq!(one.last(), 1_790_000_000_000);
57 }
58}