File Coverage

blib/lib/MouseX/NativeTraits/MethodProvider/ArrayRef.pm
Criterion Covered Total %
statement 299 328 91.1
branch 87 104 83.6
condition 6 12 50.0
subroutine 69 69 100.0
pod 29 29 100.0
total 490 542 90.4


line stmt bran cond sub pod time code
1             package MouseX::NativeTraits::MethodProvider::ArrayRef;
2 9     9   8115 use Mouse;
  9         19  
  9         69  
3 9     9   2898 use Mouse::Util::TypeConstraints ();
  9         17  
  9         166  
4              
5 9     9   52 use List::Util ();
  9         13  
  9         49226  
6              
7             extends qw(MouseX::NativeTraits::MethodProvider);
8              
9             sub generate_count {
10 6     6 1 119 my($self) = @_;
11 6         17 my $reader = $self->reader;
12             return sub {
13 23 100   23   5903 if(@_ != 1) {
14 10         102 $self->argument_error('count', 1, 1, scalar @_);
15             }
16 13         22 return scalar @{ $reader->( $_[0] ) };
  13         105  
17 6         38 };
18             }
19              
20             sub generate_is_empty {
21 6     6 1 109 my($self) = @_;
22 6         24 my $reader = $self->reader;
23             return sub {
24 42 100   42   120495 if(@_ != 1) {
        134      
25 10         175 $self->argument_error('is_empty', 1, 1, scalar @_);
26             }
27 32         49 return scalar(@{ $reader->( $_[0] ) }) == 0;
  32         303  
28 6         66 };
29             }
30              
31             sub generate_first {
32 10     50 1 157 my($self) = @_;
33 10         28 my $reader = $self->reader;
34             return sub {
35 60     100   57218 my ( $instance, $block ) = @_;
36              
37 60 100       202 if(@_ != 2) {
38 30         130 $self->argument_error('first', 2, 2, scalar @_);
39             }
40              
41 30 100       156 Mouse::Util::TypeConstraints::CodeRef($block)
42             or $instance->meta->throw_error(
43             "The argument passed to first must be a code reference");
44              
45 20         32 return List::Util::first(\&{$block}, @{ $reader->($instance) });
  20         44  
  20         167  
46 10         67 };
47             }
48              
49             sub generate_any {
50 1     101 1 23 my($self) = @_;
51 1         4 my $reader = $self->reader;
52             return sub {
53 1     101   613 my ( $instance, $block ) = @_;
        39      
54              
55 1 50       5 if(@_ != 2) {
56 0         0 $self->argument_error('any', 2, 2, scalar @_);
57             }
58              
59 1 50       6 Mouse::Util::TypeConstraints::CodeRef($block)
60             or $instance->meta->throw_error(
61             "The argument passed to any must be a code reference");
62              
63 1         2 foreach (@{ $reader->($instance) }){
  1         5  
64 3 100       16 if($block->($_)){
65 1         11 return 1;
66             }
67             }
68 0         0 return 0;
69 1         12 };
70             }
71              
72             sub generate_apply {
73 1     101 1 22 my($self) = @_;
74 1         3 my $reader = $self->reader;
75             return sub {
76 1     61   502 my ( $instance, $block ) = @_;
        18      
77              
78 1 50       6 if(@_ != 2) {
79 0         0 $self->argument_error('apply', 2, 2, scalar @_);
80             }
81              
82 1 50       5 Mouse::Util::TypeConstraints::CodeRef($block)
83             or $instance->meta->throw_error(
84             "The argument passed to apply must be a code reference");
85              
86 1         3 my @values = @{ $reader->($instance) };
  1         43  
87 1         3 foreach (@values){
88 3         12 $block->();
89             }
90 1         9 return @values;
91 1         8 };
92             }
93              
94             sub generate_map {
95 11     72 1 180 my($self) = @_;
96 11         28 my $reader = $self->reader;
97             return sub {
98 62     62   41373 my ( $instance, $block ) = @_;
        17      
99              
100 62 100       208 if(@_ != 2) {
101 30         123 $self->argument_error('map', 2, 2, scalar @_);
102             }
103              
104 32 100       132 Mouse::Util::TypeConstraints::CodeRef($block)
105             or $instance->meta->throw_error(
106             "The argument passed to map must be a code reference");
107              
108 22         35 return map { $block->() } @{ $reader->($instance) };
  106         376  
  22         74  
109 11         1493 };
110             }
111              
112             sub generate_reduce {
113 10     72 1 180 my($self) = @_;
114 10         54 my $reader = $self->reader;
115             return sub {
116 60     120   68245 my ( $instance, $block ) = @_;
117              
118 60 100       210 if(@_ != 2) {
119 30         151 $self->argument_error('reduce', 2, 2, scalar @_);
120             }
121              
122 30 100       169 Mouse::Util::TypeConstraints::CodeRef($block)
123             or $instance->meta->throw_error(
124             "The argument passed to reduce must be a code reference");
125              
126 20         38 our ($a, $b);
127 20         95 return List::Util::reduce { $block->($a, $b) } @{ $reader->($instance) };
  80         467  
  20         195  
128 10         170 };
129             }
130              
131             sub generate_sort {
132 10     130 1 149 my($self) = @_;
133 10         28 my $reader = $self->reader;
134             return sub {
135 40     160   21129 my ( $instance, $block ) = @_;
136              
137 40 100 66     250 if(@_ < 1 or @_ > 2) {
138 10         69 $self->argument_error('sort', 1, 2, scalar @_);
139             }
140              
141 30 100       71 if (defined $block) {
142 20 100       114 Mouse::Util::TypeConstraints::CodeRef($block)
143             or $instance->meta->throw_error(
144             "The argument passed to sort must be a code reference");
145              
146 10         21 return sort { $block->( $a, $b ) } @{ $reader->($instance) };
  90         288  
  10         80  
147             }
148             else {
149 10         18 return sort @{ $reader->($instance) };
  10         150  
150             }
151 10         89 };
152             }
153              
154             sub generate_sort_in_place {
155 10     170 1 163 my($self) = @_;
156 10         29 my $reader = $self->reader;
157              
158             return sub {
159 60     160   52814 my ( $instance, $block ) = @_;
160              
161 60 100 66     888 if(@_ < 1 or @_ > 2) {
162 20         193 $self->argument_error('sort_in_place', 1, 2, scalar @_);
163             }
164              
165 40         100 my $array_ref = $reader->($instance);
166              
167 40 100       89 if(defined $block){
168 30 100       135 Mouse::Util::TypeConstraints::CodeRef($block)
169             or $instance->meta->throw_error(
170             "The argument passed to sort_in_place must be a code reference");
171 20         37 @{$array_ref} = sort { $block->($a, $b) } @{$array_ref};
  20         267  
  140         472  
  20         449  
172             }
173             else{
174 10         16 @{$array_ref} = sort @{$array_ref};
  10         45  
  10         61  
175             }
176              
177 30         86 return $instance;
178 10         70 };
179             }
180              
181              
182             # The sort_by algorithm comes from perlfunc/sort
183             # See also perldoc -f sort and perldoc -q sort
184              
185             sub generate_sort_by {
186 1     161 1 32 my($self) = @_;
187 1         20 my $reader = $self->reader;
188             return sub {
189 1     181   3 my ( $instance, $block, $compare ) = @_;
190              
191 1 50 33     10 if(@_ < 1 or @_ > 3) {
192 0         0 $self->argument_error('sort_by', 1, 3, scalar @_);
193             }
194              
195 1         5 my $array_ref = $reader->($instance);
196 1         2 my @idx;
197 1         2 foreach (@{$array_ref}){ # intentinal use of $_
  1         4  
198 3         43 push @idx, scalar $block->($_);
199             }
200              
201             # NOTE: scalar(@idx)-1 is faster than $#idx
202 1 50       7 if($compare){
203 1         7 return @{ $array_ref }[
  2         9  
204 1         16 sort { $compare->($idx[$a], $idx[$b]) }
205             0 .. scalar(@idx)-1
206             ];
207             }
208             else{
209 0         0 return @{ $array_ref }[
  0         0  
210 0         0 sort { $idx[$a] cmp $idx[$b] }
211             0 .. scalar(@idx)-1
212             ];
213             }
214 1         47 };
215             }
216              
217              
218             sub generate_sort_in_place_by {
219 1     102 1 25 my($self) = @_;
220 1         4 my $reader = $self->reader;
221              
222             return sub {
223 1     61   566 my ( $instance, $block, $compare ) = @_;
224              
225 1 50 33     11 if(@_ < 1 or @_ > 3) {
226 0         0 $self->argument_error('sort_by', 1, 3, scalar @_);
227             }
228              
229 1         5 my $array_ref = $reader->($instance);
230 1         2 my @idx;
231 1         2 foreach (@{$array_ref}){
  1         3  
232 3         12 push @idx, scalar $block->($_);
233             }
234              
235 1 50       7 if($compare){
236 1         4 @{ $array_ref } = @{ $array_ref }[
  1         6  
  2         8  
237 1         5 sort { $compare->($idx[$a], $idx[$b]) }
238             0 .. scalar(@idx)-1
239             ];
240             }
241             else{
242 0         0 @{ $array_ref } = @{ $array_ref }[
  0         0  
  0         0  
243 0         0 sort { $idx[$a] cmp $idx[$b] }
244             0 .. scalar(@idx)-1
245             ];
246             }
247 1         3 return $instance;
248 1         14 };
249             }
250              
251              
252             sub generate_shuffle {
253 5     66 1 83 my($self) = @_;
254 5         23 my $reader = $self->reader;
255             return sub {
256 20     20   18459 my ( $instance ) = @_;
257              
258 20 100       80 if(@_ != 1) {
259 10         57 $self->argument_error('shuffle', 1, 1, scalar @_);
260             }
261              
262 10         19 return List::Util::shuffle @{ $reader->($instance) };
  10         265  
263 5         37 };
264             }
265              
266             sub generate_grep {
267 10     30 1 278 my($self) = @_;
268 10         32 my $reader = $self->reader;
269             return sub {
270 70     90   54112 my ( $instance, $block ) = @_;
271              
272 70 100       203 if(@_ != 2) {
273 30         127 $self->argument_error('grep', 2, 2, scalar @_);
274             }
275              
276 40 100       170 Mouse::Util::TypeConstraints::CodeRef($block)
277             or $instance->meta->throw_error(
278             "The argument passed to grep must be a code reference");
279              
280 30         43 return grep { $block->() } @{ $reader->($instance) };
  240         863  
  30         99  
281 10         62 };
282             }
283              
284             sub generate_uniq {
285 5     95 1 111 my($self) = @_;
286 5         15 my $reader = $self->reader;
287             return sub {
288 20     110   13016 my ( $instance ) = @_;
289              
290 20 100       77 if(@_ != 1) {
291 10         53 $self->argument_error('uniq', 1, 1, scalar @_);
292             }
293              
294 10         20 my %seen;
295             my $seen_undef;
296 110 50       473 return grep{
297 10         40 ( defined($_)
298             ? ++$seen{$_}
299             : ++$seen_undef
300             ) == 1
301 10         23 } @{ $reader->($instance) };
302 5         46 };
303             }
304              
305             sub generate_elements {
306 5     115 1 86 my($self) = @_;
307 5         23 my $reader = $self->reader;
308             return sub {
309 22     112   25642 my ($instance) = @_;
310              
311 22 100       91 if(@_ != 1) {
312 10         59 $self->argument_error('elements', 1, 1, scalar @_);
313             }
314              
315 12         18 return @{ $reader->($instance) };
  12         198  
316 5         31 };
317             }
318              
319             sub generate_join {
320 10     122 1 153 my($self) = @_;
321 10         26 my $reader = $self->reader;
322             return sub {
323 50     92   43965 my ( $instance, $separator ) = @_;
324              
325 50 100       184 if(@_ != 2) {
326 20         96 $self->argument_error('join', 2, 2, scalar @_);
327             }
328              
329 30 100       173 Mouse::Util::TypeConstraints::Str($separator)
330             or $instance->meta->throw_error(
331             "The argument passed to join must be a string");
332              
333 20         30 return join $separator, @{ $reader->($instance) };
  20         161  
334 10         62 };
335             }
336              
337             sub generate_push {
338 21     113 1 419 my($self) = @_;
339 21         99 my $reader = $self->reader;
340 21         429 my $writer = $self->writer;
341              
342             return sub {
343 53     125   39410 my($instance, @values) = @_;
        39      
        39      
344              
345 53         77 my @new_values = @{ $reader->($instance) };
  53         223  
346 49         171 push @new_values, @values;
347 49         287 $writer->($instance, \@new_values); # commit
348 43         364 return scalar @new_values;
349 21         442 };
350             }
351              
352             sub generate_pop {
353 6     113 1 104 my($self) = @_;
354 6         24 my $reader = $self->reader;
355             return sub {
356 23 100   105   4307 if(@_ != 1) {
        39      
357 10         59 $self->argument_error('pop', 1, 1, scalar @_);
358             }
359 13         24 return pop @{ $reader->( $_[0] ) };
  13         79  
360 6         65 };
361             }
362              
363             sub generate_unshift {
364 10     115 1 167 my($self) = @_;
365 10         32 my $reader = $self->reader;
366 10         77 my $writer = $self->writer;
367              
368             return sub {
369 22     74   22744 my($instance, @values) = @_;
370              
371 22         41 my @new_values = @{ $reader->($instance) };
  22         177  
372 22         66 unshift @new_values, @values;
373 22         129 $writer->($instance, \@new_values); # commit
374 22         151 return scalar @new_values;
375 10         176 };
376             }
377              
378             sub generate_shift {
379 5     79 1 83 my($self) = @_;
380 5         24 my $reader = $self->reader;
381              
382             return sub {
383 20 100   62   24379 if(@_ != 1) {
384 10         56 $self->argument_error('shift', 1, 1, scalar @_);
385             }
386              
387 10         19 return shift @{ $reader->( $_[0] ) };
  10         76  
388 5         32 };
389             }
390              
391             __PACKAGE__->meta->add_method(generate_get => \&generate_fetch); # alias
392             sub generate_fetch {
393 14     76 1 238 my($self, $handle_name) = @_;
394 14         67 my $reader = $self->reader;
395              
396             return sub {
397 155     197   92838 my($instance, $idx) = @_;
398              
399 155 100       755 if(@_ != 2) {
400 20         101 $self->argument_error('get', 2, 2, scalar @_);
401             }
402              
403 135 100       967 Mouse::Util::TypeConstraints::Int($idx)
404             or $instance->meta->throw_error(
405             "The index passed to get must be an integer");
406              
407 105         606 return $reader->( $instance )->[ $idx ];
408 14         169 };
409             }
410              
411             __PACKAGE__->meta->add_method(generate_set => \&generate_store); # alias
412             sub generate_store {
413 16     210 1 286 my($self) = @_;
414 16         52 my $reader = $self->reader;
415 16         39 my $writer = $self->writer;
416              
417             return sub {
418 71     243   24939 my($instance, $idx, $value) = @_;
419            
420 71 100       228 if(@_ != 3) {
421 30         129 $self->argument_error('set', 3, 3, scalar @_);
422             }
423              
424 41 50       176 Mouse::Util::TypeConstraints::Int($idx)
425             or $instance->meta->throw_error(
426             "The index argument passed to set must be an integer");
427              
428 41         67 my @new_values = @{ $reader->($instance) };
  41         182  
429 41         83 $new_values[$idx] = $value;
430 41         290 $writer->($instance, \@new_values); # commit
431 41         276 return $value;
432 16         124 };
433             }
434              
435             sub generate_accessor {
436 17     257 1 259 my($self) = @_;
437 17         72 my $reader = $self->reader;
438 17         40 my $writer = $self->writer;
439              
440             return sub {
441 94     314   29389 my($instance, $idx, $value) = @_;
442              
443              
444 94 100       321 if ( @_ == 2 ) { # reader
    100          
445 22 50       96 Mouse::Util::TypeConstraints::Int($idx)
446             or $instance->meta->throw_error(
447             "The index argument passed to accessor must be an integer");
448              
449 22         144 return $reader->($instance)->[ $idx ];
450             }
451             elsif ( @_ == 3) { # writer
452 32 50       124 Mouse::Util::TypeConstraints::Int($idx)
453             or $instance->meta->throw_error(
454             "The index argument passed to accessor must be an integer");
455              
456 32         42 my @new_values = @{ $reader->($instance) };
  32         132  
457 31         67 $new_values[$idx] = $value;
458 31         201 $writer->($instance, \@new_values); # commit
459 31         229 return $value;
460             }
461             else {
462 40         173 $self->argument_error('accessor', 2, 3, scalar @_);
463             }
464 17         223 };
465             }
466              
467             sub generate_clear {
468 5     319 1 91 my($self) = @_;
469 5         17 my $reader = $self->reader;
470              
471             return sub {
472 30     194   30572 my($instance) = @_;
473            
474 30 100       109 if(@_ != 1) {
475 10         49 $self->argument_error('clear', 1, 1, scalar @_);
476             }
477              
478 20         41 @{ $reader->( $instance ) } = ();
  20         91  
479 20         49 return $instance;
480 5         37 };
481             }
482              
483             __PACKAGE__->meta->add_method(generate_delete => \&generate_remove); # alias
484             sub generate_remove {
485 10     200 1 143 my($self) = @_;
486 10         24 my $reader = $self->reader;
487              
488             return sub {
489 40     160   20572 my($instance, $idx) = @_;
490              
491 40 100       140 if(@_ != 2) {
492 20         106 $self->argument_error('delete', 2, 2, scalar @_);
493             }
494              
495 20 50       74 Mouse::Util::TypeConstraints::Int($idx)
496             or $instance->meta->throw_error(
497             "The index argument passed to delete must be an integer");
498              
499 20         26 return splice @{ $reader->( $instance ) }, $idx, 1;
  20         146  
500 10         81 };
501             }
502              
503             sub generate_insert {
504 10     170 1 151 my($self) = @_;
505 10         28 my $reader = $self->reader;
506 10         34 my $writer = $self->writer;
507              
508             return sub {
509 20     90   32493 my($instance, $idx, $value) = @_;
510              
511 20 100       84 if(@_ != 3) {
512 10         53 $self->argument_error('insert', 3, 3, scalar @_);
513             }
514              
515 10 50       50 Mouse::Util::TypeConstraints::Int($idx)
516             or $instance->meta->throw_error(
517             "The index argument passed to insert must be an integer");
518              
519 10         18 my @new_values = @{ $reader->($instance) };
  10         52  
520 10         29 splice @new_values, $idx, 0, $value;
521 10         94 $writer->($instance, \@new_values); # commit
522 10         72 return $instance;
523 10         54 };
524             }
525              
526             sub generate_splice {
527 20     110 1 289 my($self) = @_;
528 20         50 my $reader = $self->reader;
529 20         85 my $writer = $self->writer;
530              
531             return sub {
532 90     150   74550 my ( $instance, $idx, $len, @elems ) = @_;
533              
534 90 100       300 if(@_ < 2) {
535 10         60 $self->argument_error('splice', 2, undef, scalar @_);
536             }
537              
538 80 50       268 Mouse::Util::TypeConstraints::Int($idx)
539             or $instance->meta->throw_error(
540             "The index argument passed to splice must be an integer");
541              
542 80 50       927 if(defined $len) {
543 80 100       247 Mouse::Util::TypeConstraints::Int($len)
544             or $instance->meta->throw_error(
545             "The length argument passed to splice must be an integer");
546             }
547              
548 70         82 my @new_values = @{ $reader->($instance) };
  70         280  
549 70 50       297 my @ret_values = defined($len)
550             ? splice @new_values, $idx, $len, @elems
551             : splice @new_values, $idx;
552 70         518 $writer->($instance, \@new_values); # commit
553 70 100       647 return wantarray ? @ret_values : $ret_values[-1];
554 20         166 };
555             }
556              
557             sub generate_for_each {
558 0     150 1   my($self) = @_;
559 0           my $reader = $self->reader;
560              
561             return sub {
562 0     110     my ( $instance, $block ) = @_;
563              
564 0           foreach my $element(@{ $reader->instance($instance) }){
  0            
565 0           $block->($element);
566             }
567 0           return $instance;
568 0           };
569             }
570              
571             sub generate_for_each_pair {
572 0     110 1   my($self) = @_;
573 0           my $reader = $self->reader;
574              
575             return sub {
576 0     90     my ( $instance, $block ) = @_;
577              
578 0           my $array_ref = $reader->($instance);
579 0           for(my $i = 0; $i < @{$array_ref}; $i += 2){
  0            
580 0           $block->($array_ref->[$i], $array_ref->[$i + 1]);
581             }
582 0           return $instance;
583 0           };
584             }
585              
586 9     9   298 no Mouse;
  9         22  
  9         110  
587             __PACKAGE__->meta->make_immutable();
588              
589             __END__