File Coverage

lib/Archive/CAR/CID.pm
Criterion Covered Total %
statement 52 57 91.2
branch 9 18 50.0
condition 2 9 22.2
subroutine 6 6 100.0
pod 2 2 100.0
total 71 92 77.1


line stmt bran cond sub pod time code
1 2     2   27 use v5.40;
  2         6  
2 2     2   12 use feature 'class';
  2         9  
  2         263  
3 2     2   11 no warnings 'experimental::class';
  2         4  
  2         210  
4             #
5             class Archive::CAR::CID v0.0.4 {
6 2     2   13 use Archive::CAR::Utils qw[systell];
  2         2  
  2         3237  
7             #
8             field $version : param : reader;
9             field $codec : param : reader;
10             field $hash : param : reader;
11             field $digest : param : reader;
12             field $raw : param : reader;
13             #
14             method to_string() {
15              
16             # Minimal string conversion for debugging/display
17             # In a real IPFS context, this uses Multibase (base32 or base58)
18             return 'b' . $self->_encode_base32($raw) if $version == 1;
19             return unpack( 'H*', $raw );
20             }
21              
22             method _encode_base32 ($data) {
23             my @alphabet = split //, 'abcdefghijklmnopqrstuvwxyz234567';
24             my $bits = '';
25             for my $byte ( unpack 'C*', $data ) {
26             $bits .= sprintf '%08b', $byte;
27             }
28             my $out = '';
29             while ( $bits =~ s/^([01]{5})// ) {
30             $out .= $alphabet[ oct "0b$1" ];
31             }
32             if ( length $bits ) {
33             $bits .= '0' x ( 5 - length $bits );
34             $out .= $alphabet[ oct "0b$bits" ];
35             }
36             return $out;
37             }
38              
39 38     38 1 322613 sub decode ( $class, $fh ) {
  38         81  
  38         46  
  38         41  
40 38         85 my $pos_before = systell($fh);
41 38         49 my $first_byte;
42 38         95 my $fb_res = read( $fh, $first_byte, 1 );
43 38 50 33     146 return undef unless defined $fb_res && $fb_res == 1;
44 38         74 my $fb = ord($first_byte);
45 38 50       80 if ( $fb == 0x00 ) { # Optional leading zero
46 0         0 $pos_before = systell($fh);
47 0         0 $fb_res = read( $fh, $first_byte, 1 );
48 0 0 0     0 return undef unless defined $fb_res && $fb_res == 1;
49 0         0 $fb = ord($first_byte);
50             }
51 38 100       72 if ( $fb == 0x12 ) { # Likely CIDv0 in binary form
52 14         19 my $second_byte;
53 14         22 read( $fh, $second_byte, 1 );
54 14 50 33     60 if ( defined $second_byte && ord($second_byte) == 0x20 ) {
55 14         19 my $digest;
56 14         28 read( $fh, $digest, 32 );
57 14         22 my $raw = chr(0x12) . chr(0x20) . $digest;
58 14         206 return $class->new( version => 0, codec => 0x70, hash => 0x12, digest => $digest, raw => $raw );
59             }
60 0         0 seek( $fh, $pos_before + 1, 0 );
61             }
62 24         175 seek( $fh, $pos_before, 0 );
63 24         56 my ($version) = Archive::CAR::Utils::decode_varint($fh);
64 24 50       51 return undef if !defined $version;
65 24         48 my ($codec) = Archive::CAR::Utils::decode_varint($fh);
66 24 50       47 return undef unless defined $codec;
67 24         46 my ($mh_type) = Archive::CAR::Utils::decode_varint($fh);
68 24 50       44 return undef unless defined $mh_type;
69 24         55 my ($mh_len) = Archive::CAR::Utils::decode_varint($fh);
70 24 50       47 return undef unless defined $mh_len;
71 24         28 my $digest;
72 24         46 read( $fh, $digest, $mh_len );
73 24         46 my $pos_after = systell($fh);
74 24         118 seek( $fh, $pos_before, 0 );
75 24         27 my $raw;
76 24         92 read( $fh, $raw, $pos_after - $pos_before );
77 24         157 seek( $fh, $pos_after, 0 );
78 24         323 return $class->new( version => $version, codec => $codec, hash => $mh_type, digest => $digest, raw => $raw );
79             }
80              
81 8     8 1 16 sub from_raw ( $class, $raw ) {
  8         12  
  8         21  
  8         10  
82 8         59 open my $fh, '<:raw', \$raw;
83 8         34 return $class->decode($fh);
84             }
85             };
86             #
87             1;