2 package Moose::Meta::TypeConstraint::Intersection;
8 use Moose::Meta::TypeCoercion::Intersection;
10 use List::Util qw(first);
11 use List::MoreUtils qw(all);
13 use base 'Moose::Meta::TypeConstraint';
15 __PACKAGE__->meta->add_attribute('type_constraints' => (
16 accessor => 'type_constraints',
17 default => sub { [] },
18 Class::MOP::_definition_context(),
22 my ($class, %options) = @_;
24 my $name = join '&' => sort {$a cmp $b}
25 map { $_->name } @{$options{type_constraints}};
27 my $self = $class->SUPER::new(
31 $self->_set_constraint(sub { $self->check($_[0]) });
32 $self->coercion(Moose::Meta::TypeCoercion::Intersection->new(
33 type_constraint => $self
38 sub _actually_compile_type_constraint {
41 my @constraints = @{ $self->type_constraints };
46 foreach my $type (@constraints){
47 $count++ if $type->check($value);
49 return $count==scalar @constraints ? 1: undef;
55 for my $tc ( @{ $self->type_constraints }) {
56 return 0 unless $tc->can_be_inlined;
66 join ' && ' , map { '(' . $_->_inline_check($val) . ')' } @{ $self->type_constraints }
70 sub inline_environment {
73 return { map { %{ $_->inline_environment } } @{ $self->type_constraints } };
77 my ( $self, $type_or_name ) = @_;
79 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
81 return unless $other->isa(__PACKAGE__);
83 my @self_constraints = @{ $self->type_constraints };
84 my @other_constraints = @{ $other->type_constraints };
86 return unless @self_constraints == @other_constraints;
88 # FIXME presort type constraints for efficiency?
89 constraint: foreach my $constraint ( @self_constraints ) {
90 for ( my $i = 0; $i < @other_constraints; $i++ ) {
91 if ( $constraint->equals($other_constraints[$i]) ) {
92 splice @other_constraints, $i, 1;
98 return @other_constraints == 0;
103 $self->type_constraints;
107 my ($self, $value) = @_;
109 foreach my $type (@{$self->type_constraints}) {
110 my $err = $type->validate($value);
111 return unless defined $err;
112 $message .= ($message ? ' and ' : '') . $err
115 return ($message . ' in (' . $self->name . ')') ;
119 my ($self, $value) = @_;
120 return first { $_->check($value) } @{ $self->type_constraints };
124 my ($self, $type_name) = @_;
125 foreach my $type (@{$self->type_constraints}) {
126 return 1 if $type->is_a_type_of($type_name);
132 my ($self, $type_name) = @_;
133 foreach my $type (@{$self->type_constraints}) {
134 return 1 if $type->is_subtype_of($type_name);
139 sub create_child_type {
140 my ( $self, %opts ) = @_;
143 = Moose::Meta::TypeConstraint->new( %opts, parent => $self );
145 # if we have a type constraint intersection, and no
146 # type check, this means we are just aliasing
147 # the intersection constraint, which means we need to
148 # handle this differently.
150 if ( not( defined $opts{constraint} )
151 && $self->has_coercion ) {
152 $constraint->coercion(
153 Moose::Meta::TypeCoercion::Intersection->new(
154 type_constraint => $self,
170 Moose::Meta::TypeConstraint::Intersection - An intersection of Moose type constraints
174 This metaclass represents an intersection of Moose type constraints. More
175 details to be explained later (possibly in a Cookbook recipe).
177 This actually used to be part of Moose::Meta::TypeConstraint, but it
178 is now better off in it's own file.
182 This class is not a subclass of Moose::Meta::TypeConstraint,
183 but it does provide the same API
193 =item B<type_constraints>
199 =item B<includes_type>
205 =head2 Overridden methods
215 =item B<is_a_type_of>
217 =item B<is_subtype_of>
221 =head2 Empty or Stub methods
223 These methods tend to not be very relevant in
224 the context of an intersection. Either that or they are
225 just difficult to specify and not very useful
226 anyway. They are here for completeness.
234 =item B<has_coercion>
240 =item B<hand_optimized_type_constraint>
242 =item B<has_hand_optimized_type_constraint>
244 =item B<create_child_type>
250 All complex software has bugs lurking in it, and this module is no
251 exception. If you find a bug please either email me, or add the bug
256 Stevan Little E<lt>stevan@iinteractive.comE<gt> and
257 Adam Foxson E<lt>afoxson@pobox.comE<gt>
259 =head1 COPYRIGHT AND LICENSE
261 Copyright 2006-2009 by Infinity Interactive, Inc.
263 L<http://www.iinteractive.com>
265 This library is free software; you can redistribute it and/or modify
266 it under the same terms as Perl itself.