File Coverage

blib/lib/Net/BitTorrent/Protocol/BEP03/Bencode.pm
Criterion Covered Total %
statement 47 47 100.0
branch 35 38 92.1
condition 17 18 94.4
subroutine 4 4 100.0
pod 2 2 100.0
total 105 109 96.3


line stmt bran cond sub pod time code
1             package Net::BitTorrent::Protocol::BEP03::Bencode v2.0.1 {
2 41     41   1113 use v5.40;
  41         178  
3 41     41   1375 use parent 'Exporter';
  41         878  
  41         387  
4             our %EXPORT_TAGS = ( all => [ our @EXPORT_OK = qw[bencode bdecode] ], bencode => [] );
5              
6 3167     3167 1 3597722 sub bencode ( $ref //= return ) {
  3167         5306  
  3166         4062  
7 3166 100 100     29266 return ( ( ( length $ref ) && $ref =~ m[^([-\+][1-9])?\d*$] ) ? ( 'i' . $ref . 'e' ) : ( length($ref) . ':' . $ref ) ) if !ref $ref;
    100          
8 954 100       5814 return join( '', 'l', ( map { bencode($_) } @{$ref} ), 'e' ) if ref $ref eq 'ARRAY';
  70         93  
  33         58  
9 921 100       2644 return join( '', 'd', ( map { length($_) . ':' . $_ . bencode( $ref->{$_} ) } sort { $a cmp $b } keys %{$ref} ), 'e' ) if ref $ref eq 'HASH';
  2598         6289  
  2540         5205  
  919         5029  
10 2         11 return '';
11             }
12              
13 3072     3072 1 19007 sub bdecode( $string //= return, $k //= 0 ) {
  3072         5116  
  3072         4244  
  3072         4107  
14 3072         4482 my ( $return, $leftover );
15 3072 100       24811 if ( $string =~ s[^(0+|[1-9]\d*):][] ) {
    100          
    100          
    100          
16 2335         5116 my $size = $1;
17 2335 100       5281 $return = '' if $size =~ m[^0+$];
18 2335         5497 $return .= substr( $string, 0, $size, '' );
19 2335 100       8454 return if length $return < $size;
20 2334 100       11361 return $k ? ( $return, $string ) : $return; # byte string
21             }
22             elsif ( $string =~ s[^i([-\+]?\d+)e][] ) { # integer
23 200         431 my $int = $1;
24 200 100 100     4956 $int = () if $int =~ m[^-0] || $int =~ m[^0\d+];
25 200 100       759 return $k ? ( $int, $string ) : $int;
26             }
27             elsif ( $string =~ s[^l(.*)][]s ) { # list
28 46         246 $leftover = $1;
29 46   100     180 while ( $leftover and $leftover !~ s[^e][]s ) {
30 80         156 ( my ($piece), $leftover ) = bdecode( $leftover, 1 );
31 79         561 push @$return, $piece;
32             }
33 45 100       161 return $k ? ( \@$return, $leftover ) : \@$return;
34             }
35             elsif ( $string =~ s[^d(.*)][]s ) { # dictionary
36 480         2416 $leftover = $1;
37 480         784 my $pkey;
38 480   100     3698 while ( $leftover and $leftover !~ s[^e][]s ) {
39 1378         2169 my ( $key, $value );
40 1378         3045 ( $key, $leftover ) = bdecode( $leftover, 1 );
41 1378 50       3720 ( $value, $leftover ) = bdecode( $leftover, 1 ) if $leftover;
42 1375 100 66     6719 die 'malformed dictionary' if defined $pkey && defined $key && $pkey gt $key; # BEP52
      100        
43 1372 50       4838 $return->{$key} = $value if defined $key;
44 1372 50       7525 $pkey = $key if defined $key;
45             }
46 474 100       6153 return $k ? ( \%$return, $leftover ) : \%$return;
47             }
48 11         39 return;
49             }
50             };
51             1;