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