UniqueID - time-ordered UUIDs in Swift

It's similar - as mentioned in the RFC, lots of new unique identifier formats exist which try to solve the same basic problem. CUID is another one I tend to come across quite frequently (IDs are easily recognisable because they begin with a 'c' - e.g. cjld2cyuq0000t3rmniod1foy).

Some of these use smaller identifiers (64 vs 128 bits), or base32/64 strings rather than hexadecimal. It seems the RFC author wanted to include shorter text formats, but it didn't make it to the draft. I can imagine that having 3 official text formats for UUIDs is just too awkward to include in a formal internet standard (of course, any application can decide to use a non-standard text format).

The biggest advantage of UUIDv6 is that it's a lot easier to adopt, compared to a completely different identifier:

  • Binary compatibility. It uses the same 128-bits as UUIDv4, with version and variant bits in the same position so the same software can process them. They can live side-by-side in a single database table; you might not get all of the performance benefits, but they will never collide.

  • String compatibility. The default serialisation is still the 8-4-4-4-12 string format, so code which parses UUIDs from JSON continues to work, like nothing changed.

  • Easily convertible to UUIDv1. It uses exactly the same timestamp epoch, format, and precision, just in a way that's better for sorting. Converting between them is a matter of swapping some bytes:

    +--------------+------+--------------+
    | UUIDv1 Field | Bits | UUIDv6 Field |
    +--------------+------+--------------+
    | time_low     | 32   | time_high    |
    +--------------+------+--------------+
    | time_mid     | 16   | time_mid     |
    +--------------+------+--------------+
    | time_high    | 12   | time_low     |
    +--------------+------+--------------+
    

    It might be worth adding a function to do that, but on the other hand I'm not sure UUIDv1 caught on enough to matter (mostly because of the weird timestamp layout).

The foundation dependency is limited to this file, and is for only 2 things:

Ideally, we'd have a cross-import overlay for Foundation. In the mean time, it's probably worth adding a build flag to opt-out of them. For App developers, it's really important that their existing codebases using Foundation's UUID continue to work, so I think the right default is to include it.

(But actually, part of the point of having a new "UniqueID" type rather than adding extensions on to UUID was to allow using it without Foundation)

3 Likes