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