1 package MooseX::Meta::TypeConstraint::Structured::Positional;
4 use Moose::Meta::TypeConstraint ();
5 use Moose::Util::TypeConstraints;
7 extends 'Moose::Meta::TypeConstraint';
8 with 'MooseX::Meta::TypeConstraint::Role::Structured';
12 MooseX::Meta::TypeConstraint::Structured::Positional - Structured Type Constraints
20 our $VERSION = '0.01';
24 Structured type constraints let you assign an internal pattern of type
25 constraints to a 'container' constraint. The goal is to make it easier to
26 declare constraints like "ArrayRef[Int, Int, Str]" where the constraint is an
27 ArrayRef of three elements and the internal constraint on the three is Int, Int
30 To accomplish this, we add an attribute to the base L<Moose::Meta::TypeConstraint>
31 to hold a L</signature>, which is a reference to a pattern of type constraints.
32 We then override L</constraint> to check our incoming value to the attribute
33 against this signature pattern.
35 Positionally structured Constraints expect the internal constraints to be in
36 'positioned' or ArrayRef style order.
40 The following types are defined in this class.
42 =head2 Moose::Meta::TypeConstraint
44 Used to make sure we can properly validate incoming signatures.
48 class_type 'Moose::Meta::TypeConstraint';
52 This class defines the following attributes.
56 This is a signature of internal contraints for the contents of the outer
61 has '+signature' => (isa=>'ArrayRef[Moose::Meta::TypeConstraint]');
63 =head2 optional_signature
65 This is a signature of internal contraints for the contents of the outer
66 contraint container. These are optional constraints.
70 has '+optional_signature' => (isa=>'ArrayRef[Moose::Meta::TypeConstraint]');
74 This class defines the following methods.
76 =head2 _normalize_args
78 Get arguments into a known state or die trying. Ideally we try to make this
79 into a HashRef so we can match it up with the L</signature> HashRef.
84 my ($self, $args) = @_;
86 if(ref $args eq 'ARRAY') {
89 confess 'Signature must be an ArrayRef type';
92 confess 'Signature cannot be empty';
98 The constraint is basically validating the L</signature> against the incoming
105 my @args = $self->_normalize_args(shift);
106 my @signature = @{$self->signature};
107 my @optional_signature = @{$self->optional_signature}
108 if $self->has_optional_signature;
110 ## First make sure all the required type constraints match
111 while( my $type_constraint = shift @signature) {
112 if(my $error = $type_constraint->validate(shift @args)) {
117 ## Now test the option type constraints.
118 while( my $arg = shift @args) {
119 my $optional_type_constraint = shift @optional_signature;
120 if(my $error = $optional_type_constraint->validate($arg)) {
125 ## If we got this far we passed!
130 =head2 signature_equals
132 Check that the signature equals another signature.
136 sub signature_equals {
137 my ($self, $compared_type_constraint) = @_;
139 foreach my $idx (0..$#{$self->signature}) {
140 my $this = $self->signature->[$idx];
141 my $that = $compared_type_constraint->signature->[$idx];
142 return unless $this->equals($that);
145 if($self->has_optional_signature) {
146 foreach my $idx (0..$#{$self->optional_signature}) {
147 my $this = $self->optional_signature->[$idx];
148 my $that = $compared_type_constraint->optional_signature->[$idx];
149 return unless $this->equals($that);
158 modifier to make sure equals descends into the L</signature>
162 around 'equals' => sub {
163 my ($equals, $self, $compared_type_constraint) = @_;
165 ## Make sure we are comparing typeconstraints of the same base class
166 return unless $compared_type_constraint->isa(__PACKAGE__);
168 ## Make sure the base equals is also good
169 return unless $self->$equals($compared_type_constraint);
171 ## Make sure the signatures match
172 return unless $self->signature_equals($compared_type_constraint);
174 ## If we get this far, the two are equal
180 John James Napiorkowski <jjnapiork@cpan.org>
184 You may distribute this code under the same terms as Perl itself.