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.
84 sub _add_type_coercions{
87 my $coercions = ($self->{_coercion_map} ||= []);
88 my %has = map{ $_->[0] => undef } @{$coercions};
90 for(my $i = 0; $i < @_; $i++){
92 my $action = $_[++$i];
94 if(exists $has{$from}){
95 Carp::confess("A coercion action already exists for '$from'");
98 my $type = Mouse::Util::TypeConstraints::find_or_parse_type_constraint($from)
99 or Carp::confess("Could not find the type constraint ($from) to coerce from");
101 push @{$coercions}, [ $type => $action ];
105 if(exists $self->{type_constraints}){ # union type
106 Carp::confess("Cannot add additional type coercions to Union types");
109 $self->{_compiled_type_coercion} = sub {
111 foreach my $pair (@{$coercions}) {
112 #my ($constraint, $converter) = @$pair;
113 if ($pair->[0]->check($thing)) {
115 return $pair->[1]->($thing);
126 return $self->_compiled_type_constraint->(@_);
132 return $_[0] if $self->_compiled_type_constraint->(@_);
134 my $coercion = $self->_compiled_type_coercion;
135 return $coercion ? $coercion->(@_) : $_[0];
139 my ($self, $value) = @_;
140 if ( my $msg = $self->message ) {
142 return $msg->($value);
145 $value = ( defined $value ? overload::StrVal($value) : 'undef' );
146 return "Validation failed for '$self' failed with value $value";
151 my($self, $other) = @_;
153 # ->is_a_type_of('__ANON__') is always false
154 return 0 if !ref($other) && $other eq '__ANON__';
156 (my $other_name = $other) =~ s/\s+//g;
158 return 1 if $self->name eq $other_name;
160 if(exists $self->{type_constraints}){ # union
161 foreach my $type(@{$self->{type_constraints}}){
162 return 1 if $type->name eq $other_name;
166 for(my $parent = $self->parent; defined $parent; $parent = $parent->parent){
167 return 1 if $parent->name eq $other_name;
173 # See also Moose::Meta::TypeConstraint::Parameterizable
175 my($self, $param, $name) = @_;
178 require Mouse::Util::TypeConstraints;
179 $param = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($param);
182 $name ||= sprintf '%s[%s]', $self->name, $param->name;
184 my $generator = $self->{constraint_generator}
185 || Carp::confess("The $name constraint cannot be used, because $param doesn't subtype from a parameterizable type");
187 return Mouse::Meta::TypeConstraint->new(
191 constraint => $generator->($param), # must be 'constraint', not 'optimized'
193 type => 'Parameterized',
202 Mouse::Meta::TypeConstraint - The Mouse Type Constraint metaclass
206 This document describes Mouse version 0.47
210 For the most part, the only time you will ever encounter an
211 instance of this class is if you are doing some serious deep
212 introspection. This API should not be considered final, but
213 it is B<highly unlikely> that this will matter to a regular
230 L<Moose::Meta::TypeConstraint>