last fix so far
[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
3796382a 12our $VERSION = '0.15';
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';
e85d2a5d 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);
e85d2a5d 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
e85d2a5d 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;
e85d2a5d 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
d9b40005 262 $parent = $REGISTRY->get_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
412subtype 'ClassName'
413 => as 'Str'
9af1d28b 414 => where { eval { $_->isa('UNIVERSAL') } }
e85d2a5d 415 => optimize_as { !ref($_[0]) && eval { $_[0]->isa('UNIVERSAL') } };
02a0fb52 416
d9b40005 417## --------------------------------------------------------
418# end of built-in types ...
419## --------------------------------------------------------
420
943596a6 421{
422 my @BUILTINS = list_all_type_constraints();
423 sub list_all_builtin_type_constraints { @BUILTINS }
424}
425
a15dff8d 4261;
427
428__END__
429
430=pod
431
432=head1 NAME
433
e522431d 434Moose::Util::TypeConstraints - Type constraint system for Moose
a15dff8d 435
436=head1 SYNOPSIS
437
438 use Moose::Util::TypeConstraints;
439
2c0cbef7 440 type 'Num' => where { Scalar::Util::looks_like_number($_) };
e85d2a5d 441
442 subtype 'Natural'
443 => as 'Num'
a15dff8d 444 => where { $_ > 0 };
e85d2a5d 445
446 subtype 'NaturalLessThanTen'
2c0cbef7 447 => as 'Natural'
79592a54 448 => where { $_ < 10 }
449 => message { "This number ($_) is not less than ten!" };
e85d2a5d 450
451 coerce 'Num'
2c0cbef7 452 => from 'Str'
e85d2a5d 453 => via { 0+$_ };
454
2c0cbef7 455 enum 'RGBColors' => qw(red green blue);
a15dff8d 456
457=head1 DESCRIPTION
458
e85d2a5d 459This module provides Moose with the ability to create custom type
460contraints to be used in attribute definition.
e522431d 461
6ba6d68c 462=head2 Important Caveat
463
e85d2a5d 464This is B<NOT> a type system for Perl 5. These are type constraints,
465and they are not used by Moose unless you tell it to. No type
466inference is performed, expression are not typed, etc. etc. etc.
6ba6d68c 467
e85d2a5d 468This is simply a means of creating small constraint functions which
a7d0cd00 469can be used to simplify your own type-checking code.
6ba6d68c 470
2c0cbef7 471=head2 Slightly Less Important Caveat
472
e85d2a5d 473It is almost always a good idea to quote your type and subtype names.
474This is to prevent perl from trying to execute the call as an indirect
2c0cbef7 475object call. This issue only seems to come up when you have a subtype
e85d2a5d 476the same name as a valid class, but when the issue does arise it tends
477to be quite annoying to debug.
2c0cbef7 478
479So for instance, this:
e85d2a5d 480
2c0cbef7 481 subtype DateTime => as Object => where { $_->isa('DateTime') };
482
483will I<Just Work>, while this:
484
485 use DateTime;
486 subtype DateTime => as Object => where { $_->isa('DateTime') };
487
e85d2a5d 488will fail silently and cause many headaches. The simple way to solve
489this, as well as future proof your subtypes from classes which have
2c0cbef7 490yet to have been created yet, is to simply do this:
491
492 use DateTime;
d44714be 493 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
2c0cbef7 494
6ba6d68c 495=head2 Default Type Constraints
e522431d 496
e85d2a5d 497This module also provides a simple hierarchy for Perl 5 types, this
e522431d 498could probably use some work, but it works for me at the moment.
499
500 Any
e85d2a5d 501 Item
5a4c5493 502 Bool
f65cb534 503 Undef
504 Defined
5a4c5493 505 Value
506 Num
507 Int
508 Str
9af1d28b 509 ClassName
5a4c5493 510 Ref
511 ScalarRef
451c8248 512 ArrayRef
513 HashRef
5a4c5493 514 CodeRef
515 RegexpRef
3f7376b0 516 GlobRef
0a5bd159 517 FileHandle
e85d2a5d 518 Object
5a4c5493 519 Role
e522431d 520
6ba6d68c 521Suggestions for improvement are welcome.
2c0cbef7 522
e85d2a5d 523B<NOTE:> The C<Undef> type constraint does not work correctly
2c0cbef7 524in every occasion, please use it sparringly.
703e92fb 525
e85d2a5d 526B<NOTE:> The C<ClassName> type constraint is simply a subtype
9af1d28b 527of string which responds true to C<isa('UNIVERSAL')>. This means
e85d2a5d 528that your class B<must> be loaded for this type constraint to
529pass. I know this is not ideal for all, but it is a saner
530restriction than most others.
9af1d28b 531
703e92fb 532=head2 Use with Other Constraint Modules
533
e85d2a5d 534This module should play fairly nicely with other constraint
535modules with only some slight tweaking. The C<where> clause
703e92fb 536in types is expected to be a C<CODE> reference which checks
537it's first argument and returns a bool. Since most constraint
e85d2a5d 538modules work in a similar way, it should be simple to adapt
703e92fb 539them to work with Moose.
540
e85d2a5d 541For instance, this is how you could use it with
542L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 543
e85d2a5d 544 type 'HashOfArrayOfObjects'
703e92fb 545 => IsHashRef(
546 -keys => HasLength,
547 -values => IsArrayRef( IsObject ));
548
549For more examples see the F<t/204_example_w_DCS.t> test file.
550
e85d2a5d 551Here is an example of using L<Test::Deep> and it's non-test
552related C<eq_deeply> function.
703e92fb 553
e85d2a5d 554 type 'ArrayOfHashOfBarsAndRandomNumbers'
703e92fb 555 => where {
e85d2a5d 556 eq_deeply($_,
703e92fb 557 array_each(subhashof({
558 bar => isa('Bar'),
559 random_number => ignore()
e85d2a5d 560 })))
703e92fb 561 };
562
e85d2a5d 563For a complete example see the F<t/205_example_w_TestDeep.t>
564test file.
565
a15dff8d 566=head1 FUNCTIONS
567
d9b40005 568=head2 Type Constraint Construction & Locating
182134e8 569
570=over 4
571
d9b40005 572=item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
182134e8 573
e85d2a5d 574Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
d9b40005 575this will return a L<Moose::Meta::TypeConstraint::Union> instance.
182134e8 576
0fbd4b0a 577=item B<create_parameterized_type_constraint ($type_name)>
c07af9d2 578
d9b40005 579Given a C<$type_name> in the form of:
c07af9d2 580
d9b40005 581 BaseType[ContainerType]
182134e8 582
e85d2a5d 583this will extract the base type and container type and build an instance of
0fbd4b0a 584L<Moose::Meta::TypeConstraint::Parameterized> for it.
d9b40005 585
586=item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
6ba6d68c 587
e85d2a5d 588This will attempt to find or create a type constraint given the a C<$type_name>.
589If it cannot find it in the registry, it will see if it should be a union or
590container type an create one if appropriate, and lastly if nothing can be
591found or created that way, it will create an anon-type using the
d9b40005 592C<$options_for_anon_type> HASH ref to populate it.
429ccc11 593
d9b40005 594=item B<find_type_constraint ($type_name)>
595
596This function can be used to locate a specific type constraint
597meta-object, of the class L<Moose::Meta::TypeConstraint> or a
598derivative. What you do with it from there is up to you :)
599
600=item B<get_type_constraint_registry>
601
e85d2a5d 602Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
d9b40005 603keeps track of all type constraints.
429ccc11 604
b1e01e3c 605=item B<list_all_type_constraints>
606
e85d2a5d 607This will return a list of type constraint names, you can then
608fetch them using C<find_type_constraint ($type_name)> if you
b1e01e3c 609want to.
610
943596a6 611=item B<list_all_builtin_type_constraints>
612
e85d2a5d 613This will return a list of builtin type constraints, meaning,
614those which are defined in this module. See the section
943596a6 615labeled L<Default Type Constraints> for a complete list.
616
d9b40005 617=item B<export_type_constraints_as_functions>
618
e85d2a5d 619This will export all the current type constraints as functions
620into the caller's namespace. Right now, this is mostly used for
d9b40005 621testing, but it might prove useful to others.
622
182134e8 623=back
624
a15dff8d 625=head2 Type Constraint Constructors
626
e85d2a5d 627The following functions are used to create type constraints.
628They will then register the type constraints in a global store
629where Moose can get to them if it needs to.
a15dff8d 630
25f2c3fc 631See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 632
6ba6d68c 633=over 4
a15dff8d 634
6ba6d68c 635=item B<type ($name, $where_clause)>
a15dff8d 636
e85d2a5d 637This creates a base type, which has no parent.
a15dff8d 638
79592a54 639=item B<subtype ($name, $parent, $where_clause, ?$message)>
182134e8 640
e85d2a5d 641This creates a named subtype.
d6e2d9a1 642
79592a54 643=item B<subtype ($parent, $where_clause, ?$message)>
182134e8 644
e85d2a5d 645This creates an unnamed subtype and will return the type
646constraint meta-object, which will be an instance of
647L<Moose::Meta::TypeConstraint>.
a15dff8d 648
fcec2383 649=item B<enum ($name, @values)>
650
e85d2a5d 651This will create a basic subtype for a given set of strings.
652The resulting constraint will be a subtype of C<Str> and
4ce56d04 653will match any of the items in C<@values>. It is case sensitive.
654See the L<SYNOPSIS> for a simple example.
2c0cbef7 655
e85d2a5d 656B<NOTE:> This is not a true proper enum type, it is simple
2c0cbef7 657a convient constraint builder.
658
6ba6d68c 659=item B<as>
a15dff8d 660
6ba6d68c 661This is just sugar for the type constraint construction syntax.
a15dff8d 662
6ba6d68c 663=item B<where>
a15dff8d 664
6ba6d68c 665This is just sugar for the type constraint construction syntax.
76d37e5a 666
667=item B<message>
668
669This is just sugar for the type constraint construction syntax.
a15dff8d 670
8ecb1fa0 671=item B<optimize_as>
672
e85d2a5d 673This can be used to define a "hand optimized" version of your
d44714be 674type constraint which can be used to avoid traversing a subtype
e85d2a5d 675constraint heirarchy.
d44714be 676
e85d2a5d 677B<NOTE:> You should only use this if you know what you are doing,
678all the built in types use this, so your subtypes (assuming they
d44714be 679are shallow) will not likely need to use this.
680
6ba6d68c 681=back
a15dff8d 682
6ba6d68c 683=head2 Type Coercion Constructors
a15dff8d 684
e85d2a5d 685Type constraints can also contain type coercions as well. If you
686ask your accessor to coerce, then Moose will run the type-coercion
687code first, followed by the type constraint check. This feature
688should be used carefully as it is very powerful and could easily
587ae0d2 689take off a limb if you are not careful.
a15dff8d 690
25f2c3fc 691See the L<SYNOPSIS> for an example of how to use these.
a15dff8d 692
6ba6d68c 693=over 4
a15dff8d 694
6ba6d68c 695=item B<coerce>
a15dff8d 696
6ba6d68c 697=item B<from>
a15dff8d 698
6ba6d68c 699This is just sugar for the type coercion construction syntax.
700
701=item B<via>
a15dff8d 702
6ba6d68c 703This is just sugar for the type coercion construction syntax.
a15dff8d 704
705=back
706
571dd39f 707=head2 Namespace Management
708
709=over 4
710
711=item B<unimport>
712
e85d2a5d 713This will remove all the type constraint keywords from the
571dd39f 714calling class namespace.
715
716=back
717
a15dff8d 718=head1 BUGS
719
e85d2a5d 720All complex software has bugs lurking in it, and this module is no
a15dff8d 721exception. If you find a bug please either email me, or add the bug
722to cpan-RT.
723
a15dff8d 724=head1 AUTHOR
725
726Stevan Little E<lt>stevan@iinteractive.comE<gt>
727
728=head1 COPYRIGHT AND LICENSE
729
b77fdbed 730Copyright 2006, 2007 by Infinity Interactive, Inc.
a15dff8d 731
732L<http://www.iinteractive.com>
733
734This library is free software; you can redistribute it and/or modify
e85d2a5d 735it under the same terms as Perl itself.
a15dff8d 736
81dc201f 737=cut