And the same fix for role_type
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
998a8a25 4use Carp ();
9e856c83 5use List::MoreUtils qw( all any );
9a63faba 6use Scalar::Util qw( blessed reftype );
e606ae5f 7use Moose::Exporter;
a15dff8d 8
d9b40005 9## --------------------------------------------------------
e85d2a5d 10# Prototyped subs must be predeclared because we have a
11# circular dependency with Moose::Meta::Attribute et. al.
12# so in case of us being use'd first the predeclaration
d9b40005 13# ensures the prototypes are in scope when consumers are
14# compiled.
15
d9b40005 16# dah sugah!
180899ed 17sub where (&);
18sub via (&);
19sub message (&);
d9b40005 20sub optimize_as (&);
4e36cf24 21sub inline_as (&);
d9b40005 22
d9b40005 23## --------------------------------------------------------
8c4acc60 24
1fa1a58d 25use Moose::Deprecated;
4e036ee4 26use Moose::Meta::TypeConstraint;
3726f905 27use Moose::Meta::TypeConstraint::Union;
0fbd4b0a 28use Moose::Meta::TypeConstraint::Parameterized;
7e4e1ad4 29use Moose::Meta::TypeConstraint::Parameterizable;
620db045 30use Moose::Meta::TypeConstraint::Class;
31use Moose::Meta::TypeConstraint::Role;
dabed765 32use Moose::Meta::TypeConstraint::Enum;
0a6bff54 33use Moose::Meta::TypeConstraint::DuckType;
2ca63f5d 34use Moose::Meta::TypeCoercion;
3726f905 35use Moose::Meta::TypeCoercion::Union;
22aed3c0 36use Moose::Meta::TypeConstraint::Registry;
4e036ee4 37
e606ae5f 38Moose::Exporter->setup_import_methods(
39 as_is => [
40 qw(
180899ed 41 type subtype class_type role_type maybe_type duck_type
7afaa906 42 as where message optimize_as inline_as
e606ae5f 43 coerce from via
0faea2a8 44 enum union
e606ae5f 45 find_type_constraint
0d29b772 46 register_type_constraint
47 match_on_type )
e606ae5f 48 ],
e606ae5f 49);
a15dff8d 50
d9b40005 51## --------------------------------------------------------
52## type registry and some useful functions for it
53## --------------------------------------------------------
54
22aed3c0 55my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
587ae0d2 56
180899ed 57sub get_type_constraint_registry {$REGISTRY}
58sub list_all_type_constraints { keys %{ $REGISTRY->type_constraints } }
59
d9b40005 60sub export_type_constraints_as_functions {
61 my $pkg = caller();
62 no strict 'refs';
180899ed 63 foreach my $constraint ( keys %{ $REGISTRY->type_constraints } ) {
64 my $tc = $REGISTRY->get_type_constraint($constraint)
65 ->_compiled_type_constraint;
66 *{"${pkg}::${constraint}"}
67 = sub { $tc->( $_[0] ) ? 1 : undef }; # the undef is for compat
a0f8153d 68 }
d9b40005 69}
182134e8 70
0c015f1b 71sub create_type_constraint_union {
8ac5be59 72 _create_type_constraint_union(\@_);
182134e8 73}
a15dff8d 74
a46050ae 75sub create_named_type_constraint_union {
76 my $name = shift;
8ac5be59 77 _create_type_constraint_union($name, \@_);
78}
79
80sub _create_type_constraint_union {
81 my $name;
82 $name = shift if @_ > 1;
83 my @tcs = @{ shift() };
84
a46050ae 85 my @type_constraint_names;
86
8ac5be59 87 if ( scalar @tcs == 1 && _detect_type_constraint_union( $tcs[0] ) ) {
88 @type_constraint_names = _parse_type_constraint_union( $tcs[0] );
a46050ae 89 }
90 else {
8ac5be59 91 @type_constraint_names = @tcs;
a46050ae 92 }
93
94 ( scalar @type_constraint_names >= 2 )
95 || __PACKAGE__->_throw_error(
96 "You must pass in at least 2 type names to make a union");
97
98 my @type_constraints = map {
99 find_or_parse_type_constraint($_)
100 || __PACKAGE__->_throw_error(
101 "Could not locate type constraint ($_) for the union");
102 } @type_constraint_names;
103
104 my %options = (
105 type_constraints => \@type_constraints
106 );
107 $options{name} = $name if defined $name;
108
109 return Moose::Meta::TypeConstraint::Union->new(%options);
110}
111
112
0c015f1b 113sub create_parameterized_type_constraint {
d9b40005 114 my $type_constraint_name = shift;
180899ed 115 my ( $base_type, $type_parameter )
116 = _parse_parameterized_type_constraint($type_constraint_name);
e85d2a5d 117
180899ed 118 ( defined $base_type && defined $type_parameter )
119 || __PACKAGE__->_throw_error(
120 "Could not parse type name ($type_constraint_name) correctly");
e85d2a5d 121
180899ed 122 if ( $REGISTRY->has_type_constraint($base_type) ) {
90e78884 123 my $base_type_tc = $REGISTRY->get_type_constraint($base_type);
124 return _create_parameterized_type_constraint(
125 $base_type_tc,
126 $type_parameter
127 );
180899ed 128 }
129 else {
130 __PACKAGE__->_throw_error(
131 "Could not locate the base type ($base_type)");
90e78884 132 }
22aed3c0 133}
134
90e78884 135sub _create_parameterized_type_constraint {
136 my ( $base_type_tc, $type_parameter ) = @_;
137 if ( $base_type_tc->can('parameterize') ) {
138 return $base_type_tc->parameterize($type_parameter);
180899ed 139 }
140 else {
90e78884 141 return Moose::Meta::TypeConstraint::Parameterized->new(
180899ed 142 name => $base_type_tc->name . '[' . $type_parameter . ']',
90e78884 143 parent => $base_type_tc,
180899ed 144 type_parameter =>
145 find_or_create_isa_type_constraint($type_parameter),
90e78884 146 );
147 }
180899ed 148}
90e78884 149
4ab662d6 150#should we also support optimized checks?
0c015f1b 151sub create_class_type_constraint {
620db045 152 my ( $class, $options ) = @_;
153
180899ed 154# too early for this check
155#find_type_constraint("ClassName")->check($class)
156# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
3fef8ce8 157
fe3eea66 158 my $pkg_defined_in = $options->{package_defined_in} || scalar( caller(1) );
8eddcf9e 159
c8bb956a 160 if (my $type = $REGISTRY->get_type_constraint($class)) {
6f496445 161 if (!($type->isa('Moose::Meta::TypeConstraint::Class') && $type->class eq $class)) {
162 _confess(
163 "The type constraint '$class' has already been created in "
164 . $type->_package_defined_in
165 . " and cannot be created again in "
166 . $pkg_defined_in )
167 }
0f9a0b95 168 else {
169 return $type;
170 }
c8bb956a 171 }
172
620db045 173 my %options = (
8eddcf9e 174 class => $class,
175 name => $class,
176 package_defined_in => $pkg_defined_in,
620db045 177 %{ $options || {} },
4ab662d6 178 );
620db045 179
180 $options{name} ||= "__ANON__";
181
510d13e1 182 my $tc = Moose::Meta::TypeConstraint::Class->new(%options);
183 $REGISTRY->add_type_constraint($tc);
184 return $tc;
3fef8ce8 185}
186
0c015f1b 187sub create_role_type_constraint {
620db045 188 my ( $role, $options ) = @_;
e85d2a5d 189
180899ed 190# too early for this check
191#find_type_constraint("ClassName")->check($class)
192# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
e85d2a5d 193
fe3eea66 194 my $pkg_defined_in = $options->{package_defined_in} || scalar( caller(1) );
8eddcf9e 195
c8bb956a 196 if (my $type = $REGISTRY->get_type_constraint($role)) {
6f496445 197 if (!($type->isa('Moose::Meta::TypeConstraint::Role') && $type->role eq $role)) {
198 _confess(
199 "The type constraint '$role' has already been created in "
200 . $type->_package_defined_in
201 . " and cannot be created again in "
202 . $pkg_defined_in )
203 }
7b1df680 204 else {
205 return $type;
206 }
c8bb956a 207 }
208
620db045 209 my %options = (
8eddcf9e 210 role => $role,
211 name => $role,
212 package_defined_in => $pkg_defined_in,
620db045 213 %{ $options || {} },
214 );
e85d2a5d 215
620db045 216 $options{name} ||= "__ANON__";
217
510d13e1 218 my $tc = Moose::Meta::TypeConstraint::Role->new(%options);
219 $REGISTRY->add_type_constraint($tc);
220 return $tc;
620db045 221}
222
0c015f1b 223sub find_or_create_type_constraint {
620db045 224 my ( $type_constraint_name, $options_for_anon_type ) = @_;
225
180899ed 226 if ( my $constraint
227 = find_or_parse_type_constraint($type_constraint_name) ) {
620db045 228 return $constraint;
d9b40005 229 }
620db045 230 elsif ( defined $options_for_anon_type ) {
180899ed 231
d9b40005 232 # NOTE:
4ab662d6 233 # if there is no $options_for_anon_type
234 # specified, then we assume they don't
f3c4e20e 235 # want to create one, and return nothing.
f3c4e20e 236
d9b40005 237 # otherwise assume that we should create
e85d2a5d 238 # an ANON type with the $options_for_anon_type
d9b40005 239 # options which can be passed in. It should
e85d2a5d 240 # be noted that these don't get registered
d9b40005 241 # so we need to return it.
242 # - SL
243 return Moose::Meta::TypeConstraint->new(
244 name => '__ANON__',
e85d2a5d 245 %{$options_for_anon_type}
d9b40005 246 );
247 }
e85d2a5d 248
620db045 249 return;
250}
251
0c015f1b 252sub find_or_create_isa_type_constraint {
fe3eea66 253 my ($type_constraint_name, $options) = @_;
180899ed 254 find_or_parse_type_constraint($type_constraint_name)
fe3eea66 255 || create_class_type_constraint($type_constraint_name, $options);
620db045 256}
257
0c015f1b 258sub find_or_create_does_type_constraint {
fe3eea66 259 my ($type_constraint_name, $options) = @_;
180899ed 260 find_or_parse_type_constraint($type_constraint_name)
fe3eea66 261 || create_role_type_constraint($type_constraint_name, $options);
620db045 262}
263
0c015f1b 264sub find_or_parse_type_constraint {
eb4c4e82 265 my $type_constraint_name = normalize_type_constraint_name(shift);
620db045 266 my $constraint;
180899ed 267
268 if ( $constraint = find_type_constraint($type_constraint_name) ) {
e606ae5f 269 return $constraint;
180899ed 270 }
271 elsif ( _detect_type_constraint_union($type_constraint_name) ) {
620db045 272 $constraint = create_type_constraint_union($type_constraint_name);
180899ed 273 }
274 elsif ( _detect_parameterized_type_constraint($type_constraint_name) ) {
275 $constraint
276 = create_parameterized_type_constraint($type_constraint_name);
277 }
278 else {
620db045 279 return;
280 }
bb6c8335 281
d9b40005 282 $REGISTRY->add_type_constraint($constraint);
e85d2a5d 283 return $constraint;
d9b40005 284}
22aed3c0 285
eb4c4e82 286sub normalize_type_constraint_name {
84a9c64c 287 my $type_constraint_name = shift;
c8f663b2 288 $type_constraint_name =~ s/\s//g;
eb4c4e82 289 return $type_constraint_name;
290}
291
5f223879 292sub _confess {
293 my $error = shift;
294
295 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
296 Carp::confess($error);
297}
298
22aed3c0 299## --------------------------------------------------------
300## exported functions ...
301## --------------------------------------------------------
302
0c015f1b 303sub find_type_constraint {
eeedfc8a 304 my $type = shift;
305
306 if ( blessed $type and $type->isa("Moose::Meta::TypeConstraint") ) {
307 return $type;
e606ae5f 308 }
309 else {
310 return unless $REGISTRY->has_type_constraint($type);
eeedfc8a 311 return $REGISTRY->get_type_constraint($type);
312 }
313}
22aed3c0 314
0c015f1b 315sub register_type_constraint {
3fef8ce8 316 my $constraint = shift;
180899ed 317 __PACKAGE__->_throw_error("can't register an unnamed type constraint")
318 unless defined $constraint->name;
3fef8ce8 319 $REGISTRY->add_type_constraint($constraint);
dabed765 320 return $constraint;
3fef8ce8 321}
322
7c13858b 323# type constructors
a15dff8d 324
9c27968f 325sub type {
9e856c83 326 my $name = shift;
9a63faba 327
9e856c83 328 my %p = map { %{$_} } @_;
329
180899ed 330 return _create_type_constraint(
331 $name, undef, $p{where}, $p{message},
4e36cf24 332 $p{optimize_as}, $p{inline_as},
180899ed 333 );
a15dff8d 334}
335
9c27968f 336sub subtype {
180899ed 337 if ( @_ == 1 && !ref $_[0] ) {
338 __PACKAGE__->_throw_error(
339 'A subtype cannot consist solely of a name, it must have a parent'
340 );
f75f625d 341 }
342
f6c0c589 343 # The blessed check is mostly to accommodate MooseX::Types, which
344 # uses an object which overloads stringification as a type name.
180899ed 345 my $name = ref $_[0] && !blessed $_[0] ? undef : shift;
9a63faba 346
347 my %p = map { %{$_} } @_;
348
349 # subtype Str => where { ... };
180899ed 350 if ( !exists $p{as} ) {
9e856c83 351 $p{as} = $name;
9a63faba 352 $name = undef;
353 }
354
180899ed 355 return _create_type_constraint(
356 $name, $p{as}, $p{where}, $p{message},
4e36cf24 357 $p{optimize_as}, $p{inline_as},
180899ed 358 );
a15dff8d 359}
360
9c27968f 361sub class_type {
510d13e1 362 create_class_type_constraint(@_);
3fef8ce8 363}
364
620db045 365sub role_type ($;$) {
510d13e1 366 create_role_type_constraint(@_);
620db045 367}
368
1b2c9bda 369sub maybe_type {
370 my ($type_parameter) = @_;
371
28ce1444 372 register_type_constraint(
ed7060d9 373 $REGISTRY->get_type_constraint('Maybe')->parameterize($type_parameter)
28ce1444 374 );
1b2c9bda 375}
376
180899ed 377sub duck_type {
cdacfaf3 378 my ( $type_name, @methods ) = @_;
180899ed 379 if ( ref $type_name eq 'ARRAY' && !@methods ) {
cdacfaf3 380 @methods = @$type_name;
180899ed 381 $type_name = undef;
382 }
bce5d4a5 383 if ( @methods == 1 && ref $methods[0] eq 'ARRAY' ) {
384 @methods = @{ $methods[0] };
385 }
180899ed 386
387 register_type_constraint(
0a6bff54 388 create_duck_type_constraint(
cdacfaf3 389 $type_name,
0a6bff54 390 \@methods,
180899ed 391 )
392 );
393}
394
9c27968f 395sub coerce {
180899ed 396 my ( $type_name, @coercion_map ) = @_;
397 _install_type_coercions( $type_name, \@coercion_map );
182134e8 398}
399
f6c0c589 400# The trick of returning @_ lets us avoid having to specify a
401# prototype. Perl will parse this:
402#
403# subtype 'Foo'
404# => as 'Str'
405# => where { ... }
406#
407# as this:
408#
409# subtype( 'Foo', as( 'Str', where { ... } ) );
410#
69229b40 411# If as() returns all its extra arguments, this just works, and
f6c0c589 412# preserves backwards compatibility.
180899ed 413sub as { { as => shift }, @_ }
9e856c83 414sub where (&) { { where => $_[0] } }
415sub message (&) { { message => $_[0] } }
416sub optimize_as (&) { { optimize_as => $_[0] } }
4e36cf24 417sub inline_as (&) { { inline_as => $_[0] } }
8ecb1fa0 418
9a63faba 419sub from {@_}
420sub via (&) { $_[0] }
a15dff8d 421
9c27968f 422sub enum {
180899ed 423 my ( $type_name, @values ) = @_;
424
4ab662d6 425 # NOTE:
426 # if only an array-ref is passed then
9f4334a1 427 # you get an anon-enum
428 # - SL
f6af1028 429 if ( ref $type_name eq 'ARRAY' ) {
430 @values == 0
431 || __PACKAGE__->_throw_error("enum called with an array reference and additional arguments. Did you mean to parenthesize the enum call's parameters?");
432
9f4334a1 433 @values = @$type_name;
434 $type_name = undef;
435 }
bce5d4a5 436 if ( @values == 1 && ref $values[0] eq 'ARRAY' ) {
437 @values = @{ $values[0] };
438 }
dabed765 439
440 register_type_constraint(
441 create_enum_type_constraint(
442 $type_name,
443 \@values,
444 )
445 );
446}
447
0faea2a8 448sub union {
449 my ( $type_name, @constraints ) = @_;
450 if ( ref $type_name eq 'ARRAY' ) {
451 @constraints == 0
452 || __PACKAGE__->_throw_error("union called with an array reference and additional arguments.");
453 @constraints = @$type_name;
454 $type_name = undef;
455 }
456 if ( @constraints == 1 && ref $constraints[0] eq 'ARRAY' ) {
457 @constraints = @{ $constraints[0] };
458 }
0faea2a8 459 if ( defined $type_name ) {
a46050ae 460 return register_type_constraint(
461 create_named_type_constraint_union( $type_name, @constraints )
462 );
0faea2a8 463 }
a46050ae 464 return create_type_constraint_union( @constraints );
0faea2a8 465}
466
0c015f1b 467sub create_enum_type_constraint {
dabed765 468 my ( $type_name, $values ) = @_;
e606ae5f 469
dabed765 470 Moose::Meta::TypeConstraint::Enum->new(
180899ed 471 name => $type_name || '__ANON__',
dabed765 472 values => $values,
a0f8153d 473 );
fcec2383 474}
475
0a6bff54 476sub create_duck_type_constraint {
477 my ( $type_name, $methods ) = @_;
478
479 Moose::Meta::TypeConstraint::DuckType->new(
480 name => $type_name || '__ANON__',
481 methods => $methods,
482 );
483}
484
0d29b772 485sub match_on_type {
486 my ($to_match, @cases) = @_;
487 my $default;
488 if (@cases % 2 != 0) {
489 $default = pop @cases;
490 (ref $default eq 'CODE')
491 || __PACKAGE__->_throw_error("Default case must be a CODE ref, not $default");
492 }
493 while (@cases) {
494 my ($type, $action) = splice @cases, 0, 2;
495
496 unless (blessed $type && $type->isa('Moose::Meta::TypeConstraint')) {
497 $type = find_or_parse_type_constraint($type)
498 || __PACKAGE__->_throw_error("Cannot find or parse the type '$type'")
499 }
500
501 (ref $action eq 'CODE')
502 || __PACKAGE__->_throw_error("Match action must be a CODE ref, not $action");
503
504 if ($type->check($to_match)) {
505 local $_ = $to_match;
506 return $action->($to_match);
507 }
508 }
1d39d709 509 (defined $default)
510 || __PACKAGE__->_throw_error("No cases matched for $to_match");
0d29b772 511 {
512 local $_ = $to_match;
1d39d709 513 return $default->($to_match);
0d29b772 514 }
515}
516
517
d9b40005 518## --------------------------------------------------------
519## desugaring functions ...
520## --------------------------------------------------------
521
e85d2a5d 522sub _create_type_constraint ($$$;$$) {
9a63faba 523 my $name = shift;
524 my $parent = shift;
525 my $check = shift;
526 my $message = shift;
527 my $optimized = shift;
4e36cf24 528 my $inlined = shift;
d9b40005 529
9a63faba 530 my $pkg_defined_in = scalar( caller(1) );
e85d2a5d 531
1da6728b 532 if ( defined $name ) {
d9b40005 533 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 534
5f223879 535 ( $type->_package_defined_in eq $pkg_defined_in )
536 || _confess(
537 "The type constraint '$name' has already been created in "
538 . $type->_package_defined_in
539 . " and cannot be created again in "
540 . $pkg_defined_in )
541 if defined $type;
eee1a213 542
543 $name =~ /^[\w:\.]+$/
544 or die qq{$name contains invalid characters for a type name.}
33c8a6d0 545 . qq{ Names can contain alphanumeric character, ":", and "."\n};
e85d2a5d 546 }
1da6728b 547
9ceb576e 548 my %opts = (
9a63faba 549 name => $name,
d9b40005 550 package_defined_in => $pkg_defined_in,
e85d2a5d 551
1da6728b 552 ( $check ? ( constraint => $check ) : () ),
553 ( $message ? ( message => $message ) : () ),
554 ( $optimized ? ( optimized => $optimized ) : () ),
4e36cf24 555 ( $inlined ? ( inlined => $inlined ) : () ),
d9b40005 556 );
1da6728b 557
9ceb576e 558 my $constraint;
180899ed 559 if (
560 defined $parent
1da6728b 561 and $parent
180899ed 562 = blessed $parent
563 ? $parent
564 : find_or_create_isa_type_constraint($parent)
565 ) {
85a9908f 566 $constraint = $parent->create_child_type(%opts);
1da6728b 567 }
568 else {
569 $constraint = Moose::Meta::TypeConstraint->new(%opts);
4ab662d6 570 }
d9b40005 571
572 $REGISTRY->add_type_constraint($constraint)
573 if defined $name;
574
575 return $constraint;
576}
577
e85d2a5d 578sub _install_type_coercions ($$) {
180899ed 579 my ( $type_name, $coercion_map ) = @_;
e606ae5f 580 my $type = find_type_constraint($type_name);
180899ed 581 ( defined $type )
582 || __PACKAGE__->_throw_error(
a885c019 583 "Cannot find type '$type_name', perhaps you forgot to load it");
180899ed 584 if ( $type->has_coercion ) {
41e007e4 585 $type->coercion->add_type_coercions(@$coercion_map);
586 }
587 else {
588 my $type_coercion = Moose::Meta::TypeCoercion->new(
589 type_coercion_map => $coercion_map,
590 type_constraint => $type
591 );
592 $type->coercion($type_coercion);
593 }
d9b40005 594}
595
596## --------------------------------------------------------
f1917f58 597## type notation parsing ...
598## --------------------------------------------------------
599
600{
180899ed 601
e85d2a5d 602 # All I have to say is mugwump++ cause I know
603 # do not even have enough regexp-fu to be able
604 # to have written this (I can only barely
f1917f58 605 # understand it as it is)
e85d2a5d 606 # - SL
607
f1917f58 608 use re "eval";
609
eee1a213 610 my $valid_chars = qr{[\w:\.]};
68d5a469 611 my $type_atom = qr{ (?>$valid_chars+) }x;
68113f48 612 my $ws = qr{ (?>\s*) }x;
613 my $op_union = qr{ $ws \| $ws }x;
614
615 my ($type, $type_capture_parts, $type_with_parameter, $union, $any);
616 if (Class::MOP::IS_RUNNING_ON_5_10) {
617 my $type_pattern
618 = q{ (?&type_atom) (?: \[ (?&ws) (?&any) (?&ws) \] )? };
619 my $type_capture_parts_pattern
620 = q{ ((?&type_atom)) (?: \[ (?&ws) ((?&any)) (?&ws) \] )? };
621 my $type_with_parameter_pattern
622 = q{ (?&type_atom) \[ (?&ws) (?&any) (?&ws) \] };
623 my $union_pattern
624 = q{ (?&type) (?> (?: (?&op_union) (?&type) )+ ) };
625 my $any_pattern
626 = q{ (?&type) | (?&union) };
627
628 my $defines = qr{(?(DEFINE)
629 (?<valid_chars> $valid_chars)
630 (?<type_atom> $type_atom)
631 (?<ws> $ws)
632 (?<op_union> $op_union)
633 (?<type> $type_pattern)
634 (?<type_capture_parts> $type_capture_parts_pattern)
635 (?<type_with_parameter> $type_with_parameter_pattern)
636 (?<union> $union_pattern)
637 (?<any> $any_pattern)
638 )}x;
639
640 $type = qr{ $type_pattern $defines }x;
641 $type_capture_parts = qr{ $type_capture_parts_pattern $defines }x;
642 $type_with_parameter = qr{ $type_with_parameter_pattern $defines }x;
643 $union = qr{ $union_pattern $defines }x;
644 $any = qr{ $any_pattern $defines }x;
645 }
646 else {
647 $type
648 = qr{ $type_atom (?: \[ $ws (??{$any}) $ws \] )? }x;
649 $type_capture_parts
650 = qr{ ($type_atom) (?: \[ $ws ((??{$any})) $ws \] )? }x;
651 $type_with_parameter
652 = qr{ $type_atom \[ $ws (??{$any}) $ws \] }x;
653 $union
654 = qr{ $type (?> (?: $op_union $type )+ ) }x;
655 $any
656 = qr{ $type | $union }x;
657 }
f1917f58 658
f1917f58 659
0fbd4b0a 660 sub _parse_parameterized_type_constraint {
180899ed 661 { no warnings 'void'; $any; } # force capture of interpolated lexical
84a9c64c 662 $_[0] =~ m{ $type_capture_parts }x;
180899ed 663 return ( $1, $2 );
f1917f58 664 }
665
0fbd4b0a 666 sub _detect_parameterized_type_constraint {
180899ed 667 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 668 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 669 }
670
671 sub _parse_type_constraint_union {
180899ed 672 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 673 my $given = shift;
674 my @rv;
675 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
82a5b1a7 676 push @rv => $1;
e85d2a5d 677 }
180899ed 678 ( pos($given) eq length($given) )
679 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
680 . pos($given)
681 . " and str-length="
682 . length($given)
683 . ")" );
e85d2a5d 684 @rv;
f1917f58 685 }
686
687 sub _detect_type_constraint_union {
180899ed 688 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 689 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 690 }
691}
692
693## --------------------------------------------------------
d9b40005 694# define some basic built-in types
695## --------------------------------------------------------
a15dff8d 696
06d02aac 697# By making these classes immutable before creating all the types in
698# Moose::Util::TypeConstraints::Builtin , we avoid repeatedly calling the slow
699# MOP-based accessors.
3cae4250 700$_->make_immutable(
701 inline_constructor => 1,
702 constructor_name => "_new",
703
704 # these are Class::MOP accessors, so they need inlining
705 inline_accessors => 1
706 ) for grep { $_->is_mutable }
37edf27e 707 map { Class::MOP::class_of($_) }
3cae4250 708 qw(
709 Moose::Meta::TypeConstraint
710 Moose::Meta::TypeConstraint::Union
711 Moose::Meta::TypeConstraint::Parameterized
712 Moose::Meta::TypeConstraint::Parameterizable
713 Moose::Meta::TypeConstraint::Class
714 Moose::Meta::TypeConstraint::Role
715 Moose::Meta::TypeConstraint::Enum
0a6bff54 716 Moose::Meta::TypeConstraint::DuckType
3cae4250 717 Moose::Meta::TypeConstraint::Registry
718);
719
06d02aac 720require Moose::Util::TypeConstraints::Builtins;
721Moose::Util::TypeConstraints::Builtins::define_builtins($REGISTRY);
7e4e1ad4 722
180899ed 723my @PARAMETERIZABLE_TYPES
2c29c0e7 724 = map { $REGISTRY->get_type_constraint($_) } qw[ScalarRef ArrayRef HashRef Maybe];
180899ed 725
726sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 727
4ab662d6 728sub add_parameterizable_type {
7e4e1ad4 729 my $type = shift;
180899ed 730 ( blessed $type
731 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
732 || __PACKAGE__->_throw_error(
733 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
734 );
7e4e1ad4 735 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 736}
7e4e1ad4 737
738## --------------------------------------------------------
d9b40005 739# end of built-in types ...
740## --------------------------------------------------------
741
943596a6 742{
743 my @BUILTINS = list_all_type_constraints();
180899ed 744 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 745}
746
6ea98933 747sub _throw_error {
6b83828f 748 shift;
6ea98933 749 require Moose;
750 unshift @_, 'Moose';
751 goto &Moose::throw_error;
752}
753
a15dff8d 7541;
755
ad46f524 756# ABSTRACT: Type constraint system for Moose
757
a15dff8d 758__END__
759
760=pod
761
a15dff8d 762=head1 SYNOPSIS
763
764 use Moose::Util::TypeConstraints;
765
04eec387 766 subtype 'Natural',
767 as 'Int',
768 where { $_ > 0 };
e85d2a5d 769
04eec387 770 subtype 'NaturalLessThanTen',
771 as 'Natural',
772 where { $_ < 10 },
773 message { "This number ($_) is not less than ten!" };
e85d2a5d 774
04eec387 775 coerce 'Num',
776 from 'Str',
777 via { 0+$_ };
e85d2a5d 778
00954dd1 779 class_type 'DateTimeClass', { class => 'DateTime' };
83aa5247 780
781 role_type 'Barks', { role => 'Some::Library::Role::Barks' };
782
04eec387 783 enum 'RGBColors', [qw(red green blue)];
a15dff8d 784
74dccf76 785 union 'StringOrArray', [qw( String Array )];
786
e7fcb7b2 787 no Moose::Util::TypeConstraints;
788
a15dff8d 789=head1 DESCRIPTION
790
e85d2a5d 791This module provides Moose with the ability to create custom type
6549b0d1 792constraints to be used in attribute definition.
e522431d 793
6ba6d68c 794=head2 Important Caveat
795
e85d2a5d 796This is B<NOT> a type system for Perl 5. These are type constraints,
797and they are not used by Moose unless you tell it to. No type
e7fcb7b2 798inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 799
e7fcb7b2 800A type constraint is at heart a small "check if a value is valid"
801function. A constraint can be associated with an attribute. This
802simplifies parameter validation, and makes your code clearer to read,
803because you can refer to constraints by name.
6ba6d68c 804
2c0cbef7 805=head2 Slightly Less Important Caveat
806
e7fcb7b2 807It is B<always> a good idea to quote your type names.
004222dc 808
e7fcb7b2 809This prevents Perl from trying to execute the call as an indirect
810object call. This can be an issue when you have a subtype with the
811same name as a valid class.
2c0cbef7 812
e7fcb7b2 813For instance:
e85d2a5d 814
2c0cbef7 815 subtype DateTime => as Object => where { $_->isa('DateTime') };
816
e7fcb7b2 817will I<just work>, while this:
2c0cbef7 818
819 use DateTime;
820 subtype DateTime => as Object => where { $_->isa('DateTime') };
821
e85d2a5d 822will fail silently and cause many headaches. The simple way to solve
823this, as well as future proof your subtypes from classes which have
e7fcb7b2 824yet to have been created, is to quote the type name:
2c0cbef7 825
826 use DateTime;
04eec387 827 subtype 'DateTime', as 'Object', where { $_->isa('DateTime') };
2c0cbef7 828
6ba6d68c 829=head2 Default Type Constraints
e522431d 830
e606ae5f 831This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 832that hierarchy represented visually.
e522431d 833
834 Any
e85d2a5d 835 Item
5a4c5493 836 Bool
7e4e1ad4 837 Maybe[`a]
f65cb534 838 Undef
839 Defined
5a4c5493 840 Value
5a4c5493 841 Str
f1bbe1e1 842 Num
843 Int
fcb5b0cd 844 ClassName
845 RoleName
5a4c5493 846 Ref
2c29c0e7 847 ScalarRef[`a]
7e4e1ad4 848 ArrayRef[`a]
849 HashRef[`a]
5a4c5493 850 CodeRef
851 RegexpRef
3f7376b0 852 GlobRef
94ab1609 853 FileHandle
e85d2a5d 854 Object
e522431d 855
4ab662d6 856B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 857parameterized, this means you can say:
858
757e07ef 859 ArrayRef[Int] # an array of integers
7e4e1ad4 860 HashRef[CodeRef] # a hash of str to CODE ref mappings
2c29c0e7 861 ScalarRef[Int] # a reference to an integer
7e4e1ad4 862 Maybe[Str] # value may be a string, may be undefined
863
4e8a0f64 864If Moose finds a name in brackets that it does not recognize as an
865existing type, it assumes that this is a class name, for example
866C<ArrayRef[DateTime]>.
867
e7fcb7b2 868B<NOTE:> Unless you parameterize a type, then it is invalid to include
869the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
870name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 871
4ab662d6 872B<NOTE:> The C<Undef> type constraint for the most part works
873correctly now, but edge cases may still exist, please use it
6549b0d1 874sparingly.
703e92fb 875
7e4e1ad4 876B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 877existence check. This means that your class B<must> be loaded for this
878type constraint to pass.
9af1d28b 879
e7fcb7b2 880B<NOTE:> The C<RoleName> constraint checks a string is a I<package
4831e2de 881name> which is a role, like C<'MyApp::Role::Comparable'>.
ed87d4fd 882
e606ae5f 883=head2 Type Constraint Naming
004222dc 884
eee1a213 885Type name declared via this module can only contain alphanumeric
886characters, colons (:), and periods (.).
887
e606ae5f 888Since the types created by this module are global, it is suggested
889that you namespace your types just as you would namespace your
e7fcb7b2 890modules. So instead of creating a I<Color> type for your
891B<My::Graphics> module, you would call the type
892I<My::Graphics::Types::Color> instead.
004222dc 893
703e92fb 894=head2 Use with Other Constraint Modules
895
e7fcb7b2 896This module can play nicely with other constraint modules with some
897slight tweaking. The C<where> clause in types is expected to be a
69229b40 898C<CODE> reference which checks its first argument and returns a
e7fcb7b2 899boolean. Since most constraint modules work in a similar way, it
900should be simple to adapt them to work with Moose.
703e92fb 901
e85d2a5d 902For instance, this is how you could use it with
903L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 904
9e856c83 905 type 'HashOfArrayOfObjects',
04eec387 906 where {
907 IsHashRef(
908 -keys => HasLength,
909 -values => IsArrayRef(IsObject)
910 )->(@_);
911 };
703e92fb 912
2c739d1a 913For more examples see the F<t/examples/example_w_DCS.t> test
e7fcb7b2 914file.
703e92fb 915
69229b40 916Here is an example of using L<Test::Deep> and its non-test
e85d2a5d 917related C<eq_deeply> function.
703e92fb 918
04eec387 919 type 'ArrayOfHashOfBarsAndRandomNumbers',
920 where {
e85d2a5d 921 eq_deeply($_,
703e92fb 922 array_each(subhashof({
923 bar => isa('Bar'),
924 random_number => ignore()
e85d2a5d 925 })))
703e92fb 926 };
927
e606ae5f 928For a complete example see the
2c739d1a 929F<t/examples/example_w_TestDeep.t> test file.
e85d2a5d 930
32549612 931=head2 Error messages
932
933Type constraints can also specify custom error messages, for when they fail to
934validate. This is provided as just another coderef, which receives the invalid
935value in C<$_>, as in:
936
937 subtype 'PositiveInt',
938 as 'Int',
939 where { $_ > 0 },
940 message { "$_ is not a positive integer!" };
941
942If no message is specified, a default message will be used, which indicates
943which type constraint was being used and what value failed. If
944L<Devel::PartialDump> (version 0.14 or higher) is installed, it will be used to
945display the invalid value, otherwise it will just be printed as is.
946
a15dff8d 947=head1 FUNCTIONS
948
949=head2 Type Constraint Constructors
950
e7fcb7b2 951The following functions are used to create type constraints. They
952will also register the type constraints your create in a global
953registry that is used to look types up by name.
a15dff8d 954
cec39889 955See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 956
6ba6d68c 957=over 4
a15dff8d 958
04eec387 959=item B<< subtype 'Name', as 'Parent', where { } ... >>
182134e8 960
e85d2a5d 961This creates a named subtype.
d6e2d9a1 962
dba9208a 963If you provide a parent that Moose does not recognize, it will
964automatically create a new class type constraint for this name.
965
9e856c83 966When creating a named type, the C<subtype> function should either be
967called with the sugar helpers (C<where>, C<message>, etc), or with a
968name and a hashref of parameters:
969
970 subtype( 'Foo', { where => ..., message => ... } );
971
972The valid hashref keys are C<as> (the parent), C<where>, C<message>,
973and C<optimize_as>.
9a63faba 974
04eec387 975=item B<< subtype as 'Parent', where { } ... >>
182134e8 976
e85d2a5d 977This creates an unnamed subtype and will return the type
978constraint meta-object, which will be an instance of
979L<Moose::Meta::TypeConstraint>.
a15dff8d 980
9e856c83 981When creating an anonymous type, the C<subtype> function should either
982be called with the sugar helpers (C<where>, C<message>, etc), or with
983just a hashref of parameters:
984
985 subtype( { where => ..., message => ... } );
986
620db045 987=item B<class_type ($class, ?$options)>
3fef8ce8 988
ed87d4fd 989Creates a new subtype of C<Object> with the name C<$class> and the
990metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 991
83aa5247 992 # Create a type called 'Box' which tests for objects which ->isa('Box')
993 class_type 'Box';
994
00954dd1 995By default, the name of the type and the name of the class are the same, but
996you can specify both separately.
83aa5247 997
998 # Create a type called 'Box' which tests for objects which ->isa('ObjectLibrary::Box');
999 class_type 'Box', { class => 'ObjectLibrary::Box' };
1000
620db045 1001=item B<role_type ($role, ?$options)>
1002
ed87d4fd 1003Creates a C<Role> type constraint with the name C<$role> and the
1004metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 1005
83aa5247 1006 # Create a type called 'Walks' which tests for objects which ->does('Walks')
1007 role_type 'Walks';
1008
00954dd1 1009By default, the name of the type and the name of the role are the same, but
1010you can specify both separately.
83aa5247 1011
1012 # Create a type called 'Walks' which tests for objects which ->does('MooseX::Role::Walks');
1013 role_type 'Walks', { role => 'MooseX::Role::Walks' };
1014
1b2c9bda 1015=item B<maybe_type ($type)>
1016
1017Creates a type constraint for either C<undef> or something of the
1018given type.
1019
bce5d4a5 1020=item B<duck_type ($name, \@methods)>
e451e855 1021
88b68372 1022This will create a subtype of Object and test to make sure the value
bce5d4a5 1023C<can()> do the methods in C<\@methods>.
88b68372 1024
1025This is intended as an easy way to accept non-Moose objects that
1026provide a certain interface. If you're using Moose classes, we
1027recommend that you use a C<requires>-only Role instead.
e451e855 1028
1029=item B<duck_type (\@methods)>
1030
bce5d4a5 1031If passed an ARRAY reference as the only parameter instead of the
1032C<$name>, C<\@methods> pair, this will create an unnamed duck type.
1033This can be used in an attribute definition like so:
e451e855 1034
88b68372 1035 has 'cache' => (
1036 is => 'ro',
1037 isa => duck_type( [qw( get_set )] ),
1038 );
e451e855 1039
bce5d4a5 1040=item B<enum ($name, \@values)>
fcec2383 1041
e85d2a5d 1042This will create a basic subtype for a given set of strings.
1043The resulting constraint will be a subtype of C<Str> and
bce5d4a5 1044will match any of the items in C<\@values>. It is case sensitive.
cec39889 1045See the L</SYNOPSIS> for a simple example.
2c0cbef7 1046
6549b0d1 1047B<NOTE:> This is not a true proper enum type, it is simply
1048a convenient constraint builder.
2c0cbef7 1049
9f4334a1 1050=item B<enum (\@values)>
1051
bce5d4a5 1052If passed an ARRAY reference as the only parameter instead of the
1053C<$name>, C<\@values> pair, this will create an unnamed enum. This
1054can then be used in an attribute definition like so:
9f4334a1 1055
1056 has 'sort_order' => (
1057 is => 'ro',
4ab662d6 1058 isa => enum([qw[ ascending descending ]]),
9f4334a1 1059 );
1060
74dccf76 1061=item B<union ($name, \@constraints)>
1062
1063This will create a basic subtype where any of the provided constraints
1064may match in order to satisfy this constraint.
1065
1066=item B<union (\@constraints)>
1067
1068If passed an ARRAY reference as the only parameter instead of the
1069C<$name>, C<\@constraints> pair, this will create an unnamed union.
1070This can then be used in an attribute definition like so:
1071
1072 has 'items' => (
1073 is => 'ro',
1074 isa => union([qw[ Str ArrayRef ]]),
1075 );
1076
1077This is similar to the existing string union:
1078
1079 isa => 'Str|ArrayRef'
1080
1081except that it supports anonymous elements as child constraints:
1082
1083 has 'color' => (
1084 isa => 'ro',
1085 isa => union([ 'Int', enum([qw[ red green blue ]]) ]),
1086 );
1087
e7fcb7b2 1088=item B<as 'Parent'>
a15dff8d 1089
6ba6d68c 1090This is just sugar for the type constraint construction syntax.
a15dff8d 1091
e7fcb7b2 1092It takes a single argument, which is the name of a parent type.
1093
1094=item B<where { ... }>
a15dff8d 1095
6ba6d68c 1096This is just sugar for the type constraint construction syntax.
76d37e5a 1097
e7fcb7b2 1098It takes a subroutine reference as an argument. When the type
1099constraint is tested, the reference is run with the value to be tested
1100in C<$_>. This reference should return true or false to indicate
1101whether or not the constraint check passed.
e606ae5f 1102
e7fcb7b2 1103=item B<message { ... }>
76d37e5a 1104
1105This is just sugar for the type constraint construction syntax.
a15dff8d 1106
e7fcb7b2 1107It takes a subroutine reference as an argument. When the type
1108constraint fails, then the code block is run with the value provided
1109in C<$_>. This reference should return a string, which will be used in
1110the text of the exception thrown.
e606ae5f 1111
7142d232 1112=item B<inline_as { ... }>
1113
1114This can be used to define a "hand optimized" inlinable version of your type
1115constraint.
1116
1117You provide a subroutine which will be called I<as a method> on a
1118L<Moose::Meta::TypeConstraint> object. It will receive a single parameter, the
1119name of the variable to check, typically something like C<"$_"> or C<"$_[0]">.
1120
1121The subroutine should return a code string suitable for inlining. You can
297899d1 1122assume that the check will be wrapped in parentheses when it is inlined.
7142d232 1123
01062d8a 1124The inlined code should include any checks that your type's parent types
c25e79e8 1125do. If your parent type constraint defines its own inlining, you can simply use
6054adaf 1126that to avoid repeating code. For example, here is the inlining code for the
1127C<Value> type, which is a subtype of C<Defined>:
0578d5ce 1128
1129 sub {
1130 $_[0]->parent()->_inline_check($_[1])
1131 . ' && !ref(' . $_[1] . ')'
1132 }
7142d232 1133
e7fcb7b2 1134=item B<optimize_as { ... }>
8ecb1fa0 1135
7142d232 1136B<This feature is deprecated, use C<inline_as> instead.>
1137
e85d2a5d 1138This can be used to define a "hand optimized" version of your
d44714be 1139type constraint which can be used to avoid traversing a subtype
6549b0d1 1140constraint hierarchy.
d44714be 1141
b0f8f0ec 1142B<NOTE:> You should only use this if you know what you are doing.
1143All the built in types use this, so your subtypes (assuming they
d44714be 1144are shallow) will not likely need to use this.
1145
04eec387 1146=item B<< type 'Name', where { } ... >>
e7fcb7b2 1147
1148This creates a base type, which has no parent.
1149
1150The C<type> function should either be called with the sugar helpers
1151(C<where>, C<message>, etc), or with a name and a hashref of
1152parameters:
1153
1154 type( 'Foo', { where => ..., message => ... } );
1155
7142d232 1156The valid hashref keys are C<where>, C<message>, and C<inlined_as>.
e7fcb7b2 1157
6ba6d68c 1158=back
a15dff8d 1159
0d29b772 1160=head2 Type Constraint Utilities
1161
1162=over 4
1163
1164=item B<< match_on_type $value => ( $type => \&action, ... ?\&default ) >>
1165
1a15f4a8 1166This is a utility function for doing simple type based dispatching similar to
2ae1457e 1167match/case in OCaml and case/of in Haskell. It is not as featureful as those
1a15f4a8 1168languages, nor does not it support any kind of automatic destructuring
1169bind. Here is a simple Perl pretty printer dispatching over the core Moose
1170types.
0d29b772 1171
1172 sub ppprint {
1173 my $x = shift;
1a15f4a8 1174 match_on_type $x => (
1175 HashRef => sub {
0d29b772 1176 my $hash = shift;
1a15f4a8 1177 '{ '
1178 . (
1179 join ", " => map { $_ . ' => ' . ppprint( $hash->{$_} ) }
1180 sort keys %$hash
1181 ) . ' }';
1182 },
1183 ArrayRef => sub {
0d29b772 1184 my $array = shift;
1a15f4a8 1185 '[ ' . ( join ", " => map { ppprint($_) } @$array ) . ' ]';
1186 },
1187 CodeRef => sub {'sub { ... }'},
1188 RegexpRef => sub { 'qr/' . $_ . '/' },
1189 GlobRef => sub { '*' . B::svref_2object($_)->NAME },
0d29b772 1190 Object => sub { $_->can('to_string') ? $_->to_string : $_ },
1a15f4a8 1191 ScalarRef => sub { '\\' . ppprint( ${$_} ) },
1192 Num => sub {$_},
1193 Str => sub { '"' . $_ . '"' },
1194 Undef => sub {'undef'},
1195 => sub { die "I don't know what $_ is" }
1196 );
0d29b772 1197 }
1198
e7597637 1199Or a simple JSON serializer:
1200
1201 sub to_json {
1202 my $x = shift;
1a15f4a8 1203 match_on_type $x => (
1204 HashRef => sub {
e7597637 1205 my $hash = shift;
1a15f4a8 1206 '{ '
1207 . (
1208 join ", " =>
1209 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
1210 sort keys %$hash
1211 ) . ' }';
1212 },
1213 ArrayRef => sub {
e7597637 1214 my $array = shift;
1a15f4a8 1215 '[ ' . ( join ", " => map { to_json($_) } @$array ) . ' ]';
1216 },
1217 Num => sub {$_},
1218 Str => sub { '"' . $_ . '"' },
1219 Undef => sub {'null'},
1220 => sub { die "$_ is not acceptable json type" }
1221 );
e7597637 1222 }
1223
1a15f4a8 1224The matcher is done by mapping a C<$type> to an C<\&action>. The C<$type> can
1225be either a string type or a L<Moose::Meta::TypeConstraint> object, and
1226C<\&action> is a subroutine reference. This function will dispatch on the
1227first match for C<$value>. It is possible to have a catch-all by providing an
1228additional subroutine reference as the final argument to C<match_on_type>.
0d29b772 1229
1230=back
1231
6ba6d68c 1232=head2 Type Coercion Constructors
a15dff8d 1233
e7fcb7b2 1234You can define coercions for type constraints, which allow you to
1235automatically transform values to something valid for the type
1236constraint. If you ask your accessor to coerce, then Moose will run
1237the type-coercion code first, followed by the type constraint
1238check. This feature should be used carefully as it is very powerful
1239and could easily take off a limb if you are not careful.
a15dff8d 1240
cec39889 1241See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 1242
6ba6d68c 1243=over 4
a15dff8d 1244
04eec387 1245=item B<< coerce 'Name', from 'OtherName', via { ... } >>
a15dff8d 1246
e7fcb7b2 1247This defines a coercion from one type to another. The C<Name> argument
1248is the type you are coercing I<to>.
1249
f55dd47f 1250To define multiple coercions, supply more sets of from/via pairs:
1251
04eec387 1252 coerce 'Name',
1253 from 'OtherName', via { ... },
1254 from 'ThirdName', via { ... };
f55dd47f 1255
e7fcb7b2 1256=item B<from 'OtherName'>
a15dff8d 1257
6ba6d68c 1258This is just sugar for the type coercion construction syntax.
1259
e7fcb7b2 1260It takes a single type name (or type object), which is the type being
1261coerced I<from>.
1262
1263=item B<via { ... }>
a15dff8d 1264
6ba6d68c 1265This is just sugar for the type coercion construction syntax.
a15dff8d 1266
e7fcb7b2 1267It takes a subroutine reference. This reference will be called with
1268the value to be coerced in C<$_>. It is expected to return a new value
1269of the proper type for the coercion.
1270
a15dff8d 1271=back
1272
e7fcb7b2 1273=head2 Creating and Finding Type Constraints
1274
1275These are additional functions for creating and finding type
1276constraints. Most of these functions are not available for
1277importing. The ones that are importable as specified.
004222dc 1278
1279=over 4
1280
e7fcb7b2 1281=item B<find_type_constraint($type_name)>
eb4c4e82 1282
e7fcb7b2 1283This function can be used to locate the L<Moose::Meta::TypeConstraint>
1284object for a named type.
eb4c4e82 1285
e7fcb7b2 1286This function is importable.
004222dc 1287
e7fcb7b2 1288=item B<register_type_constraint($type_object)>
004222dc 1289
e7fcb7b2 1290This function will register a L<Moose::Meta::TypeConstraint> with the
1291global type registry.
004222dc 1292
e7fcb7b2 1293This function is importable.
004222dc 1294
e7fcb7b2 1295=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1296
e7fcb7b2 1297This method takes a type constraint name and returns the normalized
1298form. This removes any whitespace in the string.
004222dc 1299
e7fcb7b2 1300=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1301
2dae61ad 1302=item B<create_named_type_constraint_union($name, $pipe_separated_types | @type_constraint_names)>
1303
e7fcb7b2 1304This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1305or a list of names. It returns a new
1306L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1307
e7fcb7b2 1308=item B<create_parameterized_type_constraint($type_name)>
620db045 1309
e7fcb7b2 1310Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1311this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1312object. The C<BaseType> must exist already exist as a parameterizable
1313type.
620db045 1314
e7fcb7b2 1315=item B<create_class_type_constraint($class, $options)>
dabed765 1316
e7fcb7b2 1317Given a class name this function will create a new
1318L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1319
e7fcb7b2 1320The C<$options> is a hash reference that will be passed to the
1321L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1322
e7fcb7b2 1323=item B<create_role_type_constraint($role, $options)>
620db045 1324
e7fcb7b2 1325Given a role name this function will create a new
1326L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1327
e7fcb7b2 1328The C<$options> is a hash reference that will be passed to the
1329L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1330
8a6c8c47 1331=item B<create_enum_type_constraint($name, $values)>
1332
1333Given a enum name this function will create a new
1334L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1335
0a6bff54 1336=item B<create_duck_type_constraint($name, $methods)>
1337
1338Given a duck type name this function will create a new
1339L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
1340
e7fcb7b2 1341=item B<find_or_parse_type_constraint($type_name)>
620db045 1342
ec4b72d2 1343Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1344in the global registry.
620db045 1345
e7fcb7b2 1346If the type name is a union or parameterized type, it will create a
1347new object of the appropriate, but if given a "regular" type that does
1348not yet exist, it simply returns false.
620db045 1349
e7fcb7b2 1350When given a union or parameterized type, the member or base type must
1351already exist.
620db045 1352
e7fcb7b2 1353If it creates a new union or parameterized type, it will add it to the
1354global registry.
004222dc 1355
e7fcb7b2 1356=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1357
e7fcb7b2 1358=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1359
e7fcb7b2 1360These functions will first call C<find_or_parse_type_constraint>. If
72042ad7 1361that function does not return a type, a new type object will
e7fcb7b2 1362be created.
004222dc 1363
e7fcb7b2 1364The C<isa> variant will use C<create_class_type_constraint> and the
1365C<does> variant will use C<create_role_type_constraint>.
004222dc 1366
1367=item B<get_type_constraint_registry>
1368
e7fcb7b2 1369Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1370keeps track of all type constraints.
1371
1372=item B<list_all_type_constraints>
1373
e7fcb7b2 1374This will return a list of type constraint names in the global
1375registry. You can then fetch the actual type object using
1376C<find_type_constraint($type_name)>.
004222dc 1377
1378=item B<list_all_builtin_type_constraints>
1379
e7fcb7b2 1380This will return a list of builtin type constraints, meaning those
1381which are defined in this module. See the L<Default Type Constraints>
1382section for a complete list.
004222dc 1383
1384=item B<export_type_constraints_as_functions>
1385
e7fcb7b2 1386This will export all the current type constraints as functions into
1387the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1388mostly used for testing, but it might prove useful to others.
004222dc 1389
1390=item B<get_all_parameterizable_types>
1391
e7fcb7b2 1392This returns all the parameterizable types that have been registered,
1393as a list of type objects.
004222dc 1394
e7fcb7b2 1395=item B<add_parameterizable_type($type)>
004222dc 1396
1397Adds C<$type> to the list of parameterizable types
1398
1399=back
1400
a15dff8d 1401=head1 BUGS
1402
d4048ef3 1403See L<Moose/BUGS> for details on reporting bugs.
a15dff8d 1404
81dc201f 1405=cut