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