@@ -61,7 +61,6 @@ impl Tuid {
61
61
} ;
62
62
63
63
#[ inline]
64
- #[ cfg( not( target_arch = "wasm32" ) ) ] // TODO(emilk): implement for wasm32 (needs ms since epoch).
65
64
pub fn random ( ) -> Self {
66
65
use std:: cell:: RefCell ;
67
66
@@ -106,35 +105,39 @@ impl Tuid {
106
105
107
106
/// Returns a high-precision, monotonically increasing count that approximates nanoseconds since unix epoch.
108
107
#[ inline]
109
- #[ cfg( not( target_arch = "wasm32" ) ) ]
110
108
fn monotonic_nanos_since_epoch ( ) -> u64 {
111
109
// This can maybe be optimized
110
+ use instant:: Instant ;
112
111
use once_cell:: sync:: Lazy ;
113
- use std:: time:: Instant ;
114
-
115
- fn epoch_offset_and_start ( ) -> ( u64 , Instant ) {
116
- if let Ok ( duration_since_epoch) = std:: time:: UNIX_EPOCH . elapsed ( ) {
117
- let nanos_since_epoch = duration_since_epoch. as_nanos ( ) as u64 ;
118
- ( nanos_since_epoch, Instant :: now ( ) )
119
- } else {
120
- // system time is set before 1970. this should be quite rare.
121
- ( 0 , Instant :: now ( ) )
122
- }
123
- }
124
112
125
- static START_TIME : Lazy < ( u64 , Instant ) > = Lazy :: new ( epoch_offset_and_start ) ;
113
+ static START_TIME : Lazy < ( u64 , Instant ) > = Lazy :: new ( || ( nanos_since_epoch ( ) , Instant :: now ( ) ) ) ;
126
114
START_TIME . 0 + START_TIME . 1 . elapsed ( ) . as_nanos ( ) as u64
127
115
}
128
116
117
+ fn nanos_since_epoch ( ) -> u64 {
118
+ if let Ok ( duration_since_epoch) = instant:: SystemTime :: UNIX_EPOCH . elapsed ( ) {
119
+ let mut nanos_since_epoch = duration_since_epoch. as_nanos ( ) as u64 ;
120
+
121
+ if cfg ! ( target_arch = "wasm32" ) {
122
+ // Web notriously round to the nearest millisecond (because of spectre/meltdown)
123
+ // so we add a bit of extra randomenss here to increase our entropy and reduce the chance of collisions:
124
+ nanos_since_epoch += random_u64 ( ) % 1_000_000 ;
125
+ }
126
+
127
+ nanos_since_epoch
128
+ } else {
129
+ // system time is set before 1970. this should be quite rare.
130
+ 0
131
+ }
132
+ }
133
+
129
134
#[ inline]
130
- #[ cfg( not( target_arch = "wasm32" ) ) ]
131
135
fn random_u64 ( ) -> u64 {
132
136
let mut bytes = [ 0_u8 ; 8 ] ;
133
- getrandom:: getrandom ( & mut bytes) . expect ( "Couldn't get inc " ) ;
137
+ getrandom:: getrandom ( & mut bytes) . expect ( "Couldn't get random bytes " ) ;
134
138
u64:: from_le_bytes ( bytes)
135
139
}
136
140
137
- #[ cfg( not( target_arch = "wasm32" ) ) ]
138
141
#[ test]
139
142
fn test_tuid ( ) {
140
143
use std:: collections:: { BTreeSet , HashSet } ;
0 commit comments