Token Templates

2015-08-28

Andrew Beverley requested a feature for my Session::Token module so I suggested what I'm calling token templates.

Andrew was after something like String::Random's randpattern. This is a neat feature which lets you make tokens of a particular format.

This was my suggestion:

use Session::Token;

sub token_template {
  my (%m) = @_;

  %m = map { $_ => Session::Token->new(alphabet => $m{$_}, length => 1) }
           keys %m;

  return sub {
    my $v = shift;
    $v =~ s/(.)/exists $m{$1} ? $m{$1}->get : $1/eg;
    return $v;
  };
}

With this utility you can easily create tokens such as UUID version 4 tokens:

sub uuid_v4_generator {
  my $t = token_template(
        x => [ 0..9, 'a'..'f' ],
        y => [ 8, 9, 'a', 'b' ],
      );

  return sub {
    return $t->('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx');
  }
}

This generator creates tokens such as the following:

1b782499-9913-4726-a80a-25e7b2221a7c
90f85a64-d826-43bf-98e7-94ba87406bfb
b8b73175-3cce-4861-b43b-3dec5ed5d641
3afb64ab-6de3-4647-bbff-eb94dfa7d4b0
447d2001-2aec-4d32-9910-8c289ae34c48

It's by far not the most efficient solution, but it's only slightly slower than String::Random's version, and of course you get all the unbiased, cryptographic security guarantees you'd expect from Session::Token.

Update: As of Session::Token 1.500, the token template solution is slightly faster than String::Random:

$ perl token-template-bench.pl
Benchmark: timing 500000 iterations of Session::Token, String::Random...
Session::Token:  6 wallclock secs ( 5.84 usr +  0.00 sys =  5.84 CPU) @ 85616.44/s (n=500000)
String::Random:  7 wallclock secs ( 6.36 usr +  0.00 sys =  6.36 CPU) @ 78616.35/s (n=500000)

You can download the benchmarking code here: bench.pl