File: Sequence.pm

package info (click to toggle)
libpath-dispatcher-perl 1.08-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 512 kB
  • sloc: perl: 1,046; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 2,911 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package Path::Dispatcher::Rule::Sequence;
# ABSTRACT: a sequence of rules

our $VERSION = '1.08';

use Moo;
use MooX::TypeTiny;
use Types::Standard qw(Str);

extends 'Path::Dispatcher::Rule';
with 'Path::Dispatcher::Role::Rules';

has delimiter => (
    is      => 'ro',
    isa     => Str,
    default => ' ',
);

sub _match_as_far_as_possible {
    my $self = shift;
    my $path = shift;

    my @tokens = $self->tokenize($path->path);
    my @rules  = $self->rules;
    my @matched;

    while (@tokens && @rules) {
        my $rule  = $rules[0];
        my $token = $tokens[0];

        last unless $rule->match($path->clone_path($token));

        push @matched, $token;
        shift @rules;
        shift @tokens;
    }

    return (\@matched, \@tokens, \@rules);
}

sub _match {
    my $self = shift;
    my $path = shift;

    my ($matched, $tokens, $rules) = $self->_match_as_far_as_possible($path);

    return if @$rules; # didn't provide everything necessary
    return if @$tokens && !$self->prefix; # had tokens left over

    my $leftover = $self->untokenize(@$tokens);
    return {
        leftover            => $leftover,
        positional_captures => $matched,
    };
}

sub complete {
    my $self = shift;
    my $path = shift;

    my ($matched, $tokens, $rules) = $self->_match_as_far_as_possible($path);
    return if @$tokens > 1; # had tokens leftover
    return if !@$rules; # consumed all rules

    my $rule = shift @$rules;
    my $token = @$tokens ? shift @$tokens : '';

    return map { $self->untokenize(@$matched, $_) }
           $rule->complete($path->clone_path($token));
}

sub tokenize {
    my $self = shift;
    my $path = shift;
    return grep { length } split $self->delimiter, $path;
}

sub untokenize {
    my $self   = shift;
    my @tokens = @_;
    return join $self->delimiter,
           grep { length }
           map { split $self->delimiter, $_ }
           @tokens;
}

__PACKAGE__->meta->make_immutable;
no Moo;

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Path::Dispatcher::Rule::Sequence - a sequence of rules

=head1 VERSION

version 1.08

=head1 SYNOPSIS

=head1 DESCRIPTION

This is basically a more robust and flexible version of
L<Path::Dispatcher::Rule::Tokens>.

Instead of a mish-mash of strings, regexes, and array references,
a Sequence rule has just a list of other rules.

=head1 ATTRIBUTES

=head2 rules

=head2 delimiter

=head1 SUPPORT

Bugs may be submitted through L<the RT bug tracker|https://rt.cpan.org/Public/Dist/Display.html?Name=Path-Dispatcher>
(or L<bug-Path-Dispatcher@rt.cpan.org|mailto:bug-Path-Dispatcher@rt.cpan.org>).

=head1 AUTHOR

Shawn M Moore, C<< <sartak at bestpractical.com> >>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2020 by Shawn M Moore.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut