File Coverage

blib/lib/Path/Dispatcher/Rule/Sequence.pm
Criterion Covered Total %
statement 50 50 100.0
branch 11 12 91.6
condition 6 6 100.0
subroutine 9 9 100.0
pod 0 3 0.0
total 76 80 95.0


line stmt bran cond sub pod time code
1             package Path::Dispatcher::Rule::Sequence;
2             # ABSTRACT: a sequence of rules
3              
4             our $VERSION = '1.08';
5              
6 31     31   223 use Moo;
  31         87  
  31         198  
7 31     31   11709 use MooX::TypeTiny;
  31         78  
  31         187  
8 31     31   22743 use Types::Standard qw(Str);
  31         80  
  31         212  
9              
10             extends 'Path::Dispatcher::Rule';
11             with 'Path::Dispatcher::Role::Rules';
12              
13             has delimiter => (
14             is => 'ro',
15             isa => Str,
16             default => ' ',
17             );
18              
19             sub _match_as_far_as_possible {
20 80     80   122 my $self = shift;
21 80         124 my $path = shift;
22              
23 80         214 my @tokens = $self->tokenize($path->path);
24 80         253 my @rules = $self->rules;
25 80         127 my @matched;
26              
27 80   100     346 while (@tokens && @rules) {
28 152         256 my $rule = $rules[0];
29 152         238 my $token = $tokens[0];
30              
31 152 100       401 last unless $rule->match($path->clone_path($token));
32              
33 112         497 push @matched, $token;
34 112         189 shift @rules;
35 112         422 shift @tokens;
36             }
37              
38 80         325 return (\@matched, \@tokens, \@rules);
39             }
40              
41             sub _match {
42 48     48   86 my $self = shift;
43 48         67 my $path = shift;
44              
45 48         225 my ($matched, $tokens, $rules) = $self->_match_as_far_as_possible($path);
46              
47 48 100       149 return if @$rules; # didn't provide everything necessary
48 26 100 100     83 return if @$tokens && !$self->prefix; # had tokens left over
49              
50 24         60 my $leftover = $self->untokenize(@$tokens);
51             return {
52 24         102 leftover => $leftover,
53             positional_captures => $matched,
54             };
55             }
56              
57             sub complete {
58 32     32 0 58 my $self = shift;
59 32         43 my $path = shift;
60              
61 32         80 my ($matched, $tokens, $rules) = $self->_match_as_far_as_possible($path);
62 32 50       77 return if @$tokens > 1; # had tokens leftover
63 32 100       78 return if !@$rules; # consumed all rules
64              
65 30         52 my $rule = shift @$rules;
66 30 100       68 my $token = @$tokens ? shift @$tokens : '';
67              
68 30         76 return map { $self->untokenize(@$matched, $_) }
  40         95  
69             $rule->complete($path->clone_path($token));
70             }
71              
72             sub tokenize {
73 80     80 0 114 my $self = shift;
74 80         123 my $path = shift;
75 80         1014 return grep { length } split $self->delimiter, $path;
  196         539  
76             }
77              
78             sub untokenize {
79 64     64 0 103 my $self = shift;
80 64         133 my @tokens = @_;
81             return join $self->delimiter,
82 88         321 grep { length }
83 64         175 map { split $self->delimiter, $_ }
  88         681  
84             @tokens;
85             }
86              
87             __PACKAGE__->meta->make_immutable;
88 31     31   31183 no Moo;
  31         73  
  31         155  
89              
90             1;
91              
92             __END__
93              
94             =pod
95              
96             =encoding UTF-8
97              
98             =head1 NAME
99              
100             Path::Dispatcher::Rule::Sequence - a sequence of rules
101              
102             =head1 VERSION
103              
104             version 1.08
105              
106             =head1 SYNOPSIS
107              
108             =head1 DESCRIPTION
109              
110             This is basically a more robust and flexible version of
111             L<Path::Dispatcher::Rule::Tokens>.
112              
113             Instead of a mish-mash of strings, regexes, and array references,
114             a Sequence rule has just a list of other rules.
115              
116             =head1 ATTRIBUTES
117              
118             =head2 rules
119              
120             =head2 delimiter
121              
122             =head1 SUPPORT
123              
124             Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Path-Dispatcher>
125             (or L<bug-Path-Dispatcher@rt.cpan.org|mailto:bug-Path-Dispatcher@rt.cpan.org>).
126              
127             =head1 AUTHOR
128              
129             Shawn M Moore, C<< <sartak at bestpractical.com> >>
130              
131             =head1 COPYRIGHT AND LICENSE
132              
133             This software is copyright (c) 2020 by Shawn M Moore.
134              
135             This is free software; you can redistribute it and/or modify it under
136             the same terms as the Perl 5 programming language system itself.
137              
138             =cut