File Coverage

blib/lib/Types/Standard.pm
Criterion Covered Total %
statement 63 64 98.4
branch 10 14 71.4
condition 5 7 71.4
subroutine 19 19 100.0
pod 3 3 100.0
total 100 107 93.4


line stmt bran cond sub pod time code
1             package Types::Standard;
2              
3 282     282   1137462 use 5.008001;
  282         1217  
4 282     282   1652 use strict;
  282         654  
  282         6406  
5 282     282   1444 use warnings;
  282         651  
  282         18439  
6              
7             BEGIN {
8 282     282   943 eval { require re };
  282         1723  
9 282 50       12312 if ( $] < 5.010 ) { require Devel::TypeTiny::Perl58Compat }
  0         0  
10             }
11              
12             BEGIN {
13 282     282   1072 $Types::Standard::AUTHORITY = 'cpan:TOBYINK';
14 282         13416 $Types::Standard::VERSION = '2.003_000';
15             }
16              
17             $Types::Standard::VERSION =~ tr/_//d;
18              
19 282     282   86268 use Type::Library -base;
  282         833  
  282         2803  
20              
21             our @EXPORT_OK = qw( slurpy );
22              
23 282     282   15530 use Eval::TypeTiny qw( set_subname );
  282         620  
  282         1420  
24 282     282   112474 use Scalar::Util qw( blessed looks_like_number );
  282         685  
  282         13988  
25 282     282   1677 use Type::Tiny ();
  282         614  
  282         3789  
26 282     282   1296 use Types::TypeTiny ();
  282         551  
  282         32759  
27              
28             my $is_class_loaded;
29              
30             BEGIN {
31 282     282   1025 $is_class_loaded = q{sub {
32             no strict 'refs';
33             return !!0 if ref $_[0];
34             return !!0 if not $_[0];
35             return !!0 if ref(do { my $tmpstr = $_[0]; \$tmpstr }) ne 'SCALAR';
36             my $stash = \%{"$_[0]\::"};
37             return !!1 if exists($stash->{'ISA'}) && *{$stash->{'ISA'}}{ARRAY} && @{$_[0].'::ISA'};
38             return !!1 if exists($stash->{'VERSION'});
39             foreach my $globref (values %$stash) {
40             return !!1
41             if ref \$globref eq 'GLOB'
42             ? *{$globref}{CODE}
43             : ref $globref; # const or sub ref
44             }
45             return !!0;
46             }};
47            
48 282         896 *_is_class_loaded =
49             Type::Tiny::_USE_XS
50             ? \&Type::Tiny::XS::Util::is_class_loaded
51             : eval $is_class_loaded;
52            
53             *_HAS_REFUTILXS = eval {
54 282         133131 require Ref::Util::XS;
55 282         192023 Ref::Util::XS::->VERSION( 0.100 );
56 282         252016 1;
57             }
58             ? sub () { !!1 }
59 282 50       620 : sub () { !!0 };
60             } #/ BEGIN
61              
62             my $add_core_type = sub {
63             my $meta = shift;
64             my ( $typedef ) = @_;
65            
66             my $name = $typedef->{name};
67             my ( $xsub, $xsubname );
68            
69             # We want Map and Tuple to be XSified, even if they're not
70             # really core.
71             $typedef->{_is_core} = 1
72             unless $name eq 'Map' || $name eq 'Tuple';
73            
74             if ( Type::Tiny::_USE_XS
75             and not( $name eq 'RegexpRef' ) )
76             {
77             $xsub = Type::Tiny::XS::get_coderef_for( $name );
78             $xsubname = Type::Tiny::XS::get_subname_for( $name );
79             }
80            
81             elsif ( Type::Tiny::_USE_MOUSE
82             and not( $name eq 'RegexpRef' or $name eq 'Int' or $name eq 'Object' ) )
83             {
84             require Mouse::Util::TypeConstraints;
85             $xsub = "Mouse::Util::TypeConstraints"->can( $name );
86             $xsubname = "Mouse::Util::TypeConstraints::$name" if $xsub;
87             }
88            
89             if ( Type::Tiny::_USE_XS
90             and Type::Tiny::XS->VERSION < 0.014
91             and $name eq 'Bool' )
92             {
93             # Broken implementation of Bool
94             $xsub = $xsubname = undef;
95             }
96            
97             if ( Type::Tiny::_USE_XS
98             and ( Type::Tiny::XS->VERSION < 0.016 or $] < 5.018 )
99             and $name eq 'Int' )
100             {
101             # Broken implementation of Int
102             $xsub = $xsubname = undef;
103             }
104            
105             $typedef->{compiled_type_constraint} = $xsub if $xsub;
106            
107             my $orig_inlined = $typedef->{inlined};
108             if (
109             defined( $xsubname ) and (
110            
111             # These should be faster than their normal inlined
112             # equivalents
113             $name eq 'Str'
114             or $name eq 'Bool'
115             or $name eq 'ClassName'
116             or $name eq 'RegexpRef'
117             or $name eq 'FileHandle'
118             )
119             )
120             {
121             $typedef->{inlined} = sub {
122             $Type::Tiny::AvoidCallbacks ? goto( $orig_inlined ) : "$xsubname\($_[1])";
123             };
124             } #/ if ( defined( $xsubname...))
125            
126             @_ = ( $meta, $typedef );
127             goto \&Type::Library::add_type;
128             };
129              
130             my $maybe_load_modules = sub {
131             my $code = pop;
132             if ( $Type::Tiny::AvoidCallbacks ) {
133             $code = sprintf(
134             'do { %s %s; %s }',
135             $Type::Tiny::SafePackage,
136             join( '; ', map "use $_ ()", @_ ),
137             $code,
138             );
139             }
140             $code;
141             };
142              
143 3     3   37 sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }
  3         12  
144              
145             my $meta = __PACKAGE__->meta;
146              
147             # Stringable and LazyLoad are optimizations that complicate
148             # this module somewhat, but they have led to performance
149             # improvements. If Types::Standard wasn't such a key type
150             # library, I wouldn't use them. I strongly discourage anybody
151             # from using them in their own code. If you're looking for
152             # examples of how to write a type library sanely, you're
153             # better off looking at the code for Types::Common::Numeric
154             # and Types::Common::String.
155              
156             {
157              
158             sub Stringable (&) {
159 47     47 1 425 bless +{ code => $_[0] }, 'Types::Standard::_Stringable';
160             }
161             Types::Standard::_Stringable->Type::Tiny::_install_overloads(
162 87   66 87   619 q[""] => sub { $_[0]{text} ||= $_[0]{code}->() } );
163            
164             sub LazyLoad ($$) {
165 10998     10998 1 59786 bless \@_, 'Types::Standard::LazyLoad';
166             }
167             'Types::Standard::LazyLoad'->Type::Tiny::_install_overloads(
168             q[&{}] => sub {
169 180     180   618 my ( $typename, $function ) = @{ $_[0] };
  180         941  
170 180         1584 my $type = $meta->get_type( $typename );
171 180         884 my $class = "Types::Standard::$typename";
172 180 50       13278 eval "require $class; 1" or die( $@ );
173            
174             # Majorly break encapsulation for Type::Tiny :-O
175 180         2457 for my $key ( keys %$type ) {
176 3614 100       9378 next unless ref( $type->{$key} ) eq 'Types::Standard::LazyLoad';
177 690         1696 my $f = $type->{$key}[1];
178 690         5793 $type->{$key} = $class->can( "__$f" );
179             }
180 180   100     1606 my $mm = $type->{my_methods} || {};
181 180         868 for my $key ( keys %$mm ) {
182 125 50       489 next unless ref( $mm->{$key} ) eq 'Types::Standard::LazyLoad';
183 125         370 my $f = $mm->{$key}[1];
184 125         686 $mm->{$key} = $class->can( "__$f" );
185             set_subname(
186             sprintf( "%s::my_%s", $type->qualified_name, $key ),
187 125         530 $mm->{$key},
188             );
189             } #/ for my $key ( keys %$mm)
190 180         1642 return $class->can( "__$function" );
191             },
192             );
193             }
194              
195 282     282   2525 no warnings;
  282         668  
  282         26569  
196              
197             BEGIN {
198             *STRICTNUM =
199             $ENV{PERL_TYPES_STANDARD_STRICTNUM}
200             ? sub() { !!1 }
201             : sub() { !!0 }
202 282 100   282   1906488 }
203              
204             my $_any = $meta->$add_core_type(
205             {
206             name => "Any",
207             inlined => sub { "!!1" },
208             complement_name => 'None',
209             type_default => sub { return undef; },
210             }
211             );
212              
213             my $_item = $meta->$add_core_type(
214             {
215             name => "Item",
216             inlined => sub { "!!1" },
217             parent => $_any,
218             }
219             );
220              
221             my $_bool = $meta->$add_core_type(
222             {
223             name => "Bool",
224             parent => $_item,
225             constraint => sub {
226             !ref $_ and ( !defined $_ or $_ eq q() or $_ eq '0' or $_ eq '1' );
227             },
228             inlined => sub {
229             "!ref $_[1] and (!defined $_[1] or $_[1] eq q() or $_[1] eq '0' or $_[1] eq '1')";
230             },
231             type_default => sub { return !!0; },
232             }
233             );
234              
235             $_bool->coercion->add_type_coercions( $_any, q{!!$_} );
236              
237             my $_undef = $meta->$add_core_type(
238             {
239             name => "Undef",
240             parent => $_item,
241             constraint => sub { !defined $_ },
242             inlined => sub { "!defined($_[1])" },
243             type_default => sub { return undef; },
244             }
245             );
246              
247             my $_def = $meta->$add_core_type(
248             {
249             name => "Defined",
250             parent => $_item,
251             constraint => sub { defined $_ },
252             inlined => sub { "defined($_[1])" },
253             complementary_type => $_undef,
254             }
255             );
256              
257             # hackish, but eh
258             Scalar::Util::weaken( $_undef->{complementary_type} ||= $_def );
259              
260             my $_val = $meta->$add_core_type(
261             {
262             name => "Value",
263             parent => $_def,
264             constraint => sub { not ref $_ },
265             inlined => sub { "defined($_[1]) and not ref($_[1])" },
266             }
267             );
268              
269             my $_str = $meta->$add_core_type(
270             {
271             name => "Str",
272             parent => $_val,
273             constraint => sub {
274             ref( \$_ ) eq 'SCALAR' or ref( \( my $val = $_ ) ) eq 'SCALAR';
275             },
276             inlined => sub {
277             "defined($_[1]) and do { ref(\\$_[1]) eq 'SCALAR' or ref(\\(my \$val = $_[1])) eq 'SCALAR' }";
278             },
279             sorter => sub { $_[0] cmp $_[1] },
280             type_default => sub { return ''; },
281             }
282             );
283              
284             my $_laxnum = $meta->add_type(
285             {
286             name => "LaxNum",
287             parent => $_str,
288             constraint => sub { looks_like_number( $_ ) and ref( \$_ ) ne 'GLOB' },
289             inlined => sub {
290             $maybe_load_modules->(
291             qw/ Scalar::Util /,
292             'Scalar::Util'->VERSION ge '1.18' # RT 132426
293             ? "defined($_[1]) && !ref($_[1]) && Scalar::Util::looks_like_number($_[1])"
294             : "defined($_[1]) && !ref($_[1]) && Scalar::Util::looks_like_number($_[1]) && ref(\\($_[1])) ne 'GLOB'"
295             );
296             },
297             sorter => sub { $_[0] <=> $_[1] },
298             type_default => sub { return 0; },
299             }
300             );
301              
302             my $_strictnum = $meta->add_type(
303             {
304             name => "StrictNum",
305             parent => $_str,
306             constraint => sub {
307             my $val = $_;
308             ( $val =~ /\A[+-]?[0-9]+\z/ )
309             || (
310             $val =~ /\A(?:[+-]?) #matches optional +- in the beginning
311             (?=[0-9]|\.[0-9]) #matches previous +- only if there is something like 3 or .3
312             [0-9]* #matches 0-9 zero or more times
313             (?:\.[0-9]+)? #matches optional .89 or nothing
314             (?:[Ee](?:[+-]?[0-9]+))? #matches E1 or e1 or e-1 or e+1 etc
315             \z/x
316             );
317             },
318             inlined => sub {
319             'my $val = '
320             . $_[1] . ';'
321             . Value()->inline_check( '$val' )
322             . ' && ( $val =~ /\A[+-]?[0-9]+\z/ || '
323             . '$val =~ /\A(?:[+-]?) # matches optional +- in the beginning
324             (?=[0-9]|\.[0-9]) # matches previous +- only if there is something like 3 or .3
325             [0-9]* # matches 0-9 zero or more times
326             (?:\.[0-9]+)? # matches optional .89 or nothing
327             (?:[Ee](?:[+-]?[0-9]+))? # matches E1 or e1 or e-1 or e+1 etc
328             \z/x ); '
329             },
330             sorter => sub { $_[0] <=> $_[1] },
331             type_default => sub { return 0; },
332             }
333             );
334              
335             my $_num = $meta->add_type(
336             {
337             name => "Num",
338             parent => ( STRICTNUM ? $_strictnum : $_laxnum ),
339             }
340             );
341              
342             $meta->$add_core_type(
343             {
344             name => "Int",
345             parent => $_num,
346             constraint => sub { /\A-?[0-9]+\z/ },
347             inlined => sub {
348             "do { my \$tmp = $_[1]; defined(\$tmp) and !ref(\$tmp) and \$tmp =~ /\\A-?[0-9]+\\z/ }";
349             },
350             type_default => sub { return 0; },
351             }
352             );
353              
354             my $_classn = $meta->add_type(
355             {
356             name => "ClassName",
357             parent => $_str,
358             constraint => \&_is_class_loaded,
359             inlined => sub {
360             $Type::Tiny::AvoidCallbacks
361             ? "($is_class_loaded)->(do { my \$tmp = $_[1] })"
362             : "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] })";
363             },
364             }
365             );
366              
367             $meta->add_type(
368             {
369             name => "RoleName",
370             parent => $_classn,
371             constraint => sub { not $_->can( "new" ) },
372             inlined => sub {
373             $Type::Tiny::AvoidCallbacks
374             ? "($is_class_loaded)->(do { my \$tmp = $_[1] }) and not $_[1]\->can('new')"
375             : "Types::Standard::_is_class_loaded(do { my \$tmp = $_[1] }) and not $_[1]\->can('new')";
376             },
377             }
378             );
379              
380             my $_ref = $meta->$add_core_type(
381             {
382             name => "Ref",
383             parent => $_def,
384             constraint => sub { ref $_ },
385             inlined => sub { "!!ref($_[1])" },
386             constraint_generator => sub {
387             return $meta->get_type( 'Ref' ) unless @_;
388            
389             my $reftype = shift;
390             $reftype =~
391             /^(SCALAR|ARRAY|HASH|CODE|REF|GLOB|LVALUE|FORMAT|IO|VSTRING|REGEXP|Regexp)$/i
392             or _croak(
393             "Parameter to Ref[`a] expected to be a Perl ref type; got $reftype" );
394            
395             $reftype = "$reftype";
396             return sub {
397             ref( $_[0] ) and Scalar::Util::reftype( $_[0] ) eq $reftype;
398             }
399             },
400             inline_generator => sub {
401             my $reftype = shift;
402             return sub {
403             my $v = $_[1];
404             $maybe_load_modules->(
405             qw/ Scalar::Util /,
406             "ref($v) and Scalar::Util::reftype($v) eq q($reftype)"
407             );
408             };
409             },
410             deep_explanation => sub {
411             require B;
412             my ( $type, $value, $varname ) = @_;
413             my $param = $type->parameters->[0];
414             return if $type->check( $value );
415             my $reftype = Scalar::Util::reftype( $value );
416             return [
417             sprintf(
418             '"%s" constrains reftype(%s) to be equal to %s', $type, $varname,
419             B::perlstring( $param )
420             ),
421             sprintf(
422             'reftype(%s) is %s', $varname,
423             defined( $reftype ) ? B::perlstring( $reftype ) : "undef"
424             ),
425             ];
426             },
427             }
428             );
429              
430             $meta->$add_core_type(
431             {
432             name => "CodeRef",
433             parent => $_ref,
434             constraint => sub { ref $_ eq "CODE" },
435             inlined => sub {
436             _HAS_REFUTILXS && !$Type::Tiny::AvoidCallbacks
437             ? "Ref::Util::XS::is_plain_coderef($_[1])"
438             : "ref($_[1]) eq 'CODE'";
439             },
440             type_default => sub { return sub {}; },
441             }
442             );
443              
444             my $_regexp = $meta->$add_core_type(
445             {
446             name => "RegexpRef",
447             parent => $_ref,
448             constraint => sub {
449             ref( $_ ) && !!re::is_regexp( $_ ) or blessed( $_ ) && $_->isa( 'Regexp' );
450             },
451             inlined => sub {
452             my $v = $_[1];
453             $maybe_load_modules->(
454             qw/ Scalar::Util re /,
455             "ref($v) && !!re::is_regexp($v) or Scalar::Util::blessed($v) && $v\->isa('Regexp')"
456             );
457             },
458             type_default => sub { return qr//; },
459             }
460             );
461              
462             $meta->$add_core_type(
463             {
464             name => "GlobRef",
465             parent => $_ref,
466             constraint => sub { ref $_ eq "GLOB" },
467             inlined => sub {
468             _HAS_REFUTILXS && !$Type::Tiny::AvoidCallbacks
469             ? "Ref::Util::XS::is_plain_globref($_[1])"
470             : "ref($_[1]) eq 'GLOB'";
471             },
472             }
473             );
474              
475             $meta->$add_core_type(
476             {
477             name => "FileHandle",
478             parent => $_ref,
479             constraint => sub {
480             ( ref( $_ ) && Scalar::Util::openhandle( $_ ) )
481             or ( blessed( $_ ) && $_->isa( "IO::Handle" ) );
482             },
483             inlined => sub {
484             $maybe_load_modules->(
485             qw/ Scalar::Util /,
486             "(ref($_[1]) && Scalar::Util::openhandle($_[1])) "
487             . "or (Scalar::Util::blessed($_[1]) && $_[1]\->isa(\"IO::Handle\"))"
488             );
489             },
490             }
491             );
492              
493             my $_arr = $meta->$add_core_type(
494             {
495             name => "ArrayRef",
496             parent => $_ref,
497             constraint => sub { ref $_ eq "ARRAY" },
498             inlined => sub {
499             _HAS_REFUTILXS && !$Type::Tiny::AvoidCallbacks
500             ? "Ref::Util::XS::is_plain_arrayref($_[1])"
501             : "ref($_[1]) eq 'ARRAY'";
502             },
503             constraint_generator => LazyLoad( ArrayRef => 'constraint_generator' ),
504             inline_generator => LazyLoad( ArrayRef => 'inline_generator' ),
505             deep_explanation => LazyLoad( ArrayRef => 'deep_explanation' ),
506             coercion_generator => LazyLoad( ArrayRef => 'coercion_generator' ),
507             type_default => sub { return []; },
508             type_default_generator => sub {
509             return $Type::Tiny::parameterize_type->type_default if @_ < 2;
510             return undef;
511             },
512             }
513             );
514              
515             my $_hash = $meta->$add_core_type(
516             {
517             name => "HashRef",
518             parent => $_ref,
519             constraint => sub { ref $_ eq "HASH" },
520             inlined => sub {
521             _HAS_REFUTILXS && !$Type::Tiny::AvoidCallbacks
522             ? "Ref::Util::XS::is_plain_hashref($_[1])"
523             : "ref($_[1]) eq 'HASH'";
524             },
525             constraint_generator => LazyLoad( HashRef => 'constraint_generator' ),
526             inline_generator => LazyLoad( HashRef => 'inline_generator' ),
527             deep_explanation => LazyLoad( HashRef => 'deep_explanation' ),
528             coercion_generator => LazyLoad( HashRef => 'coercion_generator' ),
529             type_default => sub { return {}; },
530             type_default_generator => sub {
531             return $Type::Tiny::parameterize_type->type_default if @_ < 2;
532             return undef;
533             },
534             my_methods => {
535             hashref_allows_key => LazyLoad( HashRef => 'hashref_allows_key' ),
536             hashref_allows_value => LazyLoad( HashRef => 'hashref_allows_value' ),
537             },
538             }
539             );
540              
541             $meta->$add_core_type(
542             {
543             name => "ScalarRef",
544             parent => $_ref,
545             constraint => sub { ref $_ eq "SCALAR" or ref $_ eq "REF" },
546             inlined => sub { "ref($_[1]) eq 'SCALAR' or ref($_[1]) eq 'REF'" },
547             constraint_generator => LazyLoad( ScalarRef => 'constraint_generator' ),
548             inline_generator => LazyLoad( ScalarRef => 'inline_generator' ),
549             deep_explanation => LazyLoad( ScalarRef => 'deep_explanation' ),
550             coercion_generator => LazyLoad( ScalarRef => 'coercion_generator' ),
551             type_default => sub { my $x; return \$x; },
552             }
553             );
554              
555             my $_obj = $meta->$add_core_type(
556             {
557             name => "Object",
558             parent => $_ref,
559             constraint => sub { blessed $_ },
560             inlined => sub {
561             _HAS_REFUTILXS && !$Type::Tiny::AvoidCallbacks
562             ? "Ref::Util::XS::is_blessed_ref($_[1])"
563             : $maybe_load_modules->(
564             'Scalar::Util',
565             "Scalar::Util::blessed($_[1])"
566             );
567             },
568             is_object => 1,
569             }
570             );
571              
572             $meta->$add_core_type(
573             {
574             name => "Maybe",
575             parent => $_item,
576             constraint_generator => sub {
577             return $meta->get_type( 'Maybe' ) unless @_;
578            
579             my $param = Types::TypeTiny::to_TypeTiny( shift );
580             Types::TypeTiny::is_TypeTiny( $param )
581             or _croak(
582             "Parameter to Maybe[`a] expected to be a type constraint; got $param" );
583            
584             my $param_compiled_check = $param->compiled_check;
585             my @xsub;
586             if ( Type::Tiny::_USE_XS ) {
587             my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
588             push @xsub, Type::Tiny::XS::get_coderef_for( "Maybe[$paramname]" )
589             if $paramname;
590             }
591             elsif ( Type::Tiny::_USE_MOUSE and $param->_has_xsub ) {
592             require Mouse::Util::TypeConstraints;
593             my $maker = "Mouse::Util::TypeConstraints"->can( "_parameterize_Maybe_for" );
594             push @xsub, $maker->( $param ) if $maker;
595             }
596            
597             return (
598             sub {
599             my $value = shift;
600             return !!1 unless defined $value;
601             return $param->check( $value );
602             },
603             @xsub,
604             );
605             },
606             inline_generator => sub {
607             my $param = shift;
608            
609             my $param_compiled_check = $param->compiled_check;
610             my $xsubname;
611             if ( Type::Tiny::_USE_XS ) {
612             my $paramname = Type::Tiny::XS::is_known( $param_compiled_check );
613             $xsubname = Type::Tiny::XS::get_subname_for( "Maybe[$paramname]" );
614             }
615            
616             return unless $param->can_be_inlined;
617             return sub {
618             my $v = $_[1];
619             return "$xsubname\($v\)" if $xsubname && !$Type::Tiny::AvoidCallbacks;
620             my $param_check = $param->inline_check( $v );
621             "!defined($v) or $param_check";
622             };
623             },
624             deep_explanation => sub {
625             my ( $type, $value, $varname ) = @_;
626             my $param = $type->parameters->[0];
627            
628             return [
629             sprintf( '%s is defined', Type::Tiny::_dd( $value ) ),
630             sprintf(
631             '"%s" constrains the value with "%s" if it is defined', $type, $param
632             ),
633             @{ $param->validate_explain( $value, $varname ) },
634             ];
635             },
636             coercion_generator => sub {
637             my ( $parent, $child, $param ) = @_;
638             return unless $param->has_coercion;
639             return $param->coercion;
640             },
641             type_default => sub { return undef; },
642             type_default_generator => sub {
643             $_[0]->type_default || $Type::Tiny::parameterize_type->type_default ;
644             },
645             }
646             );
647              
648             my $_map = $meta->$add_core_type(
649             {
650             name => "Map",
651             parent => $_hash,
652             constraint_generator => LazyLoad( Map => 'constraint_generator' ),
653             inline_generator => LazyLoad( Map => 'inline_generator' ),
654             deep_explanation => LazyLoad( Map => 'deep_explanation' ),
655             coercion_generator => LazyLoad( Map => 'coercion_generator' ),
656             my_methods => {
657             hashref_allows_key => LazyLoad( Map => 'hashref_allows_key' ),
658             hashref_allows_value => LazyLoad( Map => 'hashref_allows_value' ),
659             },
660             type_default_generator => sub {
661             return $Type::Tiny::parameterize_type->type_default;
662             },
663             }
664             );
665              
666             my $_Optional = $meta->add_type(
667             {
668             name => "Optional",
669             parent => $_item,
670             constraint_generator => sub {
671             return $meta->get_type( 'Optional' ) unless @_;
672            
673             my $param = Types::TypeTiny::to_TypeTiny( shift );
674             Types::TypeTiny::is_TypeTiny( $param )
675             or _croak(
676             "Parameter to Optional[`a] expected to be a type constraint; got $param" );
677            
678             sub { $param->check( $_[0] ) }
679             },
680             inline_generator => sub {
681             my $param = shift;
682             return unless $param->can_be_inlined;
683             return sub {
684             my $v = $_[1];
685             $param->inline_check( $v );
686             };
687             },
688             deep_explanation => sub {
689             my ( $type, $value, $varname ) = @_;
690             my $param = $type->parameters->[0];
691            
692             return [
693             sprintf( '%s exists', $varname ),
694             sprintf( '"%s" constrains %s with "%s" if it exists', $type, $varname, $param ),
695             @{ $param->validate_explain( $value, $varname ) },
696             ];
697             },
698             coercion_generator => sub {
699             my ( $parent, $child, $param ) = @_;
700             return unless $param->has_coercion;
701             return $param->coercion;
702             },
703             type_default_generator => sub {
704             return $_[0]->type_default;
705             },
706             }
707             );
708              
709             my $_slurpy;
710             $_slurpy = $meta->add_type(
711             {
712             name => "Slurpy",
713             slurpy => 1,
714             parent => $_item,
715             constraint_generator => sub {
716             my $self = $_slurpy;
717             my $param = @_ ? Types::TypeTiny::to_TypeTiny(shift) : $_any;
718             Types::TypeTiny::is_TypeTiny( $param )
719             or _croak(
720             "Parameter to Slurpy[`a] expected to be a type constraint; got $param" );
721            
722             return $self->create_child_type(
723             slurpy => 1,
724             display_name => $self->name_generator->( $self, $param ),
725             parameters => [ $param ],
726             constraint => sub { $param->check( $_[0] ) },
727             type_default => $param->type_default,
728             _build_coercion => sub {
729             my $coercion = shift;
730             $coercion->add_type_coercions( @{ $param->coercion->type_coercion_map } )
731             if $param->has_coercion;
732             $coercion->freeze;
733             },
734             $param->can_be_inlined
735             ? ( inlined => sub { $param->inline_check( $_[1] ) } )
736             : (),
737             );
738             },
739             deep_explanation => sub {
740             my ( $type, $value, $varname ) = @_;
741             my $param = $type->parameters->[0];
742             return [
743             sprintf( '%s is slurpy', $varname ),
744             @{ $param->validate_explain( $value, $varname ) },
745             ];
746             },
747             my_methods => {
748             'unslurpy' => sub {
749             my $self = shift;
750             $self->{_my_unslurpy} ||= $self->find_parent(
751             sub { $_->parent->{uniq} == $_slurpy->{uniq} }
752             )->type_parameter;
753             },
754             'slurp_into' => sub {
755             my $self = shift;
756             my $parameters = $self->find_parent(
757             sub { $_->parent->{uniq} == $_slurpy->{uniq} }
758             )->parameters;
759             if ( $parameters->[1] ) {
760             return $parameters->[1];
761             }
762             my $constraint = $parameters->[0];
763             return 'HASH'
764             if $constraint->is_a_type_of( HashRef() )
765             or $constraint->is_a_type_of( Map() )
766             or $constraint->is_a_type_of( Dict() );
767             return 'ARRAY';
768             },
769             },
770             }
771             );
772              
773             sub slurpy {
774 97     97 1 4212 my $t = shift;
775 97         455 my $s = $_slurpy->of( $t );
776 95   50     399 $s->{slurpy} ||= 1;
777 95 100       767 wantarray ? ( $s, @_ ) : $s;
778             }
779              
780             $meta->$add_core_type(
781             {
782             name => "Tuple",
783             parent => $_arr,
784             name_generator => sub {
785             my ( $s, @a ) = @_;
786             sprintf( '%s[%s]', $s, join q[,], @a );
787             },
788             constraint_generator => LazyLoad( Tuple => 'constraint_generator' ),
789             inline_generator => LazyLoad( Tuple => 'inline_generator' ),
790             deep_explanation => LazyLoad( Tuple => 'deep_explanation' ),
791             coercion_generator => LazyLoad( Tuple => 'coercion_generator' ),
792             }
793             );
794              
795             $meta->add_type(
796             {
797             name => "CycleTuple",
798             parent => $_arr,
799             name_generator => sub {
800             my ( $s, @a ) = @_;
801             sprintf( '%s[%s]', $s, join q[,], @a );
802             },
803             constraint_generator => LazyLoad( CycleTuple => 'constraint_generator' ),
804             inline_generator => LazyLoad( CycleTuple => 'inline_generator' ),
805             deep_explanation => LazyLoad( CycleTuple => 'deep_explanation' ),
806             coercion_generator => LazyLoad( CycleTuple => 'coercion_generator' ),
807             }
808             );
809              
810             $meta->add_type(
811             {
812             name => "Dict",
813             parent => $_hash,
814             name_generator => sub {
815             my ( $s, @p ) = @_;
816             my $l = @p
817             && Types::TypeTiny::is_TypeTiny( $p[-1] )
818             && $p[-1]->is_strictly_a_type_of( Types::Standard::Slurpy() )
819             ? pop(@p)
820             : undef;
821             my %a = @p;
822             sprintf(
823             '%s[%s%s]', $s,
824             join( q[,], map sprintf( "%s=>%s", $_, $a{$_} ), sort keys %a ),
825             $l ? ",$l" : ''
826             );
827             },
828             constraint_generator => LazyLoad( Dict => 'constraint_generator' ),
829             inline_generator => LazyLoad( Dict => 'inline_generator' ),
830             deep_explanation => LazyLoad( Dict => 'deep_explanation' ),
831             coercion_generator => LazyLoad( Dict => 'coercion_generator' ),
832             my_methods => {
833             dict_is_slurpy => LazyLoad( Dict => 'dict_is_slurpy' ),
834             hashref_allows_key => LazyLoad( Dict => 'hashref_allows_key' ),
835             hashref_allows_value => LazyLoad( Dict => 'hashref_allows_value' ),
836             },
837             }
838             );
839              
840             $meta->add_type(
841             {
842             name => "Overload",
843             parent => $_obj,
844             constraint => sub { require overload; overload::Overloaded( $_ ) },
845             inlined => sub {
846             $maybe_load_modules->(
847             qw/ Scalar::Util overload /,
848             $INC{'overload.pm'}
849             ? "Scalar::Util::blessed($_[1]) and overload::Overloaded($_[1])"
850             : "Scalar::Util::blessed($_[1]) and do { use overload (); overload::Overloaded($_[1]) }"
851             );
852             },
853             constraint_generator => sub {
854             return $meta->get_type( 'Overload' ) unless @_;
855            
856             my @operations = map {
857             Types::TypeTiny::is_StringLike( $_ )
858             ? "$_"
859             : _croak( "Parameters to Overload[`a] expected to be a strings; got $_" );
860             } @_;
861            
862             require overload;
863             return sub {
864             my $value = shift;
865             for my $op ( @operations ) {
866             return unless overload::Method( $value, $op );
867             }
868             return !!1;
869             }
870             },
871             inline_generator => sub {
872             my @operations = @_;
873             return sub {
874             require overload;
875             my $v = $_[1];
876             $maybe_load_modules->(
877             qw/ Scalar::Util overload /,
878             join " and ",
879             "Scalar::Util::blessed($v)",
880             map "overload::Method($v, q[$_])", @operations
881             );
882             };
883             },
884             is_object => 1,
885             }
886             );
887              
888             $meta->add_type(
889             {
890             name => "StrMatch",
891             parent => $_str,
892             constraint_generator => LazyLoad( StrMatch => 'constraint_generator' ),
893             inline_generator => LazyLoad( StrMatch => 'inline_generator' ),
894             }
895             );
896              
897             $meta->add_type(
898             {
899             name => "OptList",
900             parent => $_arr,
901             constraint => sub {
902             for my $inner ( @$_ ) {
903             return unless ref( $inner ) eq q(ARRAY);
904             return unless @$inner == 2;
905             return unless is_Str( $inner->[0] );
906             }
907             return !!1;
908             },
909             inlined => sub {
910             my ( $self, $var ) = @_;
911             my $Str_check = Str()->inline_check( '$inner->[0]' );
912             my @code = 'do { my $ok = 1; ';
913             push @code, sprintf( 'for my $inner (@{%s}) { no warnings; ', $var );
914             push @code,
915             sprintf(
916             '($ok=0) && last unless ref($inner) eq q(ARRAY) && @$inner == 2 && (%s); ',
917             $Str_check
918             );
919             push @code, '} ';
920             push @code, '$ok }';
921             return ( undef, join( q( ), @code ) );
922             },
923             type_default => sub { return [] },
924             }
925             );
926              
927             $meta->add_type(
928             {
929             name => "Tied",
930             parent => $_ref,
931             constraint => sub {
932             !!tied(
933             Scalar::Util::reftype( $_ ) eq 'HASH' ? %{$_}
934             : Scalar::Util::reftype( $_ ) eq 'ARRAY' ? @{$_}
935             : Scalar::Util::reftype( $_ ) =~ /^(SCALAR|REF)$/ ? ${$_}
936             : undef
937             );
938             },
939             inlined => sub {
940             my ( $self, $var ) = @_;
941             $maybe_load_modules->(
942             qw/ Scalar::Util /,
943             $self->parent->inline_check( $var )
944             . " and !!tied(Scalar::Util::reftype($var) eq 'HASH' ? \%{$var} : Scalar::Util::reftype($var) eq 'ARRAY' ? \@{$var} : Scalar::Util::reftype($var) =~ /^(SCALAR|REF)\$/ ? \${$var} : undef)"
945             );
946             },
947             name_generator => sub {
948             my $self = shift;
949             my $param = Types::TypeTiny::to_TypeTiny( shift );
950             unless ( Types::TypeTiny::is_TypeTiny( $param ) ) {
951             Types::TypeTiny::is_StringLike( $param )
952             or _croak( "Parameter to Tied[`a] expected to be a class name; got $param" );
953             require B;
954             return sprintf( "%s[%s]", $self, B::perlstring( $param ) );
955             }
956             return sprintf( "%s[%s]", $self, $param );
957             },
958             constraint_generator => LazyLoad( Tied => 'constraint_generator' ),
959             inline_generator => LazyLoad( Tied => 'inline_generator' ),
960             }
961             );
962              
963             $meta->add_type(
964             {
965             name => "InstanceOf",
966             parent => $_obj,
967             constraint_generator => sub {
968             return $meta->get_type( 'InstanceOf' ) unless @_;
969             require Type::Tiny::Class;
970             my @classes = map {
971             Types::TypeTiny::is_TypeTiny( $_ )
972             ? $_
973             : "Type::Tiny::Class"->new(
974             class => $_,
975             display_name => sprintf( 'InstanceOf[%s]', B::perlstring( $_ ) )
976             )
977             } @_;
978             return $classes[0] if @classes == 1;
979            
980             require B;
981             require Type::Tiny::Union;
982             return "Type::Tiny::Union"->new(
983             type_constraints => \@classes,
984             display_name => sprintf(
985             'InstanceOf[%s]', join q[,], map B::perlstring( $_->class ), @classes
986             ),
987             );
988             },
989             }
990             );
991              
992             $meta->add_type(
993             {
994             name => "ConsumerOf",
995             parent => $_obj,
996             constraint_generator => sub {
997             return $meta->get_type( 'ConsumerOf' ) unless @_;
998             require B;
999             require Type::Tiny::Role;
1000             my @roles = map {
1001             Types::TypeTiny::is_TypeTiny( $_ )
1002             ? $_
1003             : "Type::Tiny::Role"->new(
1004             role => $_,
1005             display_name => sprintf( 'ConsumerOf[%s]', B::perlstring( $_ ) )
1006             )
1007             } @_;
1008             return $roles[0] if @roles == 1;
1009            
1010             require Type::Tiny::Intersection;
1011             return "Type::Tiny::Intersection"->new(
1012             type_constraints => \@roles,
1013             display_name => sprintf(
1014             'ConsumerOf[%s]', join q[,], map B::perlstring( $_->role ), @roles
1015             ),
1016             );
1017             },
1018             }
1019             );
1020              
1021             $meta->add_type(
1022             {
1023             name => "HasMethods",
1024             parent => $_obj,
1025             constraint_generator => sub {
1026             return $meta->get_type( 'HasMethods' ) unless @_;
1027             require B;
1028             require Type::Tiny::Duck;
1029             return "Type::Tiny::Duck"->new(
1030             methods => \@_,
1031             display_name =>
1032             sprintf( 'HasMethods[%s]', join q[,], map B::perlstring( $_ ), @_ ),
1033             );
1034             },
1035             }
1036             );
1037              
1038             $meta->add_type(
1039             {
1040             name => "Enum",
1041             parent => $_str,
1042             constraint_generator => sub {
1043             return $meta->get_type( 'Enum' ) unless @_;
1044             my $coercion;
1045             if ( ref( $_[0] ) and ref( $_[0] ) eq 'SCALAR' ) {
1046             $coercion = ${ +shift };
1047             }
1048             elsif ( ref( $_[0] ) && !blessed( $_[0] )
1049             or blessed( $_[0] ) && $_[0]->isa( 'Type::Coercion' ) )
1050             {
1051             $coercion = shift;
1052             }
1053             require B;
1054             require Type::Tiny::Enum;
1055             return "Type::Tiny::Enum"->new(
1056             values => \@_,
1057             display_name => sprintf( 'Enum[%s]', join q[,], map B::perlstring( $_ ), @_ ),
1058             $coercion ? ( coercion => $coercion ) : (),
1059             );
1060             },
1061             type_default => undef,
1062             }
1063             );
1064              
1065             $meta->add_coercion(
1066             {
1067             name => "MkOpt",
1068             type_constraint => $meta->get_type( "OptList" ),
1069             type_coercion_map => [
1070             $_arr, q{ Exporter::Tiny::mkopt($_) },
1071             $_hash, q{ Exporter::Tiny::mkopt($_) },
1072             $_undef, q{ [] },
1073             ],
1074             }
1075             );
1076              
1077             $meta->add_coercion(
1078             {
1079             name => "Join",
1080             type_constraint => $_str,
1081             coercion_generator => sub {
1082             my ( $self, $target, $sep ) = @_;
1083             Types::TypeTiny::is_StringLike( $sep )
1084             or _croak( "Parameter to Join[`a] expected to be a string; got $sep" );
1085             require B;
1086             $sep = B::perlstring( $sep );
1087             return ( ArrayRef(), qq{ join($sep, \@\$_) } );
1088             },
1089             }
1090             );
1091              
1092             $meta->add_coercion(
1093             {
1094             name => "Split",
1095             type_constraint => $_arr,
1096             coercion_generator => sub {
1097             my ( $self, $target, $re ) = @_;
1098             ref( $re ) eq q(Regexp)
1099             or _croak(
1100             "Parameter to Split[`a] expected to be a regular expresssion; got $re" );
1101             my $regexp_string = "$re";
1102             $regexp_string =~ s/\\\//\\\\\//g; # toothpicks
1103             return ( Str(), qq{ [split /$regexp_string/, \$_] } );
1104             },
1105             }
1106             );
1107              
1108             __PACKAGE__->meta->make_immutable;
1109              
1110             1;
1111              
1112             __END__
1113              
1114             =pod
1115              
1116             =for stopwords booleans vstrings typeglobs
1117              
1118             =encoding utf-8
1119              
1120             =for stopwords datetimes
1121              
1122             =head1 NAME
1123              
1124             Types::Standard - bundled set of built-in types for Type::Tiny
1125              
1126             =head1 SYNOPSIS
1127              
1128             use v5.12;
1129             use strict;
1130             use warnings;
1131            
1132             package Horse {
1133             use Moo;
1134             use Types::Standard qw( Str Int Enum ArrayRef Object );
1135             use Type::Params qw( compile );
1136             use namespace::autoclean;
1137            
1138             has name => (
1139             is => 'ro',
1140             isa => Str,
1141             required => 1,
1142             );
1143             has gender => (
1144             is => 'ro',
1145             isa => Enum[qw( f m )],
1146             );
1147             has age => (
1148             is => 'rw',
1149             isa => Int->where( '$_ >= 0' ),
1150             );
1151             has children => (
1152             is => 'ro',
1153             isa => ArrayRef[Object],
1154             default => sub { return [] },
1155             );
1156            
1157             sub add_child {
1158             state $check = signature(
1159             method => Object,
1160             positional => [ Object ],
1161             ); # method signature
1162             my ( $self, $child ) = $check->( @_ ); # unpack @_
1163            
1164             push @{ $self->children }, $child;
1165             return $self;
1166             }
1167             }
1168            
1169             package main;
1170            
1171             my $boldruler = Horse->new(
1172             name => "Bold Ruler",
1173             gender => 'm',
1174             age => 16,
1175             );
1176            
1177             my $secretariat = Horse->new(
1178             name => "Secretariat",
1179             gender => 'm',
1180             age => 0,
1181             );
1182            
1183             $boldruler->add_child( $secretariat );
1184            
1185             use Types::Standard qw( is_Object assert_Object );
1186            
1187             # is_Object($thing) returns a boolean
1188             my $is_it_an_object = is_Object($boldruler);
1189            
1190             # assert_Object($thing) returns $thing or dies
1191             say assert_Object($boldruler)->name; # says "Bold Ruler"
1192              
1193             =head1 STATUS
1194              
1195             This module is covered by the
1196             L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.
1197              
1198             =head1 DESCRIPTION
1199              
1200             This documents the details of the L<Types::Standard> type library.
1201             L<Type::Tiny::Manual> is a better starting place if you're new.
1202              
1203             L<Type::Tiny> bundles a few types which seem to be useful.
1204              
1205             =head2 Moose-like
1206              
1207             The following types are similar to those described in
1208             L<Moose::Util::TypeConstraints>.
1209              
1210             =over
1211              
1212             =item *
1213              
1214             B<< Any >>
1215              
1216             Absolutely any value passes this type constraint (even undef).
1217              
1218             =item *
1219              
1220             B<< Item >>
1221              
1222             Essentially the same as B<Any>. All other type constraints in this library
1223             inherit directly or indirectly from B<Item>.
1224              
1225             =item *
1226              
1227             B<< Bool >>
1228              
1229             Values that are reasonable booleans. Accepts 1, 0, the empty string and
1230             undef.
1231              
1232             =item *
1233              
1234             B<< Maybe[`a] >>
1235              
1236             Given another type constraint, also accepts undef. For example,
1237             B<< Maybe[Int] >> accepts all integers plus undef.
1238              
1239             =item *
1240              
1241             B<< Undef >>
1242              
1243             Only undef passes this type constraint.
1244              
1245             =item *
1246              
1247             B<< Defined >>
1248              
1249             Only undef fails this type constraint.
1250              
1251             =item *
1252              
1253             B<< Value >>
1254              
1255             Any defined, non-reference value.
1256              
1257             =item *
1258              
1259             B<< Str >>
1260              
1261             Any string.
1262              
1263             (The only difference between B<Value> and B<Str> is that the former accepts
1264             typeglobs and vstrings.)
1265              
1266             Other customers also bought: B<< StringLike >> from L<Types::TypeTiny>.
1267              
1268             =item *
1269              
1270             B<< Num >>
1271              
1272             See B<LaxNum> and B<StrictNum> below.
1273              
1274             =item *
1275              
1276             B<< Int >>
1277              
1278             An integer; that is a string of digits 0 to 9, optionally prefixed with a
1279             hyphen-minus character.
1280              
1281             Expect inconsistent results for dualvars, and numbers too high (or negative
1282             numbers too low) for Perl to safely represent as an integer.
1283              
1284             =item *
1285              
1286             B<< ClassName >>
1287              
1288             The name of a loaded package. The package must have C<< @ISA >> or
1289             C<< $VERSION >> defined, or must define at least one sub to be considered
1290             a loaded package.
1291              
1292             =item *
1293              
1294             B<< RoleName >>
1295              
1296             Like B<< ClassName >>, but the package must I<not> define a method called
1297             C<new>. This is subtly different from Moose's type constraint of the same
1298             name; let me know if this causes you any problems. (I can't promise I'll
1299             change anything though.)
1300              
1301             =item *
1302              
1303             B<< Ref[`a] >>
1304              
1305             Any defined reference value, including blessed objects.
1306              
1307             Unlike Moose, B<Ref> is a parameterized type, allowing Scalar::Util::reftype
1308             checks, a la
1309              
1310             Ref["HASH"] # hashrefs, including blessed hashrefs
1311              
1312             =item *
1313              
1314             B<< ScalarRef[`a] >>
1315              
1316             A value where C<< ref($value) eq "SCALAR" or ref($value) eq "REF" >>.
1317              
1318             If parameterized, the referred value must pass the additional constraint.
1319             For example, B<< ScalarRef[Int] >> must be a reference to a scalar which
1320             holds an integer value.
1321              
1322             =item *
1323              
1324             B<< ArrayRef[`a] >>
1325              
1326             A value where C<< ref($value) eq "ARRAY" >>.
1327              
1328             If parameterized, the elements of the array must pass the additional
1329             constraint. For example, B<< ArrayRef[Num] >> must be a reference to an
1330             array of numbers.
1331              
1332             As an extension to Moose's B<ArrayRef> type, a minimum and maximum array
1333             length can be given:
1334              
1335             ArrayRef[CodeRef, 1] # ArrayRef of at least one CodeRef
1336             ArrayRef[FileHandle, 0, 2] # ArrayRef of up to two FileHandles
1337             ArrayRef[Any, 0, 100] # ArrayRef of up to 100 elements
1338              
1339             Other customers also bought: B<< ArrayLike >> from L<Types::TypeTiny>.
1340              
1341             =item *
1342              
1343             B<< HashRef[`a] >>
1344              
1345             A value where C<< ref($value) eq "HASH" >>.
1346              
1347             If parameterized, the values of the hash must pass the additional
1348             constraint. For example, B<< HashRef[Num] >> must be a reference to an
1349             hash where the values are numbers. The hash keys are not constrained,
1350             but Perl limits them to strings; see B<Map> below if you need to further
1351             constrain the hash values.
1352              
1353             Other customers also bought: B<< HashLike >> from L<Types::TypeTiny>.
1354              
1355             =item *
1356              
1357             B<< CodeRef >>
1358              
1359             A value where C<< ref($value) eq "CODE" >>.
1360              
1361             Other customers also bought: B<< CodeLike >> from L<Types::TypeTiny>.
1362              
1363             =item *
1364              
1365             B<< RegexpRef >>
1366              
1367             A reference where C<< re::is_regexp($value) >> is true, or
1368             a blessed reference where C<< $value->isa("Regexp") >> is true.
1369              
1370             =item *
1371              
1372             B<< GlobRef >>
1373              
1374             A value where C<< ref($value) eq "GLOB" >>.
1375              
1376             =item *
1377              
1378             B<< FileHandle >>
1379              
1380             A file handle.
1381              
1382             =item *
1383              
1384             B<< Object >>
1385              
1386             A blessed object.
1387              
1388             (This also accepts regexp refs.)
1389              
1390             =back
1391              
1392             =head2 Structured
1393              
1394             Okay, so I stole some ideas from L<MooseX::Types::Structured>.
1395              
1396             =over
1397              
1398             =item *
1399              
1400             B<< Map[`k, `v] >>
1401              
1402             Similar to B<HashRef> but parameterized with type constraints for both the
1403             key and value. The constraint for keys would typically be a subtype of
1404             B<Str>.
1405              
1406             =item *
1407              
1408             B<< Tuple[...] >>
1409              
1410             Subtype of B<ArrayRef>, accepting a list of type constraints for
1411             each slot in the array.
1412              
1413             B<< Tuple[Int, HashRef] >> would match C<< [1, {}] >> but not C<< [{}, 1] >>.
1414              
1415             =item *
1416              
1417             B<< Dict[...] >>
1418              
1419             Subtype of B<HashRef>, accepting a list of type constraints for
1420             each slot in the hash.
1421              
1422             For example B<< Dict[name => Str, id => Int] >> allows
1423             C<< { name => "Bob", id => 42 } >>.
1424              
1425             =item *
1426              
1427             B<< Optional[`a] >>
1428              
1429             Used in conjunction with B<Dict> and B<Tuple> to specify slots that are
1430             optional and may be omitted (but not necessarily set to an explicit undef).
1431              
1432             B<< Dict[name => Str, id => Optional[Int]] >> allows C<< { name => "Bob" } >>
1433             but not C<< { name => "Bob", id => "BOB" } >>.
1434              
1435             Note that any use of B<< Optional[`a] >> outside the context of
1436             parameterized B<Dict> and B<Tuple> type constraints makes little sense,
1437             and its behaviour is undefined. (An exception: it is used by
1438             L<Type::Params> for a similar purpose to how it's used in B<Tuple>.)
1439              
1440             =back
1441              
1442             This module also exports a B<Slurpy> parameterized type, which can be
1443             used as follows.
1444              
1445             It can cause additional trailing values in a B<Tuple> to be slurped
1446             into a structure and validated. For example, slurping into an arrayref:
1447              
1448             my $type = Tuple[ Str, Slurpy[ ArrayRef[Int] ] ];
1449            
1450             $type->( ["Hello"] ); # ok
1451             $type->( ["Hello", 1, 2, 3] ); # ok
1452             $type->( ["Hello", [1, 2, 3]] ); # not ok
1453              
1454             Or into a hashref:
1455              
1456             my $type2 = Tuple[ Str, Slurpy[ Map[Int, RegexpRef] ] ];
1457            
1458             $type2->( ["Hello"] ); # ok
1459             $type2->( ["Hello", 1, qr/one/i, 2, qr/two/] ); # ok
1460              
1461             It can cause additional values in a B<Dict> to be slurped into a
1462             hashref and validated:
1463              
1464             my $type3 = Dict[ values => ArrayRef, Slurpy[ HashRef[Str] ] ];
1465            
1466             $type3->( { values => [] } ); # ok
1467             $type3->( { values => [], name => "Foo" } ); # ok
1468             $type3->( { values => [], name => [] } ); # not ok
1469              
1470             In either B<Tuple> or B<Dict>, B<< Slurpy[Any] >> can be used to indicate
1471             that additional values are acceptable, but should not be constrained in
1472             any way.
1473              
1474             B<< Slurpy[Any] >> is an optimized code path. Although the following are
1475             essentially equivalent checks, the former should run a lot faster:
1476              
1477             Tuple[ Int, Slurpy[Any] ]
1478             Tuple[ Int, Slurpy[ArrayRef] ]
1479              
1480             A function C<< slurpy($type) >> is also exported which was historically
1481             how slurpy types were created.
1482              
1483             Outside of B<Dict> and B<Tuple>, B<< Slurpy[Foo] >> should just act the
1484             same as B<Foo>. But don't do that.
1485              
1486             =begin trustme
1487              
1488             =item slurpy
1489              
1490             =end trustme
1491              
1492             =head2 Objects
1493              
1494             Okay, so I stole some ideas from L<MooX::Types::MooseLike::Base>.
1495              
1496             =over
1497              
1498             =item *
1499              
1500             B<< InstanceOf[`a] >>
1501              
1502             Shortcut for a union of L<Type::Tiny::Class> constraints.
1503              
1504             B<< InstanceOf["Foo", "Bar"] >> allows objects blessed into the C<Foo>
1505             or C<Bar> classes, or subclasses of those.
1506              
1507             Given no parameters, just equivalent to B<Object>.
1508              
1509             =item *
1510              
1511             B<< ConsumerOf[`a] >>
1512              
1513             Shortcut for an intersection of L<Type::Tiny::Role> constraints.
1514              
1515             B<< ConsumerOf["Foo", "Bar"] >> allows objects where C<< $o->DOES("Foo") >>
1516             and C<< $o->DOES("Bar") >> both return true.
1517              
1518             Given no parameters, just equivalent to B<Object>.
1519              
1520             =item *
1521              
1522             B<< HasMethods[`a] >>
1523              
1524             Shortcut for a L<Type::Tiny::Duck> constraint.
1525              
1526             B<< HasMethods["foo", "bar"] >> allows objects where C<< $o->can("foo") >>
1527             and C<< $o->can("bar") >> both return true.
1528              
1529             Given no parameters, just equivalent to B<Object>.
1530              
1531             =back
1532              
1533             =head2 More
1534              
1535             There are a few other types exported by this module:
1536              
1537             =over
1538              
1539             =item *
1540              
1541             B<< Overload[`a] >>
1542              
1543             With no parameters, checks that the value is an overloaded object. Can
1544             be given one or more string parameters, which are specific operations
1545             to check are overloaded. For example, the following checks for objects
1546             which overload addition and subtraction.
1547              
1548             Overload["+", "-"]
1549              
1550             =item *
1551              
1552             B<< Tied[`a] >>
1553              
1554             A reference to a tied scalar, array or hash.
1555              
1556             Can be parameterized with a type constraint which will be applied to
1557             the object returned by the C<< tied() >> function. As a convenience,
1558             can also be parameterized with a string, which will be inflated to a
1559             L<Type::Tiny::Class>.
1560              
1561             use Types::Standard qw(Tied);
1562             use Type::Utils qw(class_type);
1563            
1564             my $My_Package = class_type { class => "My::Package" };
1565            
1566             tie my %h, "My::Package";
1567             \%h ~~ Tied; # true
1568             \%h ~~ Tied[ $My_Package ]; # true
1569             \%h ~~ Tied["My::Package"]; # true
1570            
1571             tie my $s, "Other::Package";
1572             \$s ~~ Tied; # true
1573             $s ~~ Tied; # false !!
1574              
1575             If you need to check that something is specifically a reference to
1576             a tied hash, use an intersection:
1577              
1578             use Types::Standard qw( Tied HashRef );
1579            
1580             my $TiedHash = (Tied) & (HashRef);
1581            
1582             tie my %h, "My::Package";
1583             tie my $s, "Other::Package";
1584            
1585             \%h ~~ $TiedHash; # true
1586             \$s ~~ $TiedHash; # false
1587              
1588             =item *
1589              
1590             B<< StrMatch[`a] >>
1591              
1592             A string that matches a regular expression:
1593              
1594             declare "Distance",
1595             as StrMatch[ qr{^([0-9]+)\s*(mm|cm|m|km)$} ];
1596              
1597             You can optionally provide a type constraint for the array of subexpressions:
1598              
1599             declare "Distance",
1600             as StrMatch[
1601             qr{^([0-9]+)\s*(.+)$},
1602             Tuple[
1603             Int,
1604             enum(DistanceUnit => [qw/ mm cm m km /]),
1605             ],
1606             ];
1607              
1608             Here's an example using L<Regexp::Common>:
1609              
1610             package Local::Host {
1611             use Moose;
1612             use Regexp::Common;
1613             has ip_address => (
1614             is => 'ro',
1615             required => 1,
1616             isa => StrMatch[qr/^$RE{net}{IPv4}$/],
1617             default => '127.0.0.1',
1618             );
1619             }
1620              
1621             On certain versions of Perl, type constraints of the forms
1622             B<< StrMatch[qr/../ >> and B<< StrMatch[qr/\A..\z/ >> with any number
1623             of intervening dots can be optimized to simple length checks.
1624              
1625             =item *
1626              
1627             B<< Enum[`a] >>
1628              
1629             As per MooX::Types::MooseLike::Base:
1630              
1631             has size => (
1632             is => "ro",
1633             isa => Enum[qw( S M L XL XXL )],
1634             );
1635              
1636             You can enable coercion by passing C<< \1 >> before the list of values.
1637              
1638             has size => (
1639             is => "ro",
1640             isa => Enum[ \1, qw( S M L XL XXL ) ],
1641             coerce => 1,
1642             );
1643              
1644             This will use the C<closest_match> method in L<Type::Tiny::Enum> to
1645             coerce closely matching strings.
1646              
1647             =item *
1648              
1649             B<< OptList >>
1650              
1651             An arrayref of arrayrefs in the style of L<Data::OptList> output.
1652              
1653             =item *
1654              
1655             B<< LaxNum >>, B<< StrictNum >>
1656              
1657             In Moose 2.09, the B<Num> type constraint implementation was changed from
1658             being a wrapper around L<Scalar::Util>'s C<looks_like_number> function to
1659             a stricter regexp (which disallows things like "-Inf" and "Nan").
1660              
1661             Types::Standard provides I<both> implementations. B<LaxNum> is measurably
1662             faster.
1663              
1664             The B<Num> type constraint is currently an alias for B<LaxNum> unless you
1665             set the C<PERL_TYPES_STANDARD_STRICTNUM> environment variable to true before
1666             loading Types::Standard, in which case it becomes an alias for B<StrictNum>.
1667             The constant C<< Types::Standard::STRICTNUM >> can be used to check if
1668             B<Num> is being strict.
1669              
1670             Most people should probably use B<Num> or B<StrictNum>. Don't explicitly
1671             use B<LaxNum> unless you specifically need an attribute which will accept
1672             things like "Inf".
1673              
1674             =item *
1675              
1676             B<< CycleTuple[`a] >>
1677              
1678             Similar to B<Tuple>, but cyclical.
1679              
1680             CycleTuple[Int, HashRef]
1681              
1682             will allow C<< [1,{}] >> and C<< [1,{},2,{}] >> but disallow
1683             C<< [1,{},2] >> and C<< [1,{},2,[]] >>.
1684              
1685             I think you understand B<CycleTuple> already.
1686              
1687             Currently B<Optional> and B<Slurpy> parameters are forbidden. There are
1688             fairly limited use cases for them, and it's not exactly clear what they
1689             should mean.
1690              
1691             The following is an efficient way of checking for an even-sized arrayref:
1692              
1693             CycleTuple[Any, Any]
1694              
1695             The following is an arrayref which would be suitable for coercing to a
1696             hashref:
1697              
1698             CycleTuple[Str, Any]
1699              
1700             All the examples so far have used two parameters, but the following is
1701             also a possible B<CycleTuple>:
1702              
1703             CycleTuple[Str, Int, HashRef]
1704              
1705             This will be an arrayref where the 0th, 3rd, 6th, etc values are
1706             strings, the 1st, 4th, 7th, etc values are integers, and the 2nd,
1707             5th, 8th, etc values are hashrefs.
1708              
1709             =back
1710              
1711             =head2 Coercions
1712              
1713             Most of the types in this type library have no coercions by default.
1714             The exception is B<Bool> as of Types::Standard 1.003_003, which coerces
1715             from B<Any> via C<< !!$_ >>.
1716              
1717             Some standalone coercions may be exported. These can be combined
1718             with type constraints using the C<< plus_coercions >> method.
1719              
1720             =over
1721              
1722             =item *
1723              
1724             B<< MkOpt >>
1725              
1726             A coercion from B<ArrayRef>, B<HashRef> or B<Undef> to B<OptList>. Example
1727             usage in a Moose attribute:
1728              
1729             use Types::Standard qw( OptList MkOpt );
1730            
1731             has options => (
1732             is => "ro",
1733             isa => OptList->plus_coercions( MkOpt ),
1734             coerce => 1,
1735             );
1736              
1737             =item *
1738              
1739             B<< Split[`a] >>
1740              
1741             Split a string on a regexp.
1742              
1743             use Types::Standard qw( ArrayRef Str Split );
1744            
1745             has name => (
1746             is => "ro",
1747             isa => ArrayRef->of(Str)->plus_coercions(Split[qr/\s/]),
1748             coerce => 1,
1749             );
1750              
1751             =item *
1752              
1753             B<< Join[`a] >>
1754              
1755             Join an array of strings with a delimiter.
1756              
1757             use Types::Standard qw( Str Join );
1758            
1759             my $FileLines = Str->plus_coercions(Join["\n"]);
1760            
1761             has file_contents => (
1762             is => "ro",
1763             isa => $FileLines,
1764             coerce => 1,
1765             );
1766              
1767             =back
1768              
1769             =head2 Constants
1770              
1771             =over
1772              
1773             =item C<< Types::Standard::STRICTNUM >>
1774              
1775             Indicates whether B<Num> is an alias for B<StrictNum>. (It is usually an
1776             alias for B<LaxNum>.)
1777              
1778             =back
1779              
1780             =head2 Environment
1781              
1782             =over
1783              
1784             =item C<PERL_TYPES_STANDARD_STRICTNUM>
1785              
1786             Switches to more strict regexp-based number checking instead of using
1787             C<looks_like_number>.
1788              
1789             =item C<PERL_TYPE_TINY_XS>
1790              
1791             If set to false, can be used to suppress the loading of XS implementions of
1792             some type constraints.
1793              
1794             =item C<PERL_ONLY>
1795              
1796             If C<PERL_TYPE_TINY_XS> does not exist, can be set to true to suppress XS
1797             usage similarly. (Several other CPAN distributions also pay attention to this
1798             environment variable.)
1799              
1800             =back
1801              
1802             =begin private
1803              
1804             =item Stringable
1805              
1806             =item LazyLoad
1807              
1808             =end private
1809              
1810             =head1 BUGS
1811              
1812             Please report any bugs to
1813             L<https://github.com/tobyink/p5-type-tiny/issues>.
1814              
1815             =head1 SEE ALSO
1816              
1817             L<The Type::Tiny homepage|https://typetiny.toby.ink/>.
1818              
1819             L<Type::Tiny::Manual>.
1820              
1821             L<Type::Tiny>, L<Type::Library>, L<Type::Utils>, L<Type::Coercion>.
1822              
1823             L<Moose::Util::TypeConstraints>,
1824             L<Mouse::Util::TypeConstraints>,
1825             L<MooseX::Types::Structured>.
1826              
1827             L<Types::XSD> provides some type constraints based on XML Schema's data
1828             types; this includes constraints for ISO8601-formatted datetimes, integer
1829             ranges (e.g. B<< PositiveInteger[maxInclusive=>10] >> and so on.
1830              
1831             L<Types::Encodings> provides B<Bytes> and B<Chars> type constraints that
1832             were formerly found in Types::Standard.
1833              
1834             L<Types::Common::Numeric> and L<Types::Common::String> provide replacements
1835             for L<MooseX::Types::Common>.
1836              
1837             =head1 AUTHOR
1838              
1839             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
1840              
1841             =head1 COPYRIGHT AND LICENCE
1842              
1843             This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.
1844              
1845             This is free software; you can redistribute it and/or modify it under
1846             the same terms as the Perl 5 programming language system itself.
1847              
1848             =head1 DISCLAIMER OF WARRANTIES
1849              
1850             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
1851             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1852             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.