fixing stuff
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
4use strict;
5use warnings;
6
e90c03d0 7use Carp 'confess';
86629f93 8use Scalar::Util 'blessed', 'reftype';
571dd39f 9use B 'svref_2object';
10use Sub::Exporter;
a15dff8d 11
a0f8153d 12our $VERSION = '0.16';
d44714be 13our $AUTHORITY = 'cpan:STEVAN';
a15dff8d 14
d9b40005 15## --------------------------------------------------------
e85d2a5d 16# Prototyped subs must be predeclared because we have a
17# circular dependency with Moose::Meta::Attribute et. al.
18# so in case of us being use'd first the predeclaration
d9b40005 19# ensures the prototypes are in scope when consumers are
20# compiled.
21
22# creation and location
0fbd4b0a 23sub find_type_constraint ($);
24sub find_or_create_type_constraint ($;$);
25sub create_type_constraint_union (@);
26sub create_parameterized_type_constraint ($);
d9b40005 27
28# dah sugah!
29sub type ($$;$$);
30sub subtype ($$;$$$);
31sub coerce ($@);
32sub as ($);
33sub from ($);
34sub where (&);
35sub via (&);
36sub message (&);
37sub optimize_as (&);
38sub enum ($;@);
39
e85d2a5d 40## private stuff ...
d9b40005 41sub _create_type_constraint ($$$;$$);
42sub _install_type_coercions ($$);
43
44## --------------------------------------------------------
8c4acc60 45
4e036ee4 46use Moose::Meta::TypeConstraint;
3726f905 47use Moose::Meta::TypeConstraint::Union;
0fbd4b0a 48use Moose::Meta::TypeConstraint::Parameterized;
2ca63f5d 49use Moose::Meta::TypeCoercion;
3726f905 50use Moose::Meta::TypeCoercion::Union;
22aed3c0 51use Moose::Meta::TypeConstraint::Registry;
4e036ee4 52
571dd39f 53my @exports = qw/
8ecb1fa0 54 type subtype as where message optimize_as
e85d2a5d 55 coerce from via
571dd39f 56 enum
57 find_type_constraint
58/;
59
e85d2a5d 60Sub::Exporter::setup_exporter({
571dd39f 61 exports => \@exports,
62 groups => { default => [':all'] }
63});
64
65sub unimport {
e85d2a5d 66 no strict 'refs';
571dd39f 67 my $class = caller();
68 # loop through the exports ...
69 foreach my $name (@exports) {
70 # if we find one ...
71 if (defined &{$class . '::' . $name}) {
72 my $keyword = \&{$class . '::' . $name};
e85d2a5d 73
571dd39f 74 # make sure it is from Moose
75 my $pkg_name = eval { svref_2object($keyword)->GV->STASH->NAME };
76 next if $@;
77 next if $pkg_name ne 'Moose::Util::TypeConstraints';
e85d2a5d 78
571dd39f 79 # and if it is from Moose then undef the slot
80 delete ${$class . '::'}{$name};
81 }
2c0cbef7 82 }
571dd39f 83}
a15dff8d 84
d9b40005 85## --------------------------------------------------------
86## type registry and some useful functions for it
87## --------------------------------------------------------
88
22aed3c0 89my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
587ae0d2 90
d9b40005 91sub get_type_constraint_registry { $REGISTRY }
e85d2a5d 92sub list_all_type_constraints { keys %{$REGISTRY->type_constraints} }
d9b40005 93sub export_type_constraints_as_functions {
94 my $pkg = caller();
95 no strict 'refs';
a0f8153d 96 foreach my $constraint (keys %{$REGISTRY->type_constraints}) {
97 *{"${pkg}::${constraint}"} = $REGISTRY->get_type_constraint($constraint)
98 ->_compiled_type_constraint;
99 }
d9b40005 100}
182134e8 101
d9b40005 102sub create_type_constraint_union (@) {
103 my @type_constraint_names;
e85d2a5d 104
f1917f58 105 if (scalar @_ == 1 && _detect_type_constraint_union($_[0])) {
106 @type_constraint_names = _parse_type_constraint_union($_[0]);
d9b40005 107 }
108 else {
109 @type_constraint_names = @_;
429ccc11 110 }
e85d2a5d 111
3726f905 112 (scalar @type_constraint_names >= 2)
e85d2a5d 113 || confess "You must pass in at least 2 type names to make a union";
114
d9b40005 115 ($REGISTRY->has_type_constraint($_))
116 || confess "Could not locate type constraint ($_) for the union"
117 foreach @type_constraint_names;
e85d2a5d 118
3726f905 119 return Moose::Meta::TypeConstraint::Union->new(
120 type_constraints => [
e85d2a5d 121 map {
122 $REGISTRY->get_type_constraint($_)
123 } @type_constraint_names
3726f905 124 ],
e85d2a5d 125 );
182134e8 126}
a15dff8d 127
0fbd4b0a 128sub create_parameterized_type_constraint ($) {
d9b40005 129 my $type_constraint_name = shift;
e85d2a5d 130
0fbd4b0a 131 my ($base_type, $type_parameter) = _parse_parameterized_type_constraint($type_constraint_name);
e85d2a5d 132
0fbd4b0a 133 (defined $base_type && defined $type_parameter)
d9b40005 134 || confess "Could not parse type name ($type_constraint_name) correctly";
e85d2a5d 135
d9b40005 136 ($REGISTRY->has_type_constraint($base_type))
137 || confess "Could not locate the base type ($base_type)";
e85d2a5d 138
0fbd4b0a 139 return Moose::Meta::TypeConstraint::Parameterized->new(
d9b40005 140 name => $type_constraint_name,
141 parent => $REGISTRY->get_type_constraint($base_type),
0fbd4b0a 142 type_parameter => find_or_create_type_constraint(
143 $type_parameter => {
f1917f58 144 parent => $REGISTRY->get_type_constraint('Object'),
0fbd4b0a 145 constraint => sub { $_[0]->isa($type_parameter) }
f1917f58 146 }
147 ),
e85d2a5d 148 );
22aed3c0 149}
150
d9b40005 151sub find_or_create_type_constraint ($;$) {
152 my ($type_constraint_name, $options_for_anon_type) = @_;
e85d2a5d 153
d9b40005 154 return $REGISTRY->get_type_constraint($type_constraint_name)
155 if $REGISTRY->has_type_constraint($type_constraint_name);
e85d2a5d 156
d9b40005 157 my $constraint;
e85d2a5d 158
f1917f58 159 if (_detect_type_constraint_union($type_constraint_name)) {
d9b40005 160 $constraint = create_type_constraint_union($type_constraint_name);
161 }
0fbd4b0a 162 elsif (_detect_parameterized_type_constraint($type_constraint_name)) {
e85d2a5d 163 $constraint = create_parameterized_type_constraint($type_constraint_name);
d9b40005 164 }
165 else {
166 # NOTE:
167 # otherwise assume that we should create
e85d2a5d 168 # an ANON type with the $options_for_anon_type
d9b40005 169 # options which can be passed in. It should
e85d2a5d 170 # be noted that these don't get registered
d9b40005 171 # so we need to return it.
172 # - SL
173 return Moose::Meta::TypeConstraint->new(
174 name => '__ANON__',
e85d2a5d 175 %{$options_for_anon_type}
d9b40005 176 );
177 }
e85d2a5d 178
d9b40005 179 $REGISTRY->add_type_constraint($constraint);
e85d2a5d 180 return $constraint;
d9b40005 181}
22aed3c0 182
183## --------------------------------------------------------
184## exported functions ...
185## --------------------------------------------------------
186
187sub find_type_constraint ($) { $REGISTRY->get_type_constraint(@_) }
188
7c13858b 189# type constructors
a15dff8d 190
815ec671 191sub type ($$;$$) {
1b7df21f 192 splice(@_, 1, 0, undef);
a0f8153d 193 goto &_create_type_constraint;
a15dff8d 194}
195
8ecb1fa0 196sub subtype ($$;$$$) {
86629f93 197 # NOTE:
198 # this adds an undef for the name
199 # if this is an anon-subtype:
200 # subtype(Num => where { $_ % 2 == 0 }) # anon 'even' subtype
201 # but if the last arg is not a code
202 # ref then it is a subtype alias:
203 # subtype(MyNumbers => as Num); # now MyNumbers is the same as Num
e85d2a5d 204 # ... yeah I know it's ugly code
86629f93 205 # - SL
a0f8153d 206 unshift @_ => undef if scalar @_ <= 2 && (reftype($_[1]) || '') eq 'CODE';
207 goto &_create_type_constraint;
a15dff8d 208}
209
4b598ea3 210sub coerce ($@) {
e85d2a5d 211 my ($type_name, @coercion_map) = @_;
7c13858b 212 _install_type_coercions($type_name, \@coercion_map);
182134e8 213}
214
76d37e5a 215sub as ($) { $_[0] }
216sub from ($) { $_[0] }
217sub where (&) { $_[0] }
218sub via (&) { $_[0] }
8ecb1fa0 219
220sub message (&) { +{ message => $_[0] } }
221sub optimize_as (&) { +{ optimized => $_[0] } }
a15dff8d 222
2c0cbef7 223sub enum ($;@) {
fcec2383 224 my ($type_name, @values) = @_;
2c0cbef7 225 (scalar @values >= 2)
226 || confess "You must have at least two values to enumerate through";
c4fe165f 227 my %valid = map { $_ => 1 } @values;
a0f8153d 228 _create_type_constraint(
229 $type_name,
230 'Str',
231 sub { $valid{$_} }
232 );
fcec2383 233}
234
d9b40005 235## --------------------------------------------------------
236## desugaring functions ...
237## --------------------------------------------------------
238
e85d2a5d 239sub _create_type_constraint ($$$;$$) {
d9b40005 240 my $name = shift;
241 my $parent = shift;
242 my $check = shift || sub { 1 };
e85d2a5d 243
d9b40005 244 my ($message, $optimized);
245 for (@_) {
246 $message = $_->{message} if exists $_->{message};
e85d2a5d 247 $optimized = $_->{optimized} if exists $_->{optimized};
d9b40005 248 }
249
250 my $pkg_defined_in = scalar(caller(0));
e85d2a5d 251
d9b40005 252 if (defined $name) {
253 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 254
d9b40005 255 ($type->_package_defined_in eq $pkg_defined_in)
e85d2a5d 256 || confess ("The type constraint '$name' has already been created in "
d9b40005 257 . $type->_package_defined_in . " and cannot be created again in "
258 . $pkg_defined_in)
e85d2a5d 259 if defined $type;
260 }
261
a0f8153d 262 $parent = find_or_create_type_constraint($parent) if defined $parent;
e85d2a5d 263
d9b40005 264 my $constraint = Moose::Meta::TypeConstraint->new(
265 name => $name || '__ANON__',
d9b40005 266 package_defined_in => $pkg_defined_in,
e85d2a5d 267
268 ($parent ? (parent => $parent ) : ()),
269 ($check ? (constraint => $check) : ()),
270 ($message ? (message => $message) : ()),
271 ($optimized ? (optimized => $optimized) : ()),
d9b40005 272 );
273
274 $REGISTRY->add_type_constraint($constraint)
275 if defined $name;
276
277 return $constraint;
278}
279
e85d2a5d 280sub _install_type_coercions ($$) {
d9b40005 281 my ($type_name, $coercion_map) = @_;
282 my $type = $REGISTRY->get_type_constraint($type_name);
283 (!$type->has_coercion)
e85d2a5d 284 || confess "The type coercion for '$type_name' has already been registered";
d9b40005 285 my $type_coercion = Moose::Meta::TypeCoercion->new(
286 type_coercion_map => $coercion_map,
287 type_constraint => $type
e85d2a5d 288 );
d9b40005 289 $type->coercion($type_coercion);
290}
291
292## --------------------------------------------------------
f1917f58 293## type notation parsing ...
294## --------------------------------------------------------
295
296{
e85d2a5d 297 # All I have to say is mugwump++ cause I know
298 # do not even have enough regexp-fu to be able
299 # to have written this (I can only barely
f1917f58 300 # understand it as it is)
e85d2a5d 301 # - SL
302
f1917f58 303 use re "eval";
304
3796382a 305 my $valid_chars = qr{[\w:]};
f1917f58 306 my $type_atom = qr{ $valid_chars+ };
307
308 my $type = qr{ $valid_chars+ (?: \[ (??{$any}) \] )? }x;
309 my $type_capture_parts = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
310 my $type_with_parameter = qr{ $valid_chars+ \[ (??{$any}) \] }x;
311
3796382a 312 my $op_union = qr{ \s* \| \s* }x;
f1917f58 313 my $union = qr{ $type (?: $op_union $type )+ }x;
314
315 our $any = qr{ $type | $union }x;
316
0fbd4b0a 317 sub _parse_parameterized_type_constraint {
e85d2a5d 318 $_[0] =~ m{ $type_capture_parts }x;
319 return ($1, $2);
f1917f58 320 }
321
0fbd4b0a 322 sub _detect_parameterized_type_constraint {
e85d2a5d 323 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 324 }
325
326 sub _parse_type_constraint_union {
e85d2a5d 327 my $given = shift;
328 my @rv;
329 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
330 push @rv => $1;
331 }
332 (pos($given) eq length($given))
333 || confess "'$given' didn't parse (parse-pos="
334 . pos($given)
335 . " and str-length="
336 . length($given)
337 . ")";
338 @rv;
f1917f58 339 }
340
341 sub _detect_type_constraint_union {
e85d2a5d 342 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 343 }
344}
345
346## --------------------------------------------------------
d9b40005 347# define some basic built-in types
348## --------------------------------------------------------
a15dff8d 349
f65cb534 350type 'Any' => where { 1 }; # meta-type including all
e85d2a5d 351type 'Item' => where { 1 }; # base-type
a15dff8d 352
f65cb534 353subtype 'Undef' => as 'Item' => where { !defined($_) };
354subtype 'Defined' => as 'Item' => where { defined($_) };
a15dff8d 355
8ecb1fa0 356subtype 'Bool'
e85d2a5d 357 => as 'Item'
8ecb1fa0 358 => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
5a4c5493 359
e85d2a5d 360subtype 'Value'
361 => as 'Defined'
362 => where { !ref($_) }
8ecb1fa0 363 => optimize_as { defined($_[0]) && !ref($_[0]) };
e85d2a5d 364
8ecb1fa0 365subtype 'Ref'
e85d2a5d 366 => as 'Defined'
367 => where { ref($_) }
8ecb1fa0 368 => optimize_as { ref($_[0]) };
369
e85d2a5d 370subtype 'Str'
371 => as 'Value'
372 => where { 1 }
8ecb1fa0 373 => optimize_as { defined($_[0]) && !ref($_[0]) };
374
e85d2a5d 375subtype 'Num'
376 => as 'Value'
377 => where { Scalar::Util::looks_like_number($_) }
8ecb1fa0 378 => optimize_as { !ref($_[0]) && Scalar::Util::looks_like_number($_[0]) };
e85d2a5d 379
380subtype 'Int'
381 => as 'Num'
8ecb1fa0 382 => where { "$_" =~ /^-?[0-9]+$/ }
383 => optimize_as { defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ };
384
385subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as { ref($_[0]) eq 'SCALAR' };
386subtype 'ArrayRef' => as 'Ref' => where { ref($_) eq 'ARRAY' } => optimize_as { ref($_[0]) eq 'ARRAY' };
e85d2a5d 387subtype 'HashRef' => as 'Ref' => where { ref($_) eq 'HASH' } => optimize_as { ref($_[0]) eq 'HASH' };
8ecb1fa0 388subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' } => optimize_as { ref($_[0]) eq 'CODE' };
e85d2a5d 389subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as { ref($_[0]) eq 'Regexp' };
8ecb1fa0 390subtype 'GlobRef' => as 'Ref' => where { ref($_) eq 'GLOB' } => optimize_as { ref($_[0]) eq 'GLOB' };
a15dff8d 391
0a5bd159 392# NOTE:
e85d2a5d 393# scalar filehandles are GLOB refs,
0a5bd159 394# but a GLOB ref is not always a filehandle
e85d2a5d 395subtype 'FileHandle'
396 => as 'GlobRef'
8ecb1fa0 397 => where { Scalar::Util::openhandle($_) }
398 => optimize_as { ref($_[0]) eq 'GLOB' && Scalar::Util::openhandle($_[0]) };
0a5bd159 399
e85d2a5d 400# NOTE:
a15dff8d 401# blessed(qr/.../) returns true,.. how odd
e85d2a5d 402subtype 'Object'
403 => as 'Ref'
8ecb1fa0 404 => where { blessed($_) && blessed($_) ne 'Regexp' }
405 => optimize_as { blessed($_[0]) && blessed($_[0]) ne 'Regexp' };
a15dff8d 406
e85d2a5d 407subtype 'Role'
408 => as 'Object'
8ecb1fa0 409 => where { $_->can('does') }
410 => optimize_as { blessed($_[0]) && $_[0]->can('does') };
e85d2a5d 411
0e0709ea 412my $_class_name_checker = sub {
413 return if ref($_[0]);
414 return unless defined($_[0]) && length($_[0]);
415
416 # walk the symbol table tree to avoid autovififying
417 # \*{${main::}{"Foo::"}} == \*main::Foo::
418
419 my $pack = \*::;
420 foreach my $part (split('::', $_[0])) {
421 return unless exists ${$$pack}{"${part}::"};
422 $pack = \*{${$$pack}{"${part}::"}};
423 }
424
425 # check for $VERSION or @ISA
426 return 1 if exists ${$$pack}{VERSION}
427 && defined *{${$$pack}{VERSION}}{SCALAR};
428 return 1 if exists ${$$pack}{ISA}
429 && defined *{${$$pack}{ISA}}{ARRAY};
430
431 # check for any method
432 foreach ( keys %{$$pack} ) {
433 next if substr($_, -2, 2) eq '::';
434 return 1 if defined *{${$$pack}{$_}}{CODE};
435 }
436
437 # fail
438 return;
439};
440
e85d2a5d 441subtype 'ClassName'
442 => as 'Str'
0e0709ea 443 => $_class_name_checker # where ...
444 => { optimize => $_class_name_checker };
02a0fb52 445
d9b40005 446## --------------------------------------------------------
447# end of built-in types ...
448## --------------------------------------------------------
449
943596a6 450{
451 my @BUILTINS = list_all_type_constraints();
452 sub list_all_builtin_type_constraints { @BUILTINS }
453}
454
a15dff8d 4551;
456
457__END__
458
459=pod
460
461=head1 NAME
462
e522431d 463Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 464
465=head1 SYNOPSIS
466
467 use Moose::Util::TypeConstraints;
468
2c0cbef7 469 type 'Num' => where { Scalar::Util::looks_like_number($_) };
e85d2a5d 470
471 subtype 'Natural'
472 => as 'Num'
a15dff8d 473 => where { $_ > 0 };
e85d2a5d 474
475 subtype 'NaturalLessThanTen'
2c0cbef7 476 => as 'Natural'
79592a54 477 => where { $_ < 10 }
478 => message { "This number ($_) is not less than ten!" };
e85d2a5d 479
480 coerce 'Num'
2c0cbef7 481 => from 'Str'
e85d2a5d 482 => via { 0+$_ };
483
2c0cbef7 484 enum 'RGBColors' => qw(red green blue);
a15dff8d 485
486=head1 DESCRIPTION
487
e85d2a5d 488This module provides Moose with the ability to create custom type
489contraints to be used in attribute definition.
e522431d 490
6ba6d68c 491=head2 Important Caveat
492
e85d2a5d 493This is B<NOT> a type system for Perl 5. These are type constraints,
494and they are not used by Moose unless you tell it to. No type
495inference is performed, expression are not typed, etc. etc. etc.
6ba6d68c 496
e85d2a5d 497This is simply a means of creating small constraint functions which
a7d0cd00 498can be used to simplify your own type-checking code.
6ba6d68c 499
2c0cbef7 500=head2 Slightly Less Important Caveat
501
e85d2a5d 502It is almost always a good idea to quote your type and subtype names.
503This is to prevent perl from trying to execute the call as an indirect
2c0cbef7 504object call. This issue only seems to come up when you have a subtype
e85d2a5d 505the same name as a valid class, but when the issue does arise it tends
506to be quite annoying to debug.
2c0cbef7 507
508So for instance, this:
e85d2a5d 509
2c0cbef7 510 subtype DateTime => as Object => where { $_->isa('DateTime') };
511
512will I<Just Work>, while this:
513
514 use DateTime;
515 subtype DateTime => as Object => where { $_->isa('DateTime') };
516
e85d2a5d 517will fail silently and cause many headaches. The simple way to solve
518this, as well as future proof your subtypes from classes which have
2c0cbef7 519yet to have been created yet, is to simply do this:
520
521 use DateTime;
d44714be 522 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
2c0cbef7 523
6ba6d68c 524=head2 Default Type Constraints
e522431d 525
e85d2a5d 526This module also provides a simple hierarchy for Perl 5 types, this
e522431d 527could probably use some work, but it works for me at the moment.
528
529 Any
e85d2a5d 530 Item
5a4c5493 531 Bool
f65cb534 532 Undef
533 Defined
5a4c5493 534 Value
535 Num
536 Int
537 Str
9af1d28b 538 ClassName
5a4c5493 539 Ref
540 ScalarRef
451c8248 541 ArrayRef
542 HashRef
5a4c5493 543 CodeRef
544 RegexpRef
3f7376b0 545 GlobRef
0a5bd159 546 FileHandle
e85d2a5d 547 Object
5a4c5493 548 Role
e522431d 549
6ba6d68c 550Suggestions for improvement are welcome.
2c0cbef7 551
e85d2a5d 552B<NOTE:> The C<Undef> type constraint does not work correctly
2c0cbef7 553in every occasion, please use it sparringly.
703e92fb 554
e85d2a5d 555B<NOTE:> The C<ClassName> type constraint is simply a subtype
9af1d28b 556of string which responds true to C<isa('UNIVERSAL')>. This means
e85d2a5d 557that your class B<must> be loaded for this type constraint to
558pass. I know this is not ideal for all, but it is a saner
559restriction than most others.
9af1d28b 560
703e92fb 561=head2 Use with Other Constraint Modules
562
e85d2a5d 563This module should play fairly nicely with other constraint
564modules with only some slight tweaking. The C<where> clause
703e92fb 565in types is expected to be a C<CODE> reference which checks
566it's first argument and returns a bool. Since most constraint
e85d2a5d 567modules work in a similar way, it should be simple to adapt
703e92fb 568them to work with Moose.
569
e85d2a5d 570For instance, this is how you could use it with
571L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 572
e85d2a5d 573 type 'HashOfArrayOfObjects'
703e92fb 574 => IsHashRef(
575 -keys => HasLength,
576 -values => IsArrayRef( IsObject ));
577
578For more examples see the F<t/204_example_w_DCS.t> test file.
579
e85d2a5d 580Here is an example of using L<Test::Deep> and it's non-test
581related C<eq_deeply> function.
703e92fb 582
e85d2a5d 583 type 'ArrayOfHashOfBarsAndRandomNumbers'
703e92fb 584 => where {
e85d2a5d 585 eq_deeply($_,
703e92fb 586 array_each(subhashof({
587 bar => isa('Bar'),
588 random_number => ignore()
e85d2a5d 589 })))
703e92fb 590 };
591
e85d2a5d 592For a complete example see the F<t/205_example_w_TestDeep.t>
593test file.
594
a15dff8d 595=head1 FUNCTIONS
596
d9b40005 597=head2 Type Constraint Construction & Locating
182134e8 598
599=over 4
600
d9b40005 601=item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
182134e8 602
e85d2a5d 603Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
d9b40005 604this will return a L<Moose::Meta::TypeConstraint::Union> instance.
182134e8 605
0fbd4b0a 606=item B<create_parameterized_type_constraint ($type_name)>
c07af9d2 607
d9b40005 608Given a C<$type_name> in the form of:
c07af9d2 609
d9b40005 610 BaseType[ContainerType]
182134e8 611
e85d2a5d 612this will extract the base type and container type and build an instance of
0fbd4b0a 613L<Moose::Meta::TypeConstraint::Parameterized> for it.
d9b40005 614
615=item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
6ba6d68c 616
e85d2a5d 617This will attempt to find or create a type constraint given the a C<$type_name>.
618If it cannot find it in the registry, it will see if it should be a union or
619container type an create one if appropriate, and lastly if nothing can be
620found or created that way, it will create an anon-type using the
d9b40005 621C<$options_for_anon_type> HASH ref to populate it.
429ccc11 622
d9b40005 623=item B<find_type_constraint ($type_name)>
624
625This function can be used to locate a specific type constraint
626meta-object, of the class L<Moose::Meta::TypeConstraint> or a
627derivative. What you do with it from there is up to you :)
628
629=item B<get_type_constraint_registry>
630
e85d2a5d 631Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
d9b40005 632keeps track of all type constraints.
429ccc11 633
b1e01e3c 634=item B<list_all_type_constraints>
635
e85d2a5d 636This will return a list of type constraint names, you can then
637fetch them using C<find_type_constraint ($type_name)> if you
b1e01e3c 638want to.
639
943596a6 640=item B<list_all_builtin_type_constraints>
641
e85d2a5d 642This will return a list of builtin type constraints, meaning,
643those which are defined in this module. See the section
943596a6 644labeled L<Default Type Constraints> for a complete list.
645
d9b40005 646=item B<export_type_constraints_as_functions>
647
e85d2a5d 648This will export all the current type constraints as functions
649into the caller's namespace. Right now, this is mostly used for
d9b40005 650testing, but it might prove useful to others.
651
182134e8 652=back
653
a15dff8d 654=head2 Type Constraint Constructors
655
e85d2a5d 656The following functions are used to create type constraints.
657They will then register the type constraints in a global store
658where Moose can get to them if it needs to.
a15dff8d 659
25f2c3fc 660See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 661
6ba6d68c 662=over 4
a15dff8d 663
6ba6d68c 664=item B<type ($name, $where_clause)>
a15dff8d 665
e85d2a5d 666This creates a base type, which has no parent.
a15dff8d 667
79592a54 668=item B<subtype ($name, $parent, $where_clause, ?$message)>
182134e8 669
e85d2a5d 670This creates a named subtype.
d6e2d9a1 671
79592a54 672=item B<subtype ($parent, $where_clause, ?$message)>
182134e8 673
e85d2a5d 674This creates an unnamed subtype and will return the type
675constraint meta-object, which will be an instance of
676L<Moose::Meta::TypeConstraint>.
a15dff8d 677
fcec2383 678=item B<enum ($name, @values)>
679
e85d2a5d 680This will create a basic subtype for a given set of strings.
681The resulting constraint will be a subtype of C<Str> and
4ce56d04 682will match any of the items in C<@values>. It is case sensitive.
683See the L<SYNOPSIS> for a simple example.
2c0cbef7 684
e85d2a5d 685B<NOTE:> This is not a true proper enum type, it is simple
2c0cbef7 686a convient constraint builder.
687
6ba6d68c 688=item B<as>
a15dff8d 689
6ba6d68c 690This is just sugar for the type constraint construction syntax.
a15dff8d 691
6ba6d68c 692=item B<where>
a15dff8d 693
6ba6d68c 694This is just sugar for the type constraint construction syntax.
76d37e5a 695
696=item B<message>
697
698This is just sugar for the type constraint construction syntax.
a15dff8d 699
8ecb1fa0 700=item B<optimize_as>
701
e85d2a5d 702This can be used to define a "hand optimized" version of your
d44714be 703type constraint which can be used to avoid traversing a subtype
e85d2a5d 704constraint heirarchy.
d44714be 705
e85d2a5d 706B<NOTE:> You should only use this if you know what you are doing,
707all the built in types use this, so your subtypes (assuming they
d44714be 708are shallow) will not likely need to use this.
709
6ba6d68c 710=back
a15dff8d 711
6ba6d68c 712=head2 Type Coercion Constructors
a15dff8d 713
e85d2a5d 714Type constraints can also contain type coercions as well. If you
715ask your accessor to coerce, then Moose will run the type-coercion
716code first, followed by the type constraint check. This feature
717should be used carefully as it is very powerful and could easily
587ae0d2 718take off a limb if you are not careful.
a15dff8d 719
25f2c3fc 720See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 721
6ba6d68c 722=over 4
a15dff8d 723
6ba6d68c 724=item B<coerce>
a15dff8d 725
6ba6d68c 726=item B<from>
a15dff8d 727
6ba6d68c 728This is just sugar for the type coercion construction syntax.
729
730=item B<via>
a15dff8d 731
6ba6d68c 732This is just sugar for the type coercion construction syntax.
a15dff8d 733
734=back
735
571dd39f 736=head2 Namespace Management
737
738=over 4
739
740=item B<unimport>
741
e85d2a5d 742This will remove all the type constraint keywords from the
571dd39f 743calling class namespace.
744
745=back
746
a15dff8d 747=head1 BUGS
748
e85d2a5d 749All complex software has bugs lurking in it, and this module is no
a15dff8d 750exception. If you find a bug please either email me, or add the bug
751to cpan-RT.
752
a15dff8d 753=head1 AUTHOR
754
755Stevan Little E<lt>stevan@iinteractive.comE<gt>
756
757=head1 COPYRIGHT AND LICENSE
758
b77fdbed 759Copyright 2006, 2007 by Infinity Interactive, Inc.
a15dff8d 760
761L<http://www.iinteractive.com>
762
763This library is free software; you can redistribute it and/or modify
e85d2a5d 764it under the same terms as Perl itself.
a15dff8d 765
81dc201f 766=cut