Create ULID from UUID v7
Steps to create a ULID string representation from UUID v7
- convert UUID v7 to byte array
- 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:
- create a UUIDv7 with format “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”
- remove ‘-’
- add eight 0s (4 bytes) to hex string
- convert hex string to binary
- do base32 encoding with RFC4648 character set
- change RFC4648 character set to Crockford’s character set
- 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);
}