File Coverage

blib/lib/Sys/Export/Extent.pm
Criterion Covered Total %
statement 97 98 98.9
branch 33 42 78.5
condition 22 34 64.7
subroutine 17 17 100.0
pod 9 9 100.0
total 178 200 89.0


line stmt bran cond sub pod time code
1             package Sys::Export::Extent;
2              
3             our $VERSION = '0.005'; # VERSION
4             # ABSTRACT: Represents a range of bytes and data that needs written there
5              
6 3     3   1340 use v5.26;
  3         8  
7 3     3   12 use warnings;
  3         3  
  3         131  
8 3     3   45 use experimental qw( signatures );
  3         4  
  3         16  
9 3     3   340 use Scalar::Util qw( blessed );
  3         15  
  3         195  
10 3     3   16 use Sys::Export qw( round_up_to_multiple :isa );
  3         5  
  3         42  
11 3     3   14 use Carp;
  3         5  
  3         2870  
12              
13              
14 44     44 1 65 sub new($class, %attrs) {
  44         41  
  44         87  
  44         42  
15 44         94 my $self= bless { name => delete $attrs{name} }, $class;
16             # Some fields need to be initialized in a specific order:
17 44 100       121 $self->block_size(delete $attrs{block_size}) if defined $attrs{block_size};
18 44 100       72 $self->size(delete $attrs{size}) if defined $attrs{size};
19 44 100       61 $self->data(delete $attrs{data}) if defined $attrs{data};
20 44 100       68 $self->device_offset(delete $attrs{device_offset}) if defined $attrs{device_offset};
21 44 100       68 $self->start_lba(delete $attrs{start_lba}) if defined $attrs{start_lba};
22             # The rest have no interdependencies
23 44         71 for (keys %attrs) {
24 24 50       76 my $m= $self->can($_) or croak "Unknown attribute '$_'";
25 24         66 $m->($self, $attrs{$_});
26             }
27 44         229 $self;
28             }
29              
30              
31 5     5 1 9 sub coerce($class, $x) {
  5         9  
  5         6  
  5         6  
32 5 50 33     18 return $x if blessed($x) && $x->isa($class);
33 5 50       11 return $class->new(%$x) if isa_hash $x;
34 0         0 croak "Don't know how to coerce $x into $class";
35             }
36              
37              
38 109   50 109 1 99 sub name($self) { $self->{name} // 'extent' }
  109         100  
  109         94  
  109         333  
39              
40 274     274 1 255 sub block_size($self, @v) {
  274         241  
  274         242  
  274         231  
41 274 100       344 if (@v) {
42 40 50       85 croak "block_size $v[0] not a power of 2" unless isa_pow2 $v[0];
43 40         78 $self->{block_size}= $v[0];
44             }
45 274   100     778 $self->{block_size} // 512;
46             }
47              
48              
49 328     328 1 881 sub size($self, @v) {
  328         307  
  328         306  
  328         279  
50 328 100       447 if (@v) {
51             croak "Attempt to change ector length of ".$self->name." after choosing LBA"
52             if ($self->{size} // 0) > 0 && ($self->device_offset // -1) >= 0
53 67 50 100     171 && round_up_to_multiple($v[0], $self->block_size) != round_up_to_multiple($self->{size}, $self->block_size);
      50        
      66        
      66        
54 67         77 $self->{size}= $v[0];
55             }
56             $self->{size}
57 328         769 }
58              
59              
60 405     405 1 1308 sub device_offset($self, @v) {
  405         383  
  405         379  
  405         350  
61 405 100       501 if (@v) {
62 48 50 100     139 croak "device_offset $v[0] not a multiple of ".$self->block_size
      66        
63             if ($v[0]//0) > 0 && ($v[0] & ($self->block_size-1));
64 48         87 $self->{device_offset}= $v[0];
65             }
66             $self->{device_offset}
67 405         689 }
68              
69              
70 143     143 1 2579 sub start_lba($self, @v) {
  143         159  
  143         131  
  143         182  
71 143 100       201 if (@v) {
72 1   33     29 $self->device_offset($v[0] && ($v[0] * $self->block_size));
73             }
74 143         194 my $ofs= $self->device_offset;
75 3     3   1282 use integer;
  3         37  
  3         13  
76 143 100 100     404 return defined $ofs && $ofs >= 0? ($ofs / $self->block_size) : undef;
77             }
78              
79             *lba= *start_lba;
80              
81 37     37 1 167 sub end_lba($self, @v) {
  37         40  
  37         34  
  37         33  
82 37 100       47 if (@v) {
83 1         4 my $lba= $self->start_lba;
84 1 50       13 croak "Can't set end_lba until start_lba is defined"
85             unless defined $lba;
86             # Using 'size' accessor would trigger the check for altering the size after setting
87             # device offset, which is less likely to be a useful safeguard when someone is setting
88             # start_lba/end_lba.
89 1         3 $self->{size}= ($v[0] + 1 - $lba) * $self->block_size;
90             }
91 37         45 my ($ofs, $size)= ($self->device_offset, $self->size);
92 3     3   584 use integer;
  3         7  
  3         10  
93 37 50 33     122 return ($ofs//-1) < 0 || !$size ? undef : ($ofs + $size - 1) / $self->block_size;
94             }
95              
96              
97 142     142 1 130 sub data($self, @v) {
  142         135  
  142         140  
  142         122  
98 142 100       180 if (@v) {
99 64 50 66     126 croak "data must be a scalar-ref or LazyFileData object"
100             if defined $v[0] && !isa_data_ref $v[0];
101 64         94 $self->{data}= $v[0];
102             }
103             $self->{data}
104 142         394 }
105              
106             # Avoiding dependency on namespace::clean
107             delete @{Sys::Export::Extent::}{qw(
108             carp croak confess blessed isa_array isa_data_ref isa_export_dst isa_exporter isa_group
109             isa_handle isa_hash isa_int isa_pow2 isa_user isa_userdb round_up_to_multiple
110             )};
111             1;
112              
113             __END__