1
+ import type { Id } from './Id' ;
2
+
3
+ import IdInternal from './Id' ;
1
4
import * as utils from './utils' ;
2
5
3
6
/**
@@ -22,11 +25,12 @@ const msecPrecision = 3;
22
25
const variantBits = '10' ;
23
26
const versionBits = '0111' ;
24
27
25
- function extractTs ( idBytes : ArrayBuffer ) : number {
28
+ function extractTs ( idBytes : Uint8Array ) : number {
26
29
// Decode the timestamp from the last id
27
30
// the timestamp bits is 48 bits or 6 bytes
28
- const idTsBytes = new Uint8Array ( idBytes , 0 , ( unixtsSize + msecSize ) / 8 ) ;
29
- const idTsBits = utils . bytes2bin ( idTsBytes ) ;
31
+ // this creates a new zero-copy view
32
+ const idTsBytes = idBytes . subarray ( 0 , ( unixtsSize + msecSize ) / 8 ) ;
33
+ const idTsBits = utils . bytes2bits ( idTsBytes ) ;
30
34
const unixtsBits = idTsBits . substr ( 0 , unixtsSize ) ;
31
35
const msecBits = idTsBits . substr ( unixtsSize , unixtsSize + msecSize ) ;
32
36
const unixts = parseInt ( unixtsBits , 2 ) ;
@@ -35,23 +39,21 @@ function extractTs(idBytes: ArrayBuffer): number {
35
39
return utils . fromFixedPoint ( [ unixts , msec ] , msecSize , msecPrecision ) ;
36
40
}
37
41
38
- function extractSeq ( idBytes : ArrayBuffer ) : number {
39
- const idSeqBytes = new Uint8Array (
40
- idBytes ,
42
+ function extractSeq ( idBytes : Uint8Array ) : number {
43
+ const idSeqBytes = idBytes . subarray (
41
44
( unixtsSize + msecSize ) / 8 ,
42
45
( unixtsSize + msecSize + 4 + seqSize ) / 8 ,
43
46
) ;
44
- const idSeqBits = utils . bytes2bin ( idSeqBytes ) . substr ( 4 , seqSize ) ;
47
+ const idSeqBits = utils . bytes2bits ( idSeqBytes ) . substr ( 4 , seqSize ) ;
45
48
const seq = parseInt ( idSeqBits , 2 ) ;
46
49
return seq ;
47
50
}
48
51
49
- function extractRand ( idBytes : ArrayBuffer ) : string {
50
- const idRandBytes = new Uint8Array (
51
- idBytes ,
52
+ function extractRand ( idBytes : Uint8Array ) : string {
53
+ const idRandBytes = idBytes . subarray (
52
54
( unixtsSize + msecSize + 4 + seqSize ) / 8 ,
53
55
) ;
54
- const idRandBits = utils . bytes2bin ( idRandBytes ) . substr ( 2 ) ;
56
+ const idRandBits = utils . bytes2bits ( idRandBytes ) . substr ( 2 ) ;
55
57
return idRandBits ;
56
58
}
57
59
@@ -63,12 +65,12 @@ function extractRand(idBytes: ArrayBuffer): string {
63
65
* 12 bits seq enables 4096 ids per millisecond
64
66
* After 4096, it rolls over
65
67
*/
66
- class IdSortable implements IterableIterator < ArrayBuffer > {
68
+ class IdSortable implements IterableIterator < Id > {
67
69
protected randomSource : ( size : number ) => Uint8Array ;
68
70
protected clock : ( ) => number ;
69
71
protected nodeBits ?: string ;
70
72
protected lastTs ?: [ number , number ] ;
71
- protected lastId_ ?: ArrayBuffer ;
73
+ protected _lastId ?: Id ;
72
74
protected seqCounter : number ;
73
75
74
76
public constructor ( {
@@ -77,8 +79,8 @@ class IdSortable implements IterableIterator<ArrayBuffer> {
77
79
timeSource = utils . timeSource ,
78
80
randomSource = utils . randomBytes ,
79
81
} : {
80
- lastId ?: ArrayBuffer ;
81
- nodeId ?: ArrayBuffer ;
82
+ lastId ?: Uint8Array ;
83
+ nodeId ?: Uint8Array ;
82
84
timeSource ?: ( lastTs ?: number ) => ( ) => number ;
83
85
randomSource ?: ( size : number ) => Uint8Array ;
84
86
} = { } ) {
@@ -96,24 +98,24 @@ class IdSortable implements IterableIterator<ArrayBuffer> {
96
98
}
97
99
}
98
100
99
- get lastId ( ) : ArrayBuffer {
100
- if ( this . lastId_ == null ) {
101
+ get lastId ( ) : Id {
102
+ if ( this . _lastId == null ) {
101
103
throw new ReferenceError ( 'lastId has not yet been generated' ) ;
102
104
}
103
- return this . lastId_ ;
105
+ return this . _lastId ;
104
106
}
105
107
106
- public get ( ) : ArrayBuffer {
107
- return this . next ( ) . value as ArrayBuffer ;
108
+ public get ( ) : Id {
109
+ return this . next ( ) . value as Id ;
108
110
}
109
111
110
- public next ( ) : IteratorResult < ArrayBuffer , void > {
112
+ public next ( ) : IteratorResult < Id , void > {
111
113
// Clock returns millisecond precision
112
114
const ts = this . clock ( ) / 10 ** msecPrecision ;
113
115
// Converting to seconds and subseconds
114
116
const [ unixts , msec ] = utils . toFixedPoint ( ts , msecSize , msecPrecision ) ;
115
- const unixtsBits = utils . dec2bin ( unixts , unixtsSize ) ;
116
- const msecBits = utils . dec2bin ( msec , msecSize ) ;
117
+ const unixtsBits = utils . dec2bits ( unixts , unixtsSize ) ;
118
+ const msecBits = utils . dec2bits ( msec , msecSize ) ;
117
119
if (
118
120
this . lastTs != null &&
119
121
this . lastTs [ 0 ] >= unixts &&
@@ -123,7 +125,7 @@ class IdSortable implements IterableIterator<ArrayBuffer> {
123
125
} else {
124
126
this . seqCounter = 0 ;
125
127
}
126
- const seqBits = utils . dec2bin ( this . seqCounter , seqSize ) ;
128
+ const seqBits = utils . dec2bits ( this . seqCounter , seqSize ) ;
127
129
// NodeBits can be written to the most significant rand portion
128
130
let randBits : string ;
129
131
if ( this . nodeBits != null ) {
@@ -137,17 +139,18 @@ class IdSortable implements IterableIterator<ArrayBuffer> {
137
139
}
138
140
const idBits =
139
141
unixtsBits + msecBits + versionBits + seqBits + variantBits + randBits ;
140
- const idBytes = utils . bin2bytes ( idBits ) ;
142
+ const idBytes = utils . bits2bytes ( idBits ) ;
143
+ const id = IdInternal . create ( idBytes . buffer ) ;
141
144
// Save the fixed point timestamp
142
145
this . lastTs = [ unixts , msec ] ;
143
- this . lastId_ = idBytes . buffer ;
146
+ this . _lastId = id ;
144
147
return {
145
- value : idBytes . buffer ,
148
+ value : id ,
146
149
done : false ,
147
150
} ;
148
151
}
149
152
150
- public [ Symbol . iterator ] ( ) : IterableIterator < ArrayBuffer > {
153
+ public [ Symbol . iterator ] ( ) : IterableIterator < Id > {
151
154
return this ;
152
155
}
153
156
}
0 commit comments