Create ULID from UUID v7

Steps to create a ULID string representation from UUID v7

  1. convert UUID v7 to byte array
  2. do base32 encoding using Crockford’s encoding

However, to use standard base32 encoding software, a padding of 4 bytes to the front is needed so that the boundary of the rightmost byte is at the edge of 5-byte conversion chunk.

To create a ULID string representation in linux shell, we can do

uuidgen -7 | tr -d '-' | sed 's/^/00000000/' | xxd -r -p | base32 | tr "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" "0123456789ABCDEFGHJKMNPQRSTVWXYZ" | cut -c7-

The command above does follow these steps:

  1. create a UUIDv7 with format “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”
  2. remove ‘-’
  3. add eight 0s (4 bytes) to hex string
  4. convert hex string to binary
  5. do base32 encoding with RFC4648 character set
  6. change RFC4648 character set to Crockford’s character set
  7. remove leading six 0s

And we can do the same in C# with slightly different steps.

using ByteDev.Encoding.Base32;

const string rfc4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
const string enccrockford = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
byte[] padding = [0, 0, 0, 0];

var charMap = new Dictionary<char, char>();
for (int i = 0; i < rfc4648.Length; i++)
{
    charMap.Add(rfc4648[i], enccrockford[i]);
}

Guid uuid7 = Guid.CreateVersion7();
if (args.Length == 0)
{
    Base32Encoder encoder = new Base32Encoder();
    byte[] paddedUUID7 = [.. padding, .. uuid7.ToByteArray(bigEndian: true)];
    string u = encoder.Encode(paddedUUID7);
    string v = "";
    foreach (char c in u[6..])
    {
        v += charMap[c];
    }
    Console.WriteLine(v);
}
else if (args[0] == "oo")
{
    Console.WriteLine(uuid7);
}