File Coverage

blib/lib/Data/TUID.pm
Criterion Covered Total %
statement 49 50 98.0
branch 13 16 81.2
condition 15 24 62.5
subroutine 9 9 100.0
pod 1 3 33.3
total 87 102 85.2


line stmt bran cond sub pod time code
1             package Data::TUID;
2             BEGIN {
3 3     3   276206 $Data::TUID::VERSION = '0.0111_6';
4             }
5             # ABSTRACT: A smaller and more communicable pseudo-UUID
6              
7 3     3   19 use warnings;
  3         4  
  3         61  
8 3     3   8 use strict;
  3         4  
  3         86  
9              
10             =head1 SYNOPSIS
11              
12             use Data::TUID
13              
14             my $tuid = tuid # Generate a TUID of (default) length 8
15             $tuid = tuid length => 4 # Generate a TUID of length 4
16             $tuid = Data::TUID->tuid # Generate a TUID with the default length
17              
18             $tuid = tuid uuid => '1bf4d967-9e4c-4414-9be0-26f31c16fb53' # Generate a TUID based off of the given UUID
19              
20             A sample run (length 4):
21              
22             rrry
23             ggf5
24             m1qb
25             xczx
26             pv9y
27              
28             A sample run (length 8):
29              
30             5xcfw8nj
31             2q255fyg
32             pn3xns4k
33             1xcamd3y
34             eczzca9c
35              
36             A sample run (no length limit):
37              
38             2kdk8wzjmfapj28cvexj6qndq7
39             2tmzr1f3k46tr813dtrxx2vhkqkd
40             1x3608c39mb1n726dhmxedjy72d
41             pre6tg2dm37zbw9amxg2c8bghn
42             3ys0kw21rmtpf54gsmnd28r99pj
43              
44             =head1 DESCRIPTION
45              
46             Data::TUID is a tool for creating small, communicable pseudo-unique identifiers. Essentially it
47             will take a UUID, pass the result through L, and resize accordingly (via
48             C)
49              
50             Although I've tried to sample the UUID evenly, this technique does not give any guarantee on uniqueness. Caveat emptor.
51              
52             Finally, the result is more communicable (and smaller) due to the Crockford base-32 encoding. The Crockford technique
53             uses:
54              
55             A case-insensitive mapping
56             1 in place of '1','I', 'i', and 'L'
57             0 in place of '0', 'O', and 'o'
58              
59             So, given a TUID (say something a user typed in for a URL), you can translate ambiguous characters (1, I, i, L, 0, 0, and o) into to 1 and 0.
60              
61             =head1 USAGE
62              
63             =head2 Data::TUID->tuid( ... )
64              
65             =head2 Data::TUID::tuid( ... )
66              
67             =head2 tuid ...
68              
69             The arguments are:
70              
71             uuid The UUID to use as a basis for the TUID. If none is given, one will be generated for you
72              
73             length The length of the TUID returned. By default 8. A length of -1 will result in the whole
74             UUID being used, and a variable length TUID being returned (somewhere between 25 to 28)
75            
76             =head1 SEE ALSO
77              
78             L
79              
80             L
81              
82             L
83              
84             =cut
85              
86 3     3   17 use vars qw/@ISA @EXPORT/; @ISA = qw/Exporter/; @EXPORT = qw/tuid/;
  3         4  
  3         184  
87              
88 3     3   1281 use Encode::Base32::Crockford qw/base32_encode/;
  3         2675  
  3         146  
89              
90 3     3   955 use Data::TUID::BestUUID;
  3         6  
  3         860  
91              
92             sub new_uuid {
93 10     10 0 28 return Data::TUID::BestUUID->new_uuid( @_ );
94             }
95              
96             sub uuid_to_canonical {
97 10     10 0 27 return Data::TUID::BestUUID->uuid_to_canonical( @_ );
98             }
99              
100             sub tuid {
101 10 100 100 10 1 461 shift if @_ && $_[0] eq __PACKAGE__;
102 10         11 my %given;
103 10 100       14 if ( @_ == 1 ) {
104 3         8 %given = ( length => shift );
105             }
106             else {
107 7         14 %given = @_;
108             }
109              
110 10   33     27 my $uuid = $given{uuid} || new_uuid;
111 10         24 $uuid = uuid_to_canonical( $uuid );
112              
113 10         11 my @tuid;
114             {
115 10         7 my $uuid = $uuid;
  10         8  
116 10         44 $uuid =~ s/-//g;
117 10         41 my @hex = unpack( 'A8 A8 A8 A8', $uuid );
118 10         28 my @value = map { hex $_ } @hex;
  40         56  
119 10         10 my @base32 = map { base32_encode $_ } @value;
  40         554  
120 10         178 @tuid = @base32;
121             }
122              
123 10         8 my $all;
124 10         9 my $size = $given{size};
125 10         21 my $length = $given{length};
126 10 50 33     58 if ( $length && ( $length == -1 || $length >= 28 ) || $size && $size == -1 ) {
      66        
      66        
      33        
127 0         0 return join '', @tuid;
128             }
129 10 100 100     24 $length = 8 unless $length || $size;
130 10 100 66     29 if ( ! $all && $length ) {
131 7         6 $size = int( $length / 4 );
132 7         5 $size += $length % 4;
133             }
134 10 50       28 $size = $size < 1 ? 1 : $size > 7 ? 7 : $size;
    50          
135              
136 10         8 @tuid = map { substr $_, -$size, $size } @tuid;
  40         61  
137 10         16 my $tuid = join '', @tuid;
138 10 100       17 $tuid = substr $tuid, 0, $length if $length;
139              
140 10         51 return $tuid;
141             }
142              
143             =head1 ACKNOWLEDGEMENTS
144              
145             =cut
146              
147             1;