1 package Mouse::Meta::TypeConstraint;
2 use Mouse::Util qw(:meta); # enables strict and warnings
5 'bool' => sub { 1 }, # always true
7 '""' => sub { $_[0]->name }, # stringify to tc name
9 '|' => sub { # or-combination
10 require Mouse::Util::TypeConstraints;
11 return Mouse::Util::TypeConstraints::find_or_parse_type_constraint(
21 my($class, %args) = @_;
23 $args{name} = '__ANON__' if !defined $args{name};
25 my $check = delete $args{optimized};
28 $args{hand_optimized_type_constraint} = $check;
29 $args{compiled_type_constraint} = $check;
32 $check = $args{constraint};
34 if(defined($check) && ref($check) ne 'CODE'){
35 Carp::confess("Constraint for $args{name} is not a CODE reference");
38 $args{package_defined_in} ||= caller;
40 my $self = bless \%args, $class;
41 $self->compile_type_constraint() if !$self->{hand_optimized_type_constraint};
43 if($self->{type_constraints}){ # Union
45 foreach my $type(@{$self->{type_constraints}}){
46 if($type->has_coercion){
47 push @coercions, $type;
51 $self->{_compiled_type_coercion} = sub {
53 foreach my $type(@coercions){
54 my $value = $type->coerce($thing);
55 return $value if $self->check($value);
65 sub create_child_type{
68 return ref($self)->new(
69 # a child inherits its parent's attributes
72 # but does not inherit 'compiled_type_constraint' and 'hand_optimized_type_constraint'
73 compiled_type_constraint => undef,
74 hand_optimized_type_constraint => undef,
76 # and is given child-specific args, of course.
88 sub _compiled_type_constraint;
89 sub _compiled_type_coercion;
91 sub compile_type_constraint;
93 sub _add_type_coercions{
96 my $coercions = ($self->{_coercion_map} ||= []);
97 my %has = map{ $_->[0] => undef } @{$coercions};
99 for(my $i = 0; $i < @_; $i++){
101 my $action = $_[++$i];
103 if(exists $has{$from}){
104 Carp::confess("A coercion action already exists for '$from'");
107 my $type = Mouse::Util::TypeConstraints::find_or_parse_type_constraint($from)
108 or Carp::confess("Could not find the type constraint ($from) to coerce from");
110 push @{$coercions}, [ $type => $action ];
114 if(exists $self->{type_constraints}){ # union type
115 Carp::confess("Cannot add additional type coercions to Union types");
118 $self->{_compiled_type_coercion} = sub {
120 foreach my $pair (@{$coercions}) {
121 #my ($constraint, $converter) = @$pair;
122 if ($pair->[0]->check($thing)) {
124 return $pair->[1]->($thing);
135 return $self->_compiled_type_constraint->(@_);
141 my $coercion = $self->_compiled_type_coercion;
143 Carp::confess("Cannot coerce without a type coercion");
146 return $_[0] if $self->_compiled_type_constraint->(@_);
148 return $coercion->(@_);
152 my ($self, $value) = @_;
153 if ( my $msg = $self->message ) {
155 return $msg->($value);
158 $value = ( defined $value ? overload::StrVal($value) : 'undef' );
159 return "Validation failed for '$self' failed with value $value";
164 my($self, $other) = @_;
166 # ->is_a_type_of('__ANON__') is always false
167 return 0 if !ref($other) && $other eq '__ANON__';
169 (my $other_name = $other) =~ s/\s+//g;
171 return 1 if $self->name eq $other_name;
173 if(exists $self->{type_constraints}){ # union
174 foreach my $type(@{$self->{type_constraints}}){
175 return 1 if $type->name eq $other_name;
179 for(my $parent = $self->parent; defined $parent; $parent = $parent->parent){
180 return 1 if $parent->name eq $other_name;
186 # See also Moose::Meta::TypeConstraint::Parameterizable
188 my($self, $param, $name) = @_;
191 require Mouse::Util::TypeConstraints;
192 $param = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($param);
195 $name ||= sprintf '%s[%s]', $self->name, $param->name;
197 my $generator = $self->{constraint_generator}
198 || Carp::confess("The $name constraint cannot be used, because $param doesn't subtype from a parameterizable type");
200 return Mouse::Meta::TypeConstraint->new(
204 constraint => $generator->($param), # must be 'constraint', not 'optimized'
206 type => 'Parameterized',
215 Mouse::Meta::TypeConstraint - The Mouse Type Constraint metaclass
219 This document describes Mouse version 0.50
223 For the most part, the only time you will ever encounter an
224 instance of this class is if you are doing some serious deep
225 introspection. This API should not be considered final, but
226 it is B<highly unlikely> that this will matter to a regular
243 L<Moose::Meta::TypeConstraint>