| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
2
|
|
|
2
|
|
28
|
use v5.40; |
|
|
2
|
|
|
|
|
9
|
|
|
2
|
2
|
|
|
2
|
|
13
|
use feature 'class'; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
357
|
|
|
3
|
2
|
|
|
2
|
|
17
|
no warnings 'experimental::class'; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
265
|
|
|
4
|
|
|
|
|
|
|
# |
|
5
|
|
|
|
|
|
|
class Archive::CAR::v1 v0.0.3 { |
|
6
|
2
|
|
|
2
|
|
846
|
use Archive::CAR::Utils qw[systell]; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
122
|
|
|
7
|
2
|
|
|
2
|
|
1723
|
use CBOR::Free; |
|
|
2
|
|
|
|
|
15496
|
|
|
|
2
|
|
|
|
|
77
|
|
|
8
|
2
|
|
|
2
|
|
1096
|
use CBOR::Free::Decoder; |
|
|
2
|
|
|
|
|
1835
|
|
|
|
2
|
|
|
|
|
2631
|
|
|
9
|
|
|
|
|
|
|
# |
|
10
|
|
|
|
|
|
|
field $header : reader; |
|
11
|
|
|
|
|
|
|
field $roots : reader; |
|
12
|
|
|
|
|
|
|
field $blocks : reader; |
|
13
|
|
|
|
|
|
|
# |
|
14
|
|
|
|
|
|
|
method version () {1} |
|
15
|
|
|
|
|
|
|
method to_file ($filename) { Archive::CAR->write( $filename, $self->roots, $self->blocks, 1 ) } |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
method read ( $fh, $limit //= undef ) { |
|
18
|
|
|
|
|
|
|
my $data_start = systell($fh); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Header |
|
21
|
|
|
|
|
|
|
my ($header_len) = Archive::CAR::Utils::decode_varint($fh); |
|
22
|
|
|
|
|
|
|
return undef unless defined $header_len; |
|
23
|
|
|
|
|
|
|
my $header_raw; |
|
24
|
|
|
|
|
|
|
read( $fh, $header_raw, $header_len ); |
|
25
|
|
|
|
|
|
|
$header = do { |
|
26
|
|
|
|
|
|
|
local $SIG{__WARN__} = sub { |
|
27
|
8
|
50
|
|
8
|
|
97
|
warn @_ unless $_[0] =~ /Ignoring unrecognized CBOR tag #42/; |
|
28
|
|
|
|
|
|
|
}; |
|
29
|
|
|
|
|
|
|
CBOR::Free::decode($header_raw); |
|
30
|
|
|
|
|
|
|
}; |
|
31
|
|
|
|
|
|
|
if ( $header->{roots} ) { |
|
32
|
|
|
|
|
|
|
my @roots_list; |
|
33
|
|
|
|
|
|
|
for my $root_data ( @{ $header->{roots} } ) { |
|
34
|
|
|
|
|
|
|
my $raw_cid = $root_data; |
|
35
|
|
|
|
|
|
|
open my $rfh, '<', \$raw_cid; |
|
36
|
|
|
|
|
|
|
push @roots_list, Archive::CAR::Utils::decode_cid($rfh); |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
$roots = \@roots_list; |
|
39
|
|
|
|
|
|
|
} |
|
40
|
|
|
|
|
|
|
my @blocks_list; |
|
41
|
|
|
|
|
|
|
while ( !defined $limit || systell($fh) < $data_start + $limit ) { |
|
42
|
|
|
|
|
|
|
my $record_start = systell($fh); |
|
43
|
|
|
|
|
|
|
my ( $block_len, $varint_len ) = Archive::CAR::Utils::decode_varint($fh); |
|
44
|
|
|
|
|
|
|
last unless defined $block_len; |
|
45
|
|
|
|
|
|
|
my $cid = Archive::CAR::Utils::decode_cid($fh); |
|
46
|
|
|
|
|
|
|
if ( !defined $cid ) { |
|
47
|
|
|
|
|
|
|
last; |
|
48
|
|
|
|
|
|
|
} |
|
49
|
|
|
|
|
|
|
my $cid_len = length( $cid->raw ); |
|
50
|
|
|
|
|
|
|
my $data_len = $block_len - $cid_len; |
|
51
|
|
|
|
|
|
|
if ( $data_len < 0 ) { |
|
52
|
|
|
|
|
|
|
last; |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
my $data; |
|
55
|
|
|
|
|
|
|
read( $fh, $data, $data_len ); |
|
56
|
|
|
|
|
|
|
push @blocks_list, |
|
57
|
|
|
|
|
|
|
{ |
|
58
|
|
|
|
|
|
|
cid => $cid, |
|
59
|
|
|
|
|
|
|
data => $data, |
|
60
|
|
|
|
|
|
|
offset => $record_start, |
|
61
|
|
|
|
|
|
|
length => $block_len + $varint_len, |
|
62
|
|
|
|
|
|
|
blockOffset => systell($fh) - $data_len, |
|
63
|
|
|
|
|
|
|
blockLength => $data_len, |
|
64
|
|
|
|
|
|
|
}; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
$blocks = \@blocks_list; |
|
67
|
|
|
|
|
|
|
return $self; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
method write ( $fh, $roots, $blocks ) { |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# Write Header |
|
73
|
|
|
|
|
|
|
# Transform CID objects to CBOR tags for the header |
|
74
|
|
|
|
|
|
|
my @cbor_roots = map { CBOR::Free::tag( 42, $_->raw ) } @$roots; |
|
75
|
|
|
|
|
|
|
my $header_data = { version => 1, roots => \@cbor_roots, }; |
|
76
|
|
|
|
|
|
|
my $header_encoded = CBOR::Free::encode($header_data); |
|
77
|
|
|
|
|
|
|
print {$fh} Archive::CAR::Utils::encode_varint( length($header_encoded) ); |
|
78
|
|
|
|
|
|
|
print {$fh} $header_encoded; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Write Blocks |
|
81
|
|
|
|
|
|
|
for my $block (@$blocks) { |
|
82
|
|
|
|
|
|
|
my $cid_raw = $block->{cid}->raw; |
|
83
|
|
|
|
|
|
|
my $data = $block->{data}; |
|
84
|
|
|
|
|
|
|
my $block_len = length($cid_raw) + length($data); |
|
85
|
|
|
|
|
|
|
print {$fh} Archive::CAR::Utils::encode_varint($block_len); |
|
86
|
|
|
|
|
|
|
print {$fh} $cid_raw; |
|
87
|
|
|
|
|
|
|
print {$fh} $data; |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
}; |
|
91
|
|
|
|
|
|
|
# |
|
92
|
|
|
|
|
|
|
1; |