File Coverage

blib/lib/MAD/Scrambler.pm
Criterion Covered Total %
statement 40 40 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod 4 4 100.0
total 52 52 100.0


line stmt bran cond sub pod time code
1             package MAD::Scrambler;
2             $MAD::Scrambler::VERSION = '0.000003';
3 2     2   226310 use Moo;
  2         37578  
  2         13  
4             extends 'Exporter';
5              
6             our @EXPORT_OK = qw{
7             nibble_split
8             nibble_join
9             };
10              
11 2     2   4054 use List::Util qw{ shuffle };
  2         5  
  2         238  
12              
13 2     2   1758 use Const::Fast;
  2         2173  
  2         13  
14              
15             const our $MAX_NUMBER => 2**32;
16              
17             has 'scrambler' => (
18             is => 'ro',
19             lazy => 1,
20             default => sub { [ shuffle 0 .. 7 ] },
21             );
22              
23             has 'unscrambler' => (
24             is => 'ro',
25             lazy => 1,
26             builder => sub {
27 1     1   405 my ($self) = @_;
28              
29 1         3 my @scrambler = @{ $self->scrambler };
  1         23  
30 1         10 my @unscrambler = ();
31              
32 1         4 for ( 0 .. 7 ) {
33 8         14 $unscrambler[ $scrambler[$_] ] = $_;
34             }
35              
36 1         6 return \@unscrambler;
37             },
38             );
39              
40             has 'bit_mask' => (
41             is => 'ro',
42             default => sub { int rand $MAX_NUMBER },
43             );
44              
45             sub encode {
46 3     3 1 2099 my ( $self, $number ) = @_;
47              
48 3         5 my @slice = @{ $self->scrambler };
  3         53  
49 3         477 my @nibbles = nibble_split($number);
50 3         10 my $scrambled = nibble_join( @nibbles[@slice] );
51 3         10 my $encoded = $scrambled ^ $self->bit_mask;
52              
53 3         9 return $encoded;
54             }
55              
56             sub decode {
57 3     3 1 1201 my ( $self, $encoded ) = @_;
58              
59 3         5 my @slice = @{ $self->unscrambler };
  3         52  
60 3         24 my $number = $encoded ^ $self->bit_mask;
61 3         5 my @nibbles = nibble_split($number);
62 3         9 my $decoded = nibble_join( @nibbles[@slice] );
63              
64 3         10 return $decoded;
65             }
66              
67             sub nibble_split {
68 7     7 1 18 my ($number) = @_;
69              
70 7         8 my @nibbles;
71 7         14 for ( 0 .. 7 ) {
72 56         90 $nibbles[$_] = ( $number >> ( $_ * 4 ) ) & 0x0000000f;
73             }
74              
75 7         27 return @nibbles;
76             }
77              
78             sub nibble_join {
79 7     7 1 734 my (@nibbles) = @_;
80              
81 7         10 my $number = 0;
82 7         12 for ( 0 .. 7 ) {
83 56         83 $number = $number | ( $nibbles[$_] << ( $_ * 4 ) );
84             }
85              
86 7         17 return $number;
87             }
88              
89             1;
90              
91             # ABSTRACT: Scramble nibbles of a 32-bit integer
92              
93             __END__