positional and named constraints
[gitmo/MooseX-Types-Structured.git] / lib / MooseX / Meta / TypeConstraint / Structured.pm
CommitLineData
65748864 1package MooseX::Meta::TypeConstraint::Structured;
2
3use 5.8.8; ## Minimum tested Perl Version
4use Moose;
5use Moose::Util::TypeConstraints;
6
7extends 'Moose::Meta::TypeConstraint';
8
9our $AUTHORITY = 'cpan:JJNAPIORK';
10
11=head1 NAME
12
13MooseX::Meta::TypeConstraint::Structured - Structured Type Constraints
14
15=head1 VERSION
16
170.01
18
19=cut
20
21our $VERSION = '0.01';
22
23=head1 DESCRIPTION
24
25Structured type constraints let you assign an internal pattern of type
26constraints to a 'container' constraint. The goal is to make it easier to
27declare constraints like "ArrayRef[Int, Int, Str]" where the constraint is an
28ArrayRef of three elements and the internal constraint on the three is Int, Int
29and Str.
30
31=head1 ATTRIBUTES
32
33This class defines the following attributes.
34
35=head2 parent
36
37additional details on the inherited parent attribute
38
39=head2 signature
40
41This is a signature of internal contraints for the contents of the outer
42contraint container.
43
44=cut
45
bc64165b 46subtype 'MooseX::Meta::TypeConstraint::Structured::Signature',
47 as 'HashRef[Object]',
48 where {
49 my %signature = %$_;
50 foreach my $key (keys %signature) {
51 $signature{$key}->isa('Moose::Meta::TypeConstraint');
52 } 1;
53 };
54
55coerce 'MooseX::Meta::TypeConstraint::Structured::Signature',
56 from 'ArrayRef[Object]',
57 via {
58 my @signature = @$_;
59 my %hashed_signature = map { $_ => $signature[$_] } 0..$#signature;
60 \%hashed_signature;
61 };
62
65748864 63has 'signature' => (
64 is=>'ro',
bc64165b 65 isa=>'MooseX::Meta::TypeConstraint::Structured::Signature',
66 coerce=>1,
65748864 67 required=>1,
68);
69
70=head1 METHODS
71
72This class defines the following methods.
73
74=head2 _normalize_args
75
bc64165b 76Get arguments into a known state or die trying. Ideally we try to make this
77into a HashRef so we can match it up with the L</signature> HashRef.
65748864 78
79=cut
80
81sub _normalize_args {
82 my ($self, $args) = @_;
bc64165b 83 if(defined $args) {
84 if(ref $args eq 'ARRAY') {
85 return map { $_ => $args->[$_] } (0..$#$args);
86 } elsif (ref $args eq 'HASH') {
87 return %$args;
88 } else {
89 confess 'Signature must be a reference';
90 }
65748864 91 } else {
bc64165b 92 confess 'Signature cannot be empty';
65748864 93 }
94}
95
96=head2 constraint
97
98The constraint is basically validating the L</signature> against the incoming
99
100=cut
101
102sub constraint {
103 my $self = shift;
104 return sub {
bc64165b 105 my %args = $self->_normalize_args(shift);
106 foreach my $idx (keys %{$self->signature}) {
107 my $type_constraint = $self->signature->{$idx};
108 if(my $error = $type_constraint->validate($args{$idx})) {
65748864 109 confess $error;
110 }
111 } 1;
112 };
113}
114
bc64165b 115=head2 equals
116
117modifier to make sure equals descends into the L</signature>
118
119=cut
120
121around 'equals' => sub {
122 my ($equals, $self, $compared_type_constraint) = @_;
123
124 ## Make sure we are comparing typeconstraints of the same base class
125 return unless $compared_type_constraint->isa(__PACKAGE__);
126
127 ## Make sure the base equals is also good
128 return unless $self->$equals($compared_type_constraint);
129
130 ## Make sure the signatures match
131 return unless $self->signature_equals($compared_type_constraint);
132
133 ## If we get this far, the two are equal
134 return 1;
135};
136
137=head2 signature_equals
138
139Check that the signature equals another signature.
140
141=cut
142
143sub signature_equals {
144 my ($self, $compared_type_constraint) = @_;
145
146 foreach my $idx (keys %{$self->signature}) {
147 my $this = $self->signature->{$idx};
148 my $that = $compared_type_constraint->signature->{$idx};
149 return unless $this->equals($that);
150 }
151
152 return 1;
153}
154
65748864 155=head1 AUTHOR
156
157John James Napiorkowski <jjnapiork@cpan.org>
158
159=head1 LICENSE
160
161You may distribute this code under the same terms as Perl itself.
162
163=cut
164
165no Moose; 1;