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