ulid4d
Universally Unique Lexicographically Sortable Identifier (ULID) implementation for Dart, with binary implementation and monotonicity support.
Background
UUID can be suboptimal for many use-cases because:
- It isn’t the most character efficient way of encoding 128 bits of randomness
- UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address
- UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures
- UUID v4 provides no other information than randomness which can cause fragmentation in many data structures
Instead, herein is proposed ULID:
- 128-bit compatibility with UUID
- 1.21e+24 unique ULIDs per millisecond
- Lexicographically sortable!
- Canonically encoded as a 26 character string, as opposed to the 36 character UUID
- Uses Crockford’s base32 for better efficiency and readability (5 bits per character)
- Case-insensitive
- No special characters (URL safe)
- Monotonic sort order (correctly detects and handles the same millisecond)
Usage
- Generate ULID String:
var ulid = ULID.randomULID();
- Generate
ULID
instance:
var ulid = ULID.nextULID();
var ulidString = ulid.toString();
- Generate
ULID
usingULIDFactory
var factory = ULIDFactory();
var ulid = factory.nextULID();
var ulidString = ulid.toString();
You can use ULIDFactory(Random)
to use a different Random
instance.
- Generating
ULID
from/to bytes
// generate a ULID instance
var ulid = ULID.nextULID();
// generate byte array (Uint8List) of ULID instance
var data = ulid.toBytes();
// generate a ULID from given byte array using 'fromBytes'
var ulidFromBytes = ULID.fromBytes(data);
- Generate
ULID
from/to ULID string
// generate a ULID string
var ulidString = ULID.randomULID();
// generate a ULID from given String using 'fromString'
var ulidFromString = ULID.fromString(ulidString);
// generate a ULID String from ULID instance
var ulidStringFromULID = ulid.toString();
Monotonicity
- Generate monotonic
ULID
// generate ULID instance using a monotonic factory
var ulid = ULID.nextMonotonicULID(ulid);
// using a monotonic factory, generate a ULID instance or null in case
// of overflow
var ulidStrict = ULID.nextMonotonicULIDStrict(ulidMono);
- Generate
ULID
usingULIDMonocity
factory
// generate ULID using ULID monotonic factory
var factory = ULIDMonotonic();
var ulid = factory.nextULID(ulid);
var ulidStrict = factory.nextULIDStrict(ulid);
Specification
Below is the current specification of ULID as implemented in this repository.
Components
Timestamp
- 48 bits
- UNIX-time in milliseconds
- Won’t run out of space till the year 10889 AD
Entropy
- 80 bits
- User defined entropy source.
Encoding
Crockford’s Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.
0123456789ABCDEFGHJKMNPQRSTVWXYZ
Binary Layout and Byte Order
The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).
0 1 2 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 32_bit_uint_time_high |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 16_bit_uint_time_low | 16_bit_uint_random |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 32_bit_uint_random |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 32_bit_uint_random |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
String Representation
01AN4Z07BY 79KA1307SR9X4MV3
|----------| |----------------|
Timestamp Entropy
10 chars 16 chars
48bits 80bits
base32 base32
Prior Art
License
ulid4d is an open-sourced software licensed under the BSD 3-clause license.