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