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
62 isa=>'ArrayRef[Moose::Meta::TypeConstraint]',
65 =head2 optional_signature
67 This is a signature of internal contraints for the contents of the outer
68 contraint container. These are optional constraints.
72 has 'optional_signature' => (
74 isa=>'ArrayRef[Moose::Meta::TypeConstraint]',
75 predicate=>'has_optional_signature',
80 This class defines the following methods.
82 =head2 _normalize_args
84 Get arguments into a known state or die trying. Ideally we try to make this
85 into a HashRef so we can match it up with the L</signature> HashRef.
90 my ($self, $args) = @_;
92 if(ref $args eq 'ARRAY') {
95 confess 'Signature must be an ArrayRef type';
98 confess 'Signature cannot be empty';
104 The constraint is basically validating the L</signature> against the incoming
111 my @args = $self->_normalize_args(shift);
112 my @signature = @{$self->signature};
113 my @optional_signature = @{$self->optional_signature}
114 if $self->has_optional_signature;
116 ## First make sure all the required type constraints match
117 while( my $type_constraint = shift @signature) {
118 if(my $error = $type_constraint->validate(shift @args)) {
123 ## Now test the option type constraints.
124 while( my $arg = shift @args) {
125 my $optional_type_constraint = shift @optional_signature;
126 if(my $error = $optional_type_constraint->validate($arg)) {
131 ## If we got this far we passed!
136 =head2 signature_equals
138 Check that the signature equals another signature.
142 sub signature_equals {
143 my ($self, $compared_type_constraint) = @_;
145 foreach my $idx (0..$#{$self->signature}) {
146 my $this = $self->signature->[$idx];
147 my $that = $compared_type_constraint->signature->[$idx];
148 return unless $this->equals($that);
151 if($self->has_optional_signature) {
152 foreach my $idx (0..$#{$self->optional_signature}) {
153 my $this = $self->optional_signature->[$idx];
154 my $that = $compared_type_constraint->optional_signature->[$idx];
155 return unless $this->equals($that);
164 modifier to make sure equals descends into the L</signature>
168 around 'equals' => sub {
169 my ($equals, $self, $compared_type_constraint) = @_;
171 ## Make sure we are comparing typeconstraints of the same base class
172 return unless $compared_type_constraint->isa(__PACKAGE__);
174 ## Make sure the base equals is also good
175 return unless $self->$equals($compared_type_constraint);
177 ## Make sure the signatures match
178 return unless $self->signature_equals($compared_type_constraint);
180 ## If we get this far, the two are equal
186 John James Napiorkowski <jjnapiork@cpan.org>
190 You may distribute this code under the same terms as Perl itself.