UUIDv7 in Perl
I came across UUIDv7 in 20 languages, a blog post about UUIDv7. I talked about the new UUIDs a couple of years ago. Since then, they have been approved. This post generates one of them in 20 different languages. I noticed Perl wasn't among them, so I wrote it.
#!/usr/bin/env perl
use v5.40;
use Time::HiRes;
my $value;
# Start with 48 bits of the current time in ms
my $milliseconds = int(Time::HiRes::time * 1000);
vec($value, 0, 32) = $milliseconds >> 16;
vec($value, 2, 16) = $milliseconds;
# Add 80 bits of random
vec($value, $_ + 6, 8) = int(rand(256)) for 0..9;
# Replace version bits with 7.
vec($value, 13, 4) = 7;
# Replace "var" bits with 0b10.
vec($value, 35, 2) = 2;
# Print with dashes, like this
# 0190163d-8694-739b-aea5-966c26f8ad91
my $s = unpack 'H*', $value;
substr($s, $_, 0, '-') for (8, 13, 18, 23);
say $s;
But the article implies that rand
isn't random enough, so I wrote it with urandom
#!/usr/bin/env perl
use v5.40;
use Crypt::URandom;
use Time::HiRes;
# 128 bits (16 bytes) random
my $value = Crypt::URandom::urandom(16);
# Replace first 48 bits with current time in ms
my $milliseconds = int(Time::HiRes::time * 1000);
vec($value, 0, 32) = $milliseconds >> 16;
vec($value, 2, 16) = $milliseconds;
# Replace version bits with 7.
vec($value, 13, 4) = 7;
# Replace "var" bits with 0b10.
vec($value, 35, 2) = 2;
# Print with dashes, like this
# 0190163d-8694-739b-aea5-966c26f8ad91
my $s = unpack 'H*', $value;
substr($s, $_, 0, '-') for (8, 13, 18, 23);
say $s;
But Crypt::URandom is on CPAN, not in the standard library. If we were willing to add a CPAN dependency, we might as well add UUID!
❯ perl -MUUID=uuid7 -E 'say uuid7'
0190274d-abb5-7cdf-8bd7-483dbdd79906
So I didn't contribute a Perl solution to UUIDv7 in N languages.