1 package MooseX::Meta::TypeConstraint::Role::Structured;
4 use Moose::Util::TypeConstraints;
8 MooseX::Meta::TypeConstraint::Role::Structured - Structured Type Constraints
16 our $VERSION = '0.01';
20 Structured type constraints let you assign an internal pattern of type
21 constraints to a 'container' constraint. The goal is to make it easier to
22 declare constraints like "ArrayRef[Int, Int, Str]" where the constraint is an
23 ArrayRef of three elements and the internal constraint on the three is Int, Int
26 To accomplish this, we add an attribute to the base L<Moose::Meta::TypeConstraint>
27 to hold a L</signature>, which is a reference to a pattern of type constraints.
28 We then override L</constraint> to check our incoming value to the attribute
29 against this signature pattern.
33 The following subtypes and coercions are defined in this class.
35 =head2 MooseX::Meta::TypeConstraint::Structured::Signature
37 This is a type constraint to normalize the incoming L</signature>. We want
38 everything as a HashRef in the end.
42 subtype 'MooseX::Meta::TypeConstraint::Structured::Signature',
46 foreach my $key (keys %signature) {
47 $signature{$key}->isa('Moose::Meta::TypeConstraint');
51 coerce 'MooseX::Meta::TypeConstraint::Structured::Signature',
52 from 'ArrayRef[Object]',
55 my %hashed_signature = map { $_ => $signature[$_] } 0..$#signature;
61 This class defines the following attributes.
65 This is a signature of internal contraints for the contents of the outer
72 isa=>'MooseX::Meta::TypeConstraint::Structured::Signature',
79 This class defines the following methods.
81 =head2 _normalize_args
83 Get arguments into a known state or die trying. Ideally we try to make this
84 into a HashRef so we can match it up with the L</signature> HashRef.
89 my ($self, $args) = @_;
91 if(ref $args eq 'ARRAY') {
92 return map { $_ => $args->[$_] } (0..$#$args);
93 } elsif (ref $args eq 'HASH') {
96 confess 'Signature must be a reference';
99 confess 'Signature cannot be empty';
105 The constraint is basically validating the L</signature> against the incoming
112 my %args = $self->_normalize_args(shift);
113 foreach my $idx (keys %{$self->signature}) {
114 my $type_constraint = $self->signature->{$idx};
115 if(my $error = $type_constraint->validate($args{$idx})) {
124 modifier to make sure equals descends into the L</signature>
128 around 'equals' => sub {
129 my ($equals, $self, $compared_type_constraint) = @_;
131 ## Make sure we are comparing typeconstraints of the same base class
132 return unless $compared_type_constraint->isa(__PACKAGE__);
134 ## Make sure the base equals is also good
135 return unless $self->$equals($compared_type_constraint);
137 ## Make sure the signatures match
138 return unless $self->signature_equals($compared_type_constraint);
140 ## If we get this far, the two are equal
144 =head2 signature_equals
146 Check that the signature equals another signature.
150 sub signature_equals {
151 my ($self, $compared_type_constraint) = @_;
153 foreach my $idx (keys %{$self->signature}) {
154 my $this = $self->signature->{$idx};
155 my $that = $compared_type_constraint->signature->{$idx};
156 return unless $this->equals($that);
164 John James Napiorkowski <jjnapiork@cpan.org>
168 You may distribute this code under the same terms as Perl itself.