File Coverage

blib/lib/Integer/Tiny.pm
Criterion Covered Total %
statement 54 54 100.0
branch 18 18 100.0
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 83 83 100.0


line stmt bran cond sub pod time code
1             package Integer::Tiny;
2              
3 2     2   101795 use utf8;
  2         13  
  2         14  
4 2     2   60 use strict;
  2         3  
  2         65  
5 2     2   11 use warnings;
  2         9  
  2         65  
6              
7 2     2   1742 use Math::BigInt;
  2         22916  
  2         24  
8              
9 2     2   16022 use Carp;
  2         5  
  2         1473  
10              
11             our $VERSION = '0.3';
12              
13             sub new {
14 8     8 1 4430 my ($class, $alphabet) = @_;
15              
16 8 100       73 confess 'Missing key in constructor' unless defined $alphabet;
17 7 100       36 confess 'Key is too short' unless length $alphabet >= 2;
18              
19 6         8 my $pos = 0;
20 6         46 my %chars_to_positions = map { $_ => $pos++ } split(//, $alphabet);
  168         421  
21 6         200 my %positions_to_chars = reverse %chars_to_positions;
22 6         20 my $length_of_alphabet = length $alphabet;
23              
24 6 100       34 confess 'Key contains duplicate characters'
25             unless int keys %chars_to_positions == $length_of_alphabet;
26              
27 5         26 my $self = {
28             'c2p' => \%chars_to_positions,
29             'p2c' => \%positions_to_chars,
30             'len' => $length_of_alphabet,
31             };
32              
33 5         46 return bless $self, $class;
34             }
35              
36             sub encrypt {
37 8     8 1 2626 my ($self, $value) = @_;
38 8         13 my $integer;
39              
40 8 100       41 confess 'Value to encrypt not given' unless defined $value;
41              
42 7 100       48 if (ref $value eq 'Math::BigInt') {
    100          
43 1         5 $integer = $value->copy();
44             }
45             elsif ($value =~ m/^\d+$/) {
46 5         23 $integer = Math::BigInt->new($value);
47             }
48             else {
49 1         11 confess 'Value to encrypt is not an Integer or Math::BigInt object';
50             }
51              
52 6         261 my $encrypted = '';
53              
54 6         10 do {
55 321         62175 my $mod = $integer->copy();
56 321         5696 $mod->bmod($self->{'len'});
57 321         49907 $encrypted = $self->{'p2c'}->{$mod} . $encrypted;
58 321         7407 $integer->bdiv($self->{'len'})->bfloor();
59             } while ($integer->is_pos());
60              
61 6         998 return $encrypted;
62              
63             }
64              
65             sub decrypt {
66 9     9 1 3467 my ($self, $encrypted) = @_;
67              
68 9 100       43 confess 'Value encrypted not given' unless defined $encrypted;
69 8 100       40 confess 'Value encrypted is an empty string' unless length $encrypted;
70              
71 7         11 my $pos = 0;
72 7         40 my $integer = Math::BigInt->new(0);
73 7         3122 my @chars = reverse split //, $encrypted;
74              
75 7 100       28 confess 'Value encrypted contains characters not present in key' if grep { !defined $self->{'c2p'}->{$_} } @chars;
  322         632  
76              
77 6         14 for my $ch (@chars) {
78 321         31423 my $to_add = Math::BigInt->new($self->{'len'});
79 321         12471 $to_add->bpow($pos++);
80 321         333063 $to_add->bmul($self->{'c2p'}->{$ch});
81 321         58484 $integer->badd($to_add);
82             }
83              
84 6         459 return $integer;
85             }
86              
87             =head1 NAME
88              
89             Integer::Tiny - Shorten and obfuscate your Integer values. Just like IDs on YouTube!
90              
91             =head1 SYNOPSIS
92              
93             use Integer::Tiny;
94             $it = Integer::Tiny->new('0WEMACKGVPHRQNST862UYZ3FL4X17O59DJIB');
95             print $it->encrypt('12345678'); # prints 'GQZB2'
96             print $it->decrypt('GQZB2'); # prints '12345678'
97              
98             Check USAGE section for more cool examples.
99              
100             =head1 DESCRIPTION
101              
102             Do you need fast and reliable method to obfuscate and shorten some Integer values?
103              
104             Do you want to choose characters range you can use in output?
105              
106             This module is for you!
107              
108             =head1 USAGE
109              
110             Typical encrypt-and-shorten suitable for URL addresses.
111              
112             my $key = 'hc2riK8fku7ezavCBJdMPwmntZ1s0yU4bOLI3SHRqANXFVD69gTG5oYQjExplW';
113             my $it = Integer::Tiny->new($key);
114             print $it->encrypt('48888851145'); # om3R4e
115              
116             Time to clone someone, convert Integer to DNA sequence :)
117              
118             my $key = 'GCAT';
119             my $it = Integer::Tiny->new($key);
120             print $it->encrypt('48888851145'); # ATCAGAGGGGAAAATGAC
121              
122             And so on... You're limited only by your imagination when inventing keys.
123              
124             This module is suitable for most Internet usage,
125             like preventing your webpages from being scanned by ID sequence
126             or hiding informations you do not like to show explicitly.
127              
128             =head1 KEYS
129              
130             Key must be a String of AT LEAST TWO UNIQUE CHARACTERS (utf8 is allowed).
131              
132             Characters used in key will also be your output characters range, simple as that!
133              
134             The longer the key the shorter output you get!
135              
136             Here is some code snippet to generate typical alphanumeric keys.
137              
138             use List::Util;
139             my @t = ('a' .. 'z', 'A' .. 'Z', 0 .. 9);
140             $key = join('', List::Util::shuffle @t );
141              
142             =head1 METHODS
143              
144             =head3 new
145              
146             my $it = Integer::Tiny->new('qwerty');
147              
148             Create new object of C using key passed as the first parameter.
149              
150             C will be called on missing or invalid key.
151              
152             =head3 encrypt
153              
154             print $it->encrypt('48888851145'); # rtetrwqyteytyr
155              
156             or
157              
158             my $i = Math::BigInt->new('48888851145');
159             print $it->encrypt($i); # rtetrwqyteytyr
160              
161             Encrypt passed Integer value (bigint allowed) using key given in constructor.
162              
163             C will be called if value to encrypt is missing or not an Integer.
164              
165             WARNING: Do not use syntax shown below unless you are sure it fits in your machine integer size.
166              
167             print $it->encrypt(48888851145); # integer may overflow
168              
169             NOTE: Passed value is treated as Integer so leading C<0> (zero) chars are ignored!
170              
171             my $e = $it->encrypt('0048888851145');
172             print $it->decrypt($e); # 48888851145
173              
174             =head3 decrypt
175              
176             print $it->decrypt('rtetrwqyteytyr'); # 48888851145
177              
178             Decrypt passed value using key given in constructor.
179              
180             C will be called if value to decrypt is missing
181             or contains characters not existing in key.
182              
183             =head1 PERL6
184              
185             Yes, P6 Rakudo version is on the way
186              
187             =head1 AUTHOR
188              
189             Pawel (bbkr) Pabian
190              
191             Private website: L (visit for contact data)
192              
193             Company website: L
194              
195             =head1 COPYRIGHT
196              
197             This program is free software; you can redistribute
198             it and/or modify it under the same terms as Perl itself.
199              
200             The full text of the license can be found in the
201             LICENSE file included with this module.
202              
203             =cut
204              
205             1;