File Coverage

blib/lib/Data/Rand/Obscure/Generator.pm
Criterion Covered Total %
statement 63 64 98.4
branch 12 20 60.0
condition 6 12 50.0
subroutine 16 16 100.0
pod 2 2 100.0
total 99 114 86.8


line stmt bran cond sub pod time code
1             package Data::Rand::Obscure::Generator;
2              
3 3     3   18 use warnings;
  3         7  
  3         93  
4 3     3   15 use strict;
  3         6  
  3         102  
5              
6             =head1 SYNOPSIS
7              
8             use Data::Rand::Obscure::Generator;
9              
10             my $generator = Data::Rand::Obscure::Generator->new;
11              
12             # Some random hexadecimal string value.
13             $value = $generator->create;
14              
15             ...
16              
17             # Random base64 value:
18             $value = $generator->create_b64;
19              
20             # Random binary value:
21             $value = $generator->create_bin;
22              
23             # Random hexadecimal value:
24             $value = $generator->create_hex;
25              
26             ...
27              
28             # A random value containing only hexadecimal characters and 103 characters in length:
29             $value = $generator->create_hex(length => 103);
30              
31             =head1 DESCRIPTION
32              
33             An objectified version of L<Data::Rand::Obscure> functionality
34              
35             This is the actual workhorse of the distribution, L<Data::Rand::Obscure> contains function wrappers around a singleton object.
36              
37             =cut
38              
39 3     3   19 use Digest;
  3         4  
  3         57  
40 3     3   15 use Carp::Clan;
  3         6  
  3         26  
41 3     3   3016 use Object::Tiny qw/seeder digester/;
  3         1023  
  3         31  
42 3     3   500 use vars qw/$_default_seeder $_default_digester/;
  3         6  
  3         1680  
43              
44             =head1 METHODS
45              
46             =head2 $generator = Data::Rand::Obscure::Generator->new([ seeder => <seeder>, digester => <digester> ])
47              
48             Returns a Data::Rand::Obscure::Generator with the following methods:
49              
50             create
51             create_hex
52             create_bin
53             create_b64
54              
55             You may optionally supply a seeder subroutine, which is called everytime a new value is to be generated.
56             It should return some seed value that will be digested.
57              
58             You may also optionally supply a digester subroutine, which is also called everytime a new value is to be generated.
59             It should return a L<Digest> object of some kind (which will be used to take the digest of the seed value).
60              
61             =head2 $generator->seeder
62              
63             Returns the seeding code reference for $generator
64              
65             =head2 $generator->digester
66              
67             Returns the L<Digest>-generating code reference for $generator
68              
69             =cut
70              
71             sub new {
72 3     3 1 532 my $self = bless {}, shift;
73 3         13 local %_ = @_;
74              
75 3 50 66     29 croak "You supplied a seeder but it's undefined" if exists $_{seeder} && ! $_{seeder};
76 3 50 33     15 croak "You supplied a digester but it's undefined" if exists $_{digester} && ! $_{digester};
77            
78 3   66     39 my $seeder = $self->{seeder} = $_{seeder} || $_default_seeder;
79 3   33     22 my $digester = $self->{digester} = $_{digester} || $_default_digester;
80              
81 3 50       14 croak "The given seeder ($seeder) is not a code reference" unless ref $seeder eq "CODE";
82 3 50       13 croak "The given digester ($digester) is not a code reference" unless ref $digester eq "CODE";
83              
84 3         23 return $self;
85             }
86              
87             sub _create {
88 10039     10039   12030 my $self = shift;
89              
90 10039         290344 my $digest = $self->digester->();
91 10039         624526 my $seed = $self->seeder->();
92 10039         107619 $digest->add($seed);
93 10039         73327 return $digest;
94             }
95              
96             sub _create_to_length {
97 1992     1992   3680 my $self = shift;
98 1992         2814 my $method = shift;
99 1992         2254 my $length = shift;
100 1992 50       4913 $length > 0 or croak "You need to specify a length greater than 0";
101              
102 1992         2574 my $result = "";
103 1992         4863 while (length($result) < $length) {
104 9978         102607 $result .= $self->$method;
105             }
106              
107 1992         35513 return substr $result, 0, $length;
108             }
109              
110             sub _create_bin {
111 3524     3524   4810 my $self = shift;
112 3524         10676 return $self->_create->digest;
113             }
114              
115             sub _create_hex {
116 3837     3837   4927 my $self = shift;
117 3837         6952 return $self->_create->hexdigest;
118             }
119              
120             sub _create_b64 {
121 2678     2678   3707 my $self = shift;
122 2678         5124 return $self->_create->b64digest;
123             }
124              
125             =head1 METHODS
126              
127             =head2 $value = $generator->create([ length => <length> ])
128              
129             =head2 $value = $generator->create_hex([ length => <length> ])
130              
131             Create a random hexadecimal value and return it. If <length> is specificied, then the string will be <length> characters long.
132              
133             If <length> is specified and not a multiple of 2, then $value will technically not be a valid hexadecimal value.
134              
135             =head2 $value = $generator->create_bin([ length => <length> ])
136              
137             Create a random binary value and return it. If <length> is specificied, then the value will be <length> bytes long.
138              
139             =head2 $value = $generator->create_b64([ length => <length> ])
140              
141             Create a random base64 value and return it. If <length> is specificied, then the value will be <length> bytes long.
142              
143             If <length> is specified, then $value is (technically) not guaranteed to be a "legal" b64 value (since padding may be off, etc).
144              
145             =cut
146              
147             sub create {
148 261     261 1 149489 my $self = shift;
149 261         740 return $self->create_hex(@_);
150             }
151              
152             for my $name (map { "create_$_" } qw/hex bin b64/) {
153 3     3   19 no strict 'refs';
  3         4  
  3         971  
154             my $method = "_$name";
155             *$name = sub {
156 2053     2053   9708 my $self = shift;
157 2053 100       5635 return $self->$method unless @_;
158 1992         7387 local %_ = @_;
159 1992 50       9091 return $self->_create_to_length($method, $_{length}) if exists $_{length};
160 0         0 croak "Don't know what you want to do: length wasn't specified, but \@_ was non-empty.";
161             };
162             }
163              
164             # HoD not required. :)
165             my $default_seeder_counter = 0;
166             $_default_seeder = sub {
167             return join("", ++$default_seeder_counter, time, rand, $$, overload::StrVal({}));
168             };
169              
170             my $digest_algorithm;
171             sub _find_digester() {
172 10039 100   10039   22561 unless ($digest_algorithm) {
173 2         8 foreach my $algorithm (qw/SHA-1 SHA-256 MD5/) {
174 2 50       4 if ( eval { Digest->new($algorithm) } ) {
  2         20  
175 2         11473 $digest_algorithm = $algorithm;
176 2         8 last;
177             }
178             }
179 2 50       13 die "Could not find a suitable Digest module. Please install "
180             . "Digest::SHA1, Digest::SHA, or Digest::MD5"
181             unless $digest_algorithm;
182             }
183              
184 10039         30022 return Digest->new($digest_algorithm);
185             }
186              
187             $_default_digester = sub {
188             return _find_digester();
189             };
190              
191             =head1 AUTHOR
192              
193             Robert Krimen, C<< <rkrimen at cpan.org> >>
194              
195             =head1 BUGS
196              
197             Please report any bugs or feature requests to C<bug-data-rand-obscure at rt.cpan.org>, or through
198             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Rand-Obscure>. I will be notified, and then you'll
199             automatically be notified of progress on your bug as I make changes.
200              
201              
202              
203              
204             =head1 SUPPORT
205              
206             You can find documentation for this module with the perldoc command.
207              
208             perldoc Data::Rand::Obscure
209              
210              
211             You can also look for information at:
212              
213             =over 4
214              
215             =item * RT: CPAN's request tracker
216              
217             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Rand-Obscure>
218              
219             =item * AnnoCPAN: Annotated CPAN documentation
220              
221             L<http://annocpan.org/dist/Data-Rand-Obscure>
222              
223             =item * CPAN Ratings
224              
225             L<http://cpanratings.perl.org/d/Data-Rand-Obscure>
226              
227             =item * Search CPAN
228              
229             L<http://search.cpan.org/dist/Data-Rand-Obscure>
230              
231             =back
232              
233              
234             =head1 ACKNOWLEDGEMENTS
235              
236             This package was inspired by (and contains code taken from) the L<Catalyst::Plugin::Session> package by Yuval Kogman
237              
238             =head1 COPYRIGHT & LICENSE
239              
240             Copyright 2007 Robert Krimen, all rights reserved.
241              
242             This program is free software; you can redistribute it and/or modify it
243             under the same terms as Perl itself.
244              
245              
246             =cut
247              
248             1; # End of Data::Rand::Obscure