|
7 | 7 | <br> |
8 | 8 | </h1> |
9 | 9 |
|
10 | | -[](https://travis-ci.org/alizain/ulid) [](https://codecov.io/gh/alizain/ulid) |
| 10 | +[](https://travis-ci.org/ulid/javascript) [](https://codecov.io/gh/ulid/javascript) |
11 | 11 | [](https://www.npmjs.com/package/ulid) |
12 | 12 |
|
13 | 13 | # Universally Unique Lexicographically Sortable Identifier |
@@ -150,157 +150,11 @@ ulid() // 01BXAVRG61YJ5YSBRM51702F6M |
150 | 150 |
|
151 | 151 | ## Implementations in other languages |
152 | 152 |
|
153 | | -From the community! |
154 | | - |
155 | | -| Language | Author | Binary Implementation | |
156 | | -| -------- | ------ | --------------------- | |
157 | | -| [C++](https://github.com/suyash/ulid) | [suyash](https://github.com/suyash) | ✓ | |
158 | | -| [Clojure](https://github.com/theikkila/clj-ulid) | [theikkila](https://github.com/theikkila) | |
159 | | -| [Objective-C](https://github.com/whitesmith/ulid) | [ricardopereira](https://github.com/ricardopereira) | |
160 | | -| [Crystal](https://github.com/SuperPaintman/ulid) | [SuperPaintman](https://github.com/SuperPaintman) | |
161 | | -| [Dart](https://github.com/agilord/ulid) | [isoos](https://github.com/isoos) | ✓ | |
162 | | -| [Delphi](https://github.com/martinusso/ulid) | [matinusso](https://github.com/martinusso) | |
163 | | -| [D](https://github.com/enckse/ulid) | [enckse](https://github.com/enckse) | |
164 | | -| [D (dub)](https://code.dlang.org/packages/ulid-d) | [extrawurst](https://github.com/Extrawurst) |
165 | | -| [Erlang](https://github.com/savonarola/ulid) | [savonarola](https://github.com/savonarola) | |
166 | | -| [Elixir](https://github.com/merongivian/ulid) | [merongivian](https://github.com/merongivian) | |
167 | | -| [F#](https://github.com/lucasschejtman/FSharp.Ulid) | [lucasschejtman](https://github.com/lucasschejtman) | |
168 | | -| [Go](https://github.com/imdario/go-ulid) | [imdario](https://github.com/imdario/) | |
169 | | -| [Go](https://github.com/oklog/ulid) | [oklog](https://github.com/oklog) | ✓ | |
170 | | -| [Haskell](https://github.com/steven777400/ulid) | [steven777400](https://github.com/steven777400) | ✓ | |
171 | | -| [Java](https://github.com/huxi/sulky/tree/master/sulky-ulid) | [huxi](https://github.com/huxi) | ✓ | |
172 | | -| [Java](https://github.com/azam/ulidj) | [azam](https://github.com/azam) | |
173 | | -| [Java](https://github.com/Lewiscowles1986/jULID) | [Lewiscowles1986](https://github.com/Lewiscowles1986) | |
174 | | -| [Julia](https://github.com/ararslan/ULID.jl) | [ararslan](https://github.com/ararslan) | |
175 | | -| [Lua](https://github.com/Tieske/ulid.lua) | [Tieske](https://github.com/Tieske) | |
176 | | -| [.NET](https://github.com/RobThree/NUlid) | [RobThree](https://github.com/RobThree) | ✓ | |
177 | | -| [.NET](https://github.com/fvilers/ulid.net) | [fvilers](https://github.com/fvilers) |
178 | | -| [Nim](https://github.com/adelq/ulid) | [adelq](https://github.com/adelq) |
179 | | -| [Perl 5](https://github.com/bk/Data-ULID) | [bk](https://github.com/bk) | ✓ | |
180 | | -| [PHP](https://github.com/Lewiscowles1986/ulid) | [Lewiscowles1986](https://github.com/Lewiscowles1986) | |
181 | | -| [PHP](https://github.com/robinvdvleuten/php-ulid) | [robinvdvleuten](https://github.com/robinvdvleuten) | |
182 | | -| [PowerShell](https://github.com/PetterBomban/posh-ulid) | [PetterBomban](https://github.com/PetterBomban) | |
183 | | -| [Python](https://github.com/mdipierro/ulid) | [mdipierro](https://github.com/mdipierro) | |
184 | | -| [Python](https://github.com/ahawker/ulid) | [ahawker](https://github.com/ahawker) | ✓ | |
185 | | -| [Python](https://github.com/mdomke/python-ulid) | [mdomke](https://github.com/mdomke) | ✓ | |
186 | | -| [Ruby](https://github.com/rafaelsales/ulid) | [rafaelsales](https://github.com/rafaelsales) | |
187 | | -| [Rust](https://github.com/mmacedoeu/rulid.rs) | [mmacedoeu](https://github.com/mmacedoeu/rulid.rs) | ✓ | |
188 | | -| [Rust](https://github.com/dylanhart/ulid-rs) | [dylanhart](https://github.com/dylanhart) | ✓ | |
189 | | -| [SQL-Microsoft](https://github.com/rmalayter/ulid-mssql) | [rmalayter](https://github.com/rmalayter) | ✓ | |
190 | | -| [Swift](https://github.com/simonwhitehouse/ULIDSwift) | [simonwhitehouse](https://github.com/simonwhitehouse) | |
191 | | -| [Tcl](https://wiki.tcl-lang.org/48827) | [dbohdan](https://github.com/dbohdan) | |
| 153 | +Refer to [ulid/spec](https://github.com/ulid/spec) |
192 | 154 |
|
193 | 155 | ## Specification |
194 | 156 |
|
195 | | -Below is the current specification of ULID as implemented in this repository. |
196 | | - |
197 | | -*Note: the binary format has not been implemented in JavaScript as of yet.* |
198 | | - |
199 | | -``` |
200 | | - 01AN4Z07BY 79KA1307SR9X4MV3 |
201 | | -
|
202 | | -|----------| |----------------| |
203 | | - Timestamp Randomness |
204 | | - 48bits 80bits |
205 | | -``` |
206 | | - |
207 | | -### Components |
208 | | - |
209 | | -**Timestamp** |
210 | | -- 48 bit integer |
211 | | -- UNIX-time in milliseconds |
212 | | -- Won't run out of space till the year 10895 AD. |
213 | | - |
214 | | -**Randomness** |
215 | | -- 80 bits |
216 | | -- Cryptographically secure source of randomness, if possible |
217 | | - |
218 | | -### Sorting |
219 | | - |
220 | | -The left-most character must be sorted first, and the right-most character sorted last (lexical order). The default ASCII character set must be used. Within the same millisecond, sort order is not guaranteed |
221 | | - |
222 | | -### Canonical String Representation |
223 | | - |
224 | | -``` |
225 | | -ttttttttttrrrrrrrrrrrrrrrr |
226 | | -
|
227 | | -where |
228 | | -t is Timestamp (10 characters) |
229 | | -r is Randomness (16 characters) |
230 | | -``` |
231 | | - |
232 | | -#### Encoding |
233 | | - |
234 | | -Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse. |
235 | | - |
236 | | -``` |
237 | | -0123456789ABCDEFGHJKMNPQRSTVWXYZ |
238 | | -``` |
239 | | - |
240 | | -### Monotonicity |
241 | | - |
242 | | -When generating a ULID within the same millisecond, we can provide some |
243 | | -guarantees regarding sort order. Namely, if the same millisecond is detected, the `random` component is incremented by 1 bit in the least significant bit position (with carrying). For example: |
244 | | - |
245 | | -```javascript |
246 | | -import { monotonicFactory } from 'ulid' |
247 | | - |
248 | | -const ulid = monotonicFactory() |
249 | | - |
250 | | -// Assume that these calls occur within the same millisecond |
251 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ |
252 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS0 |
253 | | -``` |
254 | | - |
255 | | -If, in the extremely unlikely event that, you manage to generate more than 2<sup>80</sup> ULIDs within the same millisecond, or cause the random component to overflow with less, the generation will fail. |
256 | | - |
257 | | -```javascript |
258 | | -import { monotonicFactory } from 'ulid' |
259 | | - |
260 | | -const ulid = monotonicFactory() |
261 | | - |
262 | | -// Assume that these calls occur within the same millisecond |
263 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRY |
264 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ |
265 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS0 |
266 | | -ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS1 |
267 | | -... |
268 | | -ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZX |
269 | | -ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZY |
270 | | -ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZZ |
271 | | -ulid() // throw new Error()! |
272 | | -``` |
273 | | - |
274 | | -#### Overflow Errors when Parsing Base32 Strings |
275 | | - |
276 | | -Technically, a 26-character Base32 encoded string can contain 130 bits of information, whereas a ULID must only contain 128 bits. Therefore, the largest valid ULID encoded in Base32 is `7ZZZZZZZZZZZZZZZZZZZZZZZZZ`, which corresponds to an epoch time of `281474976710655` or `2 ^ 48 - 1`. |
277 | | - |
278 | | -Any attempt to decode or encode a ULID larger than this should be rejected by all implementations, to prevent overflow bugs. |
279 | | - |
280 | | -### Binary Layout and Byte Order |
281 | | - |
282 | | -The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order). |
283 | | - |
284 | | -``` |
285 | | -0 1 2 3 |
286 | | - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
287 | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
288 | | -| 32_bit_uint_time_high | |
289 | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
290 | | -| 16_bit_uint_time_low | 16_bit_uint_random | |
291 | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
292 | | -| 32_bit_uint_random | |
293 | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
294 | | -| 32_bit_uint_random | |
295 | | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
296 | | -``` |
297 | | - |
298 | | -## Prior Art |
299 | | - |
300 | | -Partly inspired by: |
301 | | -- http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram |
302 | | -- https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html |
303 | | - |
| 157 | +Refer to [ulid/spec](https://github.com/ulid/spec) |
304 | 158 |
|
305 | 159 | ## Test Suite |
306 | 160 |
|
|
0 commit comments