File Coverage

blib/lib/Router/Pygmy/Route.pm
Criterion Covered Total %
statement 46 47 97.8
branch 12 14 85.7
condition 4 6 66.6
subroutine 11 11 100.0
pod 0 8 0.0
total 73 86 84.8


line stmt bran cond sub pod time code
1             package Router::Pygmy::Route;
2             $Router::Pygmy::Route::VERSION = '0.04';
3 1     1   6 use strict;
  1         3  
  1         39  
4 1     1   7 use warnings;
  1         1  
  1         31  
5              
6             # ABSTRACT: simple route object
7              
8 1     1   5 use Carp;
  1         2  
  1         768  
9             our @CARP_NOT = qw(Router::Pygmy);
10              
11 10     10 0 151 sub spec { shift()->{spec}; }
12              
13 15     15 0 72 sub arg_names { shift()->{arg_names}; }
14              
15 5     5 0 19 sub arg_idxs { shift()->{arg_idxs}; }
16              
17 24     24 0 87 sub parts { shift()->{parts}; }
18              
19             sub new {
20 11     11 0 32 my ($class, %fields) = @_;
21 11         42 return bless(\%fields, $class);
22             }
23              
24             sub parse {
25 11     11 0 12 my ( $class, $spec ) = @_;
26              
27 11         12 my ( @arg_names, @arg_idxs, @parts );
28 11         22 my $i = 0;
29 11         31 for my $part ( grep { $_ } split m{/}, $spec ) {
  33         44  
30 33         63 my $is_arg = $part =~ s/^://;
31 33 100       40 if ($is_arg) {
32 16         17 push @parts, undef;
33 16         16 push @arg_idxs, $i;
34 16         17 push @arg_names, $part;
35             }
36             else {
37 17         29 push @parts, $part;
38             }
39 33         41 $i++;
40             }
41 11         30 return $class->new(
42             spec => $spec,
43             parts => \@parts,
44             arg_names => \@arg_names,
45             arg_idxs => \@arg_idxs,
46             );
47             }
48              
49             sub path_for {
50 13     13 0 18 my $this = shift;
51              
52 13         13 my @parts = @{ $this->parts };
  13         32  
53 13         37 @parts[ @{ $this->arg_idxs } ] = $this->args_for(@_);
  5         13  
54 5         40 return join '/', @parts;
55             }
56              
57             sub args_for {
58 13     13 0 14 my $this = shift;
59 13 100 33     91 my $args
    50          
60             = !@_ || !defined $_[0] ? []
61             : !ref $_[0] ? [ shift() ]
62             : shift();
63              
64 13         27 my $arg_names = $this->arg_names;
65              
66 13 100       46 if ( ref $args eq 'ARRAY' ) {
    50          
67              
68             # positional args
69 7 100       26 @$args == @$arg_names
70             or croak sprintf
71             "Invalid arg count for route '%s', got %d args, expected %d",
72             $this->spec, scalar @$args, scalar @$arg_names;
73 3         10 return @$args;
74             }
75             elsif ( ref $args eq 'HASH' ) {
76              
77             # named args
78 4         26 keys %$args == @$arg_names
79 7         26 && not( grep { !exists $args->{$_}; } @$arg_names )
80             or croak sprintf
81             "Invalid args for route '%s', got (%s) expected (%s)",
82             $this->spec,
83 3         10 join( ', ', map {"'$_'"} sort { $a cmp $b } keys %$args ),
  6         86  
84 6 100 100     34 join( ', ', map {"'$_'"} @$arg_names );
85              
86 2         8 return @$args{@$arg_names};
87             }
88             else {
89 0           croak sprintf "Invalid args for route '%s' (%s)", $this->spec, $args;
90             }
91             }
92              
93             1;
94              
95             # vim: expandtab:shiftwidth=4:tabstop=4:softtabstop=0:textwidth=78:
96              
97             __END__