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};
27 if($args{_compiled_type_constraint}){
28 Carp::cluck("'_compiled_type_constraint' has been deprecated, use 'optimized' instead")
29 if Mouse::Util::_MOUSE_VERBOSE;
31 $check = $args{_compiled_type_constraint};
35 $args{hand_optimized_type_constraint} = $check;
36 $args{compiled_type_constraint} = $check;
39 $check = $args{constraint};
41 if(defined($check) && ref($check) ne 'CODE'){
42 Carp::confess("Constraint for $args{name} is not a CODE reference");
45 $args{package_defined_in} ||= caller;
47 my $self = bless \%args, $class;
48 $self->compile_type_constraint() if !$self->{hand_optimized_type_constraint};
50 if($self->{type_constraints}){ # Union
52 foreach my $type(@{$self->{type_constraints}}){
53 if($type->has_coercion){
54 push @coercions, $type;
58 $self->{_compiled_type_coercion} = sub {
60 foreach my $type(@coercions){
61 my $value = $type->coerce($thing);
62 return $value if $self->check($value);
72 sub create_child_type{
75 return ref($self)->new(
76 # a child inherits its parent's attributes
79 # but does not inherit 'compiled_type_constraint' and 'hand_optimized_type_constraint'
80 compiled_type_constraint => undef,
81 hand_optimized_type_constraint => undef,
83 # and is given child-specific args, of course.
91 sub _add_type_coercions{
94 my $coercions = ($self->{_coercion_map} ||= []);
95 my %has = map{ $_->[0] => undef } @{$coercions};
97 for(my $i = 0; $i < @_; $i++){
99 my $action = $_[++$i];
101 if(exists $has{$from}){
102 Carp::confess("A coercion action already exists for '$from'");
105 my $type = Mouse::Util::TypeConstraints::find_or_parse_type_constraint($from)
106 or Carp::confess("Could not find the type constraint ($from) to coerce from");
108 push @{$coercions}, [ $type => $action ];
112 if(exists $self->{type_constraints}){ # union type
113 Carp::confess("Cannot add additional type coercions to Union types");
116 $self->{_compiled_type_coercion} = sub {
118 foreach my $pair (@{$coercions}) {
\r
119 #my ($constraint, $converter) = @$pair;
\r
120 if ($pair->[0]->check($thing)) {
\r
122 return $pair->[1]->($thing);
133 return $self->_compiled_type_constraint->(@_);
139 return $_[0] if $self->_compiled_type_constraint->(@_);
141 my $coercion = $self->_compiled_type_coercion;
142 return $coercion ? $coercion->(@_) : $_[0];
146 my ($self, $value) = @_;
147 if ( my $msg = $self->message ) {
149 return $msg->($value);
152 $value = ( defined $value ? overload::StrVal($value) : 'undef' );
153 return "Validation failed for '$self' failed with value $value";
158 my($self, $other) = @_;
160 # ->is_a_type_of('__ANON__') is always false
161 return 0 if !ref($other) && $other eq '__ANON__';
163 (my $other_name = $other) =~ s/\s+//g;
165 return 1 if $self->name eq $other_name;
167 if(exists $self->{type_constraints}){ # union
168 foreach my $type(@{$self->{type_constraints}}){
169 return 1 if $type->name eq $other_name;
173 for(my $parent = $self->parent; defined $parent; $parent = $parent->parent){
174 return 1 if $parent->name eq $other_name;
180 # See also Moose::Meta::TypeConstraint::Parameterizable
182 my($self, $param, $name) = @_;
185 require Mouse::Util::TypeConstraints;
186 $param = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($param);
189 $name ||= sprintf '%s[%s]', $self->name, $param->name;
191 my $generator = $self->{constraint_generator}
192 || Carp::confess("The $name constraint cannot be used, because $param doesn't subtype from a parameterizable type");
194 return Mouse::Meta::TypeConstraint->new(
198 constraint => $generator->($param), # must be 'constraint', not 'optimized'
200 type => 'Parameterized',
209 Mouse::Meta::TypeConstraint - The Mouse Type Constraint metaclass
213 This document describes Mouse version 0.40_09
217 For the most part, the only time you will ever encounter an
218 instance of this class is if you are doing some serious deep
219 introspection. This API should not be considered final, but
220 it is B<highly unlikely> that this will matter to a regular
237 L<Moose::Meta::TypeConstraint>