File Coverage

lib/Archive/CAR/v2.pm
Criterion Covered Total %
statement 14 14 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 19 19 100.0


line stmt bran cond sub pod time code
1 2     2   28 use v5.40;
  2         7  
2 2     2   12 use feature 'class';
  2         4  
  2         271  
3 2     2   13 no warnings 'experimental::class';
  2         3  
  2         112  
4 2     2   11 use Archive::CAR::v1;
  2         3  
  2         205  
5             #
6             class Archive::CAR::v2 v0.0.4 : isa(Archive::CAR::v1) {
7 2     2   12 use Archive::CAR::Utils qw[systell];
  2         4  
  2         2233  
8             #
9             field $v2_header : reader;
10             field $index : reader;
11             #
12             method version () {2}
13             method to_file ($filename) { Archive::CAR->write( $filename, $self->roots, $self->blocks, 2 ) }
14              
15             method read ($fh) {
16              
17             # Pragma (11 bytes)
18             my $pragma;
19             read( $fh, $pragma, 11 );
20              
21             # Header (40 bytes)
22             my $header_raw;
23             read( $fh, $header_raw, 40 );
24             my ( $char_raw, $data_offset, $data_size, $index_offset ) = unpack( 'a16 Q< Q< Q<', $header_raw );
25             $v2_header = { characteristics => $char_raw, data_offset => $data_offset, data_size => $data_size, index_offset => $index_offset, };
26              
27             # Read Index if exists
28             if ( $index_offset > 0 ) {
29             seek( $fh, $index_offset, 0 );
30             $index = '';
31             while ( read( $fh, my $buf, 8192 ) ) {
32             $index .= $buf;
33             }
34             }
35              
36             # Read CAR v1 data
37             seek( $fh, $data_offset, 0 );
38             $self->SUPER::read( $fh, $data_size );
39             return $self;
40             }
41              
42             method write ( $fh, $roots, $blocks ) {
43              
44             # Pragma
45             my $pragma = pack( 'H*', '0aa16776657273696f6e02' );
46             print {$fh} $pragma;
47              
48             # Header Placeholder (40 bytes)
49             my $header_pos = systell($fh);
50             print {$fh} pack( 'a40', '' );
51              
52             # Write CAR v1 data
53             my $data_offset = systell($fh);
54             $self->SUPER::write( $fh, $roots, $blocks );
55             my $data_size = systell($fh) - $data_offset;
56              
57             # Index
58             my $index_offset = systell($fh);
59             require Archive::CAR::Indexer;
60             my $indexer = Archive::CAR::Indexer->new();
61             my $index_data = $indexer->generate_index( $self->blocks );
62             print {$fh} $index_data;
63              
64             # Backfill Header
65             my $current_pos = systell($fh);
66             seek( $fh, $header_pos, 0 );
67              
68             # characteristics (16 bytes), data_offset (8), data_size (8), index_offset (8)
69             my $header_raw = pack( 'a16 Q< Q< Q<', "\0" x 16, $data_offset, $data_size, $index_offset );
70             print {$fh} $header_raw;
71             seek( $fh, $current_pos, 0 );
72             }
73              
74             # Override header to include v2 fields and v1 roots as expected in some outputs
75             method header () {
76             my $v1_header = $self->SUPER::header;
77             return { %$v2_header, roots => $v1_header->{roots}, version => 2, };
78             }
79             };
80             #
81             1;