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