add missing files
[gitmo/MooseX-Types.git] / lib / MooseX / Types.pm
CommitLineData
52d358e2 1package MooseX::Types;
16ddefbf 2use Moose;
8af0a70d 3
4=head1 NAME
5
52d358e2 6MooseX::Types - Organise your Moose types in libraries
8af0a70d 7
8=cut
9
8af0a70d 10use Moose::Util::TypeConstraints;
4c2125a4 11use MooseX::Types::TypeDecorator;
b0db42a9 12use MooseX::Types::Base ();
13use MooseX::Types::Util qw( filter_tags );
52d358e2 14use MooseX::Types::UndefinedType;
b0db42a9 15use MooseX::Types::CheckedUtilExports ();
16use Carp::Clan qw( ^MooseX::Types );
17use Sub::Name;
18use Scalar::Util 'reftype';
9616cebc 19
20use namespace::clean -except => [qw( meta )];
8af0a70d 21
eba48805 22use 5.008;
b0db42a9 23our $VERSION = '0.11';
8af0a70d 24my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
25
26=head1 SYNOPSIS
27
9616cebc 28=head2 Library Definition
29
8af0a70d 30 package MyLibrary;
8af0a70d 31
32 # predeclare our own types
52d358e2 33 use MooseX::Types
475bbd1d 34 -declare => [qw(
35 PositiveInt NegativeInt
36 ArrayRefOfPositiveInt ArrayRefOfAtLeastThreeNegativeInts
37 LotsOfInnerConstraints StrOrArrayRef
38 )];
8af0a70d 39
40 # import builtin types
b0db42a9 41 use MooseX::Types::Moose qw/Int HashRef/;
8af0a70d 42
77134b88 43 # type definition.
8af0a70d 44 subtype PositiveInt,
45 as Int,
46 where { $_ > 0 },
47 message { "Int is not larger than 0" };
48
49 subtype NegativeInt,
50 as Int,
51 where { $_ < 0 },
52 message { "Int is not smaller than 0" };
53
54 # type coercion
55 coerce PositiveInt,
56 from Int,
57 via { 1 };
58
d9002a85 59 # with parameterized constraints.
475bbd1d 60
61 subtype ArrayRefOfPositiveInt,
d9002a85 62 as ArrayRef[PositiveInt];
475bbd1d 63
64 subtype ArrayRefOfAtLeastThreeNegativeInts,
d9002a85 65 as ArrayRef[NegativeInt],
475bbd1d 66 where { scalar(@$_) > 2 };
67
68 subtype LotsOfInnerConstraints,
d9002a85 69 as ArrayRef[ArrayRef[HashRef[Int]]];
475bbd1d 70
71 # with TypeConstraint Unions
72
73 subtype StrOrArrayRef,
74 as Str|ArrayRef;
75
b0db42a9 76 class_type 'DateTime';
77
78 coerce 'DateTime',
79 from HashRef,
80 via { DateTime->new(%$_) };
81
8af0a70d 82 1;
83
9616cebc 84=head2 Usage
85
8af0a70d 86 package Foo;
87 use Moose;
88 use MyLibrary qw( PositiveInt NegativeInt );
89
90 # use the exported constants as type names
91 has 'bar',
92 isa => PositiveInt,
93 is => 'rw';
94 has 'baz',
95 isa => NegativeInt,
96 is => 'rw';
97
98 sub quux {
99 my ($self, $value);
100
101 # test the value
102 print "positive\n" if is_PositiveInt($value);
103 print "negative\n" if is_NegativeInt($value);
104
105 # coerce the value, NegativeInt doesn't have a coercion
106 # helper, since it didn't define any coercions.
107 $value = to_PositiveInt($value) or die "Cannot coerce";
108 }
109
110 1;
111
112=head1 DESCRIPTION
113
114The types provided with L<Moose> are by design global. This package helps
115you to organise and selectively import your own and the built-in types in
116libraries. As a nice side effect, it catches typos at compile-time too.
117
118However, the main reason for this module is to provide an easy way to not
119have conflicts with your type names, since the internal fully qualified
120names of the types will be prefixed with the library's name.
121
122This module will also provide you with some helper functions to make it
123easier to use Moose types in your code.
124
b0db42a9 125String type names will produce a syntax error, unless it's for a C<class_type>
126or C<role_type> declared within the library.
127
8af0a70d 128=head1 TYPE HANDLER FUNCTIONS
129
130=head2 $type
131
132A constant with the name of your type. It contains the type's fully
133qualified name. Takes no value, as all constants.
134
135=head2 is_$type
136
137This handler takes a value and tests if it is a valid value for this
138C<$type>. It will return true or false.
139
140=head2 to_$type
141
142A handler that will take a value and coerce it into the C<$type>. It will
143return a false value if the type could not be coerced.
144
145B<Important Note>: This handler will only be exported for types that can
146do type coercion. This has the advantage that a coercion to a type that
147cannot hasn't defined any coercions will lead to a compile-time error.
148
149=head1 LIBRARY DEFINITION
150
52d358e2 151A MooseX::Types is just a normal Perl module. Unlike Moose
8af0a70d 152itself, it does not install C<use strict> and C<use warnings> in your
153class by default, so this is up to you.
154
155The only thing a library is required to do is
156
52d358e2 157 use MooseX::Types -declare => \@types;
8af0a70d 158
159with C<@types> being a list of types you wish to define in this library.
160This line will install a proper base class in your package as well as the
161full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared
162types. It will then hand control over to L<Moose::Util::TypeConstraints>'
163C<import> method to export the functions you will need to declare your
164types.
165
166If you want to use Moose' built-in types (e.g. for subtyping) you will
167want to
168
52d358e2 169 use MooseX::Types::Moose @types;
8af0a70d 170
52d358e2 171to import the helpers from the shipped L<MooseX::Types::Moose>
8af0a70d 172library which can export all types that come with Moose.
173
174You will have to define coercions for your types or your library won't
175export a L</to_$type> coercion helper for it.
176
21a1dfe2 177Note that you currently cannot define types containing C<::>, since
249888e7 178exporting would be a problem.
179
559cf3d8 180You also don't need to use C<warnings> and C<strict>, since the
181definition of a library automatically exports those.
182
8af0a70d 183=head1 LIBRARY USAGE
184
185You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
186library by C<use>ing it with a list of types to import as arguments. If
187you want all of them, use the C<:all> tag. For example:
188
189 use MyLibrary ':all';
190 use MyOtherLibrary qw( TypeA TypeB );
191
52d358e2 192MooseX::Types comes with a library of Moose' built-in types called
193L<MooseX::Types::Moose>.
8af0a70d 194
16ddefbf 195The exporting mechanism is, since version 0.5, implemented via a wrapper
196around L<Sub::Exporter>. This means you can do something like this:
197
198 use MyLibrary TypeA => { -as => 'MyTypeA' },
199 TypeB => { -as => 'MyTypeB' };
200
c20dc98b 201=head1 WRAPPING A LIBRARY
202
203You can define your own wrapper subclasses to manipulate the behaviour
204of a set of library exports. Here is an example:
205
206 package MyWrapper;
207 use strict;
208 use Class::C3;
52d358e2 209 use base 'MooseX::Types::Wrapper';
c20dc98b 210
211 sub coercion_export_generator {
212 my $class = shift;
213 my $code = $class->next::method(@_);
214 return sub {
215 my $value = $code->(@_);
216 warn "Coercion returned undef!"
217 unless defined $value;
218 return $value;
219 };
220 }
221
222 1;
223
224This class wraps the coercion generator (e.g., C<to_Int()>) and warns
225if a coercion returned an undefined value. You can wrap any library
226with this:
227
228 package Foo;
229 use strict;
230 use MyWrapper MyLibrary => [qw( Foo Bar )],
231 Moose => [qw( Str Int )];
232
233 ...
234 1;
235
236The C<Moose> library name is a special shortcut for
52d358e2 237L<MooseX::Types::Moose>.
c20dc98b 238
239=head2 Generator methods you can overload
240
241=over 4
242
243=item type_export_generator( $short, $full )
244
245Creates a closure returning the type's L<Moose::Meta::TypeConstraint>
246object.
247
248=item check_export_generator( $short, $full, $undef_message )
249
250This creates the closure used to test if a value is valid for this type.
251
252=item coercion_export_generator( $short, $full, $undef_message )
253
254This is the closure that's doing coercions.
255
256=back
257
258=head2 Provided Parameters
259
260=over 4
261
262=item $short
263
264The short, exported name of the type.
265
266=item $full
267
268The fully qualified name of this type as L<Moose> knows it.
269
270=item $undef_message
271
272A message that will be thrown when type functionality is used but the
273type does not yet exist.
274
0ad3779e 275=back
276
077ac262 277=head1 RECURSIVE SUBTYPES
278
279As of version 0.08, L<Moose::Types> has experimental support for Recursive
280subtypes. This will allow:
281
282 subtype Tree() => as HashRef[Str|Tree];
283
284Which validates things like:
285
286 {key=>'value'};
287 {key=>{subkey1=>'value', subkey2=>'value'}}
288
289And so on. This feature is new and there may be lurking bugs so don't be afraid
290to hunt me down with patches and test cases if you have trouble.
291
475bbd1d 292=head1 NOTES REGARDING TYPE UNIONS
293
294L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
295which generally allows you to easily create union types:
296
297 subtype StrOrArrayRef,
298 as Str|ArrayRef;
299
300As with parameterized constrains, this overloading extends to modules using the
301types you define in a type library.
302
303 use Moose;
304 use MooseX::Types::Moose qw(HashRef Int);
305
306 has 'attr' => (isa=>HashRef|Int);
307
308And everything should just work as you'd think.
77134b88 309
8af0a70d 310=head1 METHODS
311
312=head2 import
313
52d358e2 314Installs the L<MooseX::Types::Base> class into the caller and
e211870f 315exports types according to the specification described in
316L</"LIBRARY DEFINITION">. This will continue to
317L<Moose::Util::TypeConstraints>' C<import> method to export helper
318functions you will need to declare your types.
319
8af0a70d 320=cut
321
322sub import {
323 my ($class, %args) = @_;
324 my $callee = caller;
325
559cf3d8 326 # everyone should want this
327 strict->import;
328 warnings->import;
329
8af0a70d 330 # inject base class into new library
331 { no strict 'refs';
52d358e2 332 unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
8af0a70d 333 }
334
335 # generate predeclared type helpers
e211870f 336 if (my @orig_declare = @{ $args{ -declare } || [] }) {
337 my ($tags, $declare) = filter_tags @orig_declare;
16ddefbf 338 my @to_export;
e211870f 339
340 for my $type (@$declare) {
249888e7 341
342 croak "Cannot create a type containing '::' ($type) at the moment"
343 if $type =~ /::/;
344
16ddefbf 345 # add type to library and remember to export
8af0a70d 346 $callee->add_type($type);
16ddefbf 347 push @to_export, $type;
8af0a70d 348 }
16ddefbf 349
350 $callee->import({ -full => 1, -into => $callee }, @to_export);
8af0a70d 351 }
352
353 # run type constraints import
b0db42a9 354 Moose::Util::TypeConstraints->import({ into => $callee });
355
356 # override some with versions that check for syntax errors
357 MooseX::Types::CheckedUtilExports->import({ into => $callee });
358
359 1;
8af0a70d 360}
361
362=head2 type_export_generator
363
e211870f 364Generate a type export, e.g. C<Int()>. This will return either a
365L<Moose::Meta::TypeConstraint> object, or alternatively a
52d358e2 366L<MooseX::Types::UndefinedType> object if the type was not
e211870f 367yet defined.
368
8af0a70d 369=cut
370
371sub type_export_generator {
a706b0f2 372 my ($class, $type, $name) = @_;
686e5888 373
374 ## Return an anonymous subroutine that will generate the proxied type
375 ## constraint for you.
376
b0db42a9 377 return subname $name => sub {
378 my $type_constraint = $class->create_base_type_constraint($name);
379
e088dd03 380 if(defined(my $params = shift @_)) {
686e5888 381 ## We currently only allow a TC to accept a single, ArrayRef
382 ## parameter, as in HashRef[Int], where [Int] is what's inside the
383 ## ArrayRef passed.
b0db42a9 384 if(reftype $params eq 'ARRAY') {
e088dd03 385 $type_constraint = $class->create_arged_type_constraint($name, @$params);
b0db42a9 386 } elsif(!defined $type_constraint) {
387 croak "Syntax error in type definition (did you forget a comma"
388 . " after $type?)";
e088dd03 389 } else {
b0db42a9 390 croak "Argument must be an ArrayRef to create a parameterized "
391 . "type, Eg.: ${type}[Int]. Got: ".ref($params)."."
e088dd03 392 }
e088dd03 393 }
e7d06577 394
e088dd03 395 $type_constraint = defined($type_constraint) ? $type_constraint
396 : MooseX::Types::UndefinedType->new($name);
475bbd1d 397
d9002a85 398 my $type_decorator = $class->create_type_decorator($type_constraint);
bb5b7b28 399
686e5888 400 ## If there are additional args, that means it's probably stuff that
401 ## needs to be returned to the subtype. Not an ideal solution here but
402 ## doesn't seem to cause trouble.
403
d9002a85 404 if(@_) {
405 return ($type_decorator, @_);
406 } else {
407 return $type_decorator;
408 }
e211870f 409 };
8af0a70d 410}
411
a706b0f2 412=head2 create_arged_type_constraint ($name, @args)
413
686e5888 414Given a String $name with @args find the matching typeconstraint and parameterize
415it with @args.
a706b0f2 416
417=cut
418
419sub create_arged_type_constraint {
371efa05 420 my ($class, $name, @args) = @_;
421 my $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint("$name");
686e5888 422 return $type_constraint->parameterize(@args);
a706b0f2 423}
424
425=head2 create_base_type_constraint ($name)
426
427Given a String $name, find the matching typeconstraint.
428
429=cut
430
431sub create_base_type_constraint {
432 my ($class, $name) = @_;
433 return find_type_constraint($name);
434}
435
436=head2 create_type_decorator ($type_constraint)
437
438Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
439instance.
440
441=cut
442
443sub create_type_decorator {
444 my ($class, $type_constraint) = @_;
475bbd1d 445 return MooseX::Types::TypeDecorator->new($type_constraint);
a706b0f2 446}
447
8af0a70d 448=head2 coercion_export_generator
449
e211870f 450This generates a coercion handler function, e.g. C<to_Int($value)>.
451
8af0a70d 452=cut
453
454sub coercion_export_generator {
455 my ($class, $type, $full, $undef_msg) = @_;
456 return sub {
457 my ($value) = @_;
458
459 # we need a type object
460 my $tobj = find_type_constraint($full) or croak $undef_msg;
461 my $return = $tobj->coerce($value);
462
463 # non-successful coercion returns false
464 return unless $tobj->check($return);
465
466 return $return;
467 }
468}
469
470=head2 check_export_generator
471
e211870f 472Generates a constraint check closure, e.g. C<is_Int($value)>.
473
8af0a70d 474=cut
475
476sub check_export_generator {
477 my ($class, $type, $full, $undef_msg) = @_;
478 return sub {
479 my ($value) = @_;
480
481 # we need a type object
482 my $tobj = find_type_constraint($full) or croak $undef_msg;
483
484 return $tobj->check($value);
485 }
486}
487
e211870f 488=head1 CAVEATS
489
686e5888 490The following are lists of gotcha's and their workarounds for developers coming
491from the standard string based type constraint names
492
493=head2 Uniqueness
494
e211870f 495A library makes the types quasi-unique by prefixing their names with (by
496default) the library package name. If you're only using the type handler
52d358e2 497functions provided by MooseX::Types, you shouldn't ever have to use
e211870f 498a type's actual full name.
499
686e5888 500=head2 Argument separation ('=>' versus ',')
501
502The Perlop manpage has this to say about the '=>' operator: "The => operator is
503a synonym for the comma, but forces any word (consisting entirely of word
504characters) to its left to be interpreted as a string (as of 5.001). This
505includes words that might otherwise be considered a constant or function call."
506
507Due to this stringification, the following will NOT work as you might think:
508
509 subtype StrOrArrayRef => as Str|ArrayRef;
510
511The 'StrOrArrayRef' will have it's stringification activated this causes the
512subtype to not be created. Since the bareword type constraints are not strings
513you really should not try to treat them that way. You will have to use the ','
514operator instead. The author's of this package realize that all the L<Moose>
515documention and examples nearly uniformly use the '=>' version of the comma
516operator and this could be an issue if you are converting code.
517
518Patches welcome for discussion.
077ac262 519
520=head2 Compatibility with Sub::Exporter
521
522If you want to use L<Sub::Exporter> with a Type Library, you need to make sure
523you export all the type constraints declared AS WELL AS any additional export
524targets. For example if you do:
525
526 package TypeAndSubExporter; {
527
528 use MooseX::Types::Moose qw(Str);
529 use MooseX::Types -declare => [qw(MyStr)];
530 use Sub::Exporter -setup => { exports => [ qw(something) ] };
531
532 subtype MyStr,
533 as Str;
534
535 sub something {
536 return 1;
537 }
538
539 } 1;
540
541 package Foo; {
542 use TypeAndSubExporter qw(MyStr);
543 } 1;
544
545You'll get a '"MyStr" is not exported by the TypeAndSubExporter module' error.
546Upi can workaround by:
547
548 - use Sub::Exporter -setup => { exports => [ qw(something) ] };
549 + use Sub::Exporter -setup => { exports => [ qw(something MyStr) ] };
550
551This is a workaround and I am exploring how to make these modules work better
552together. I realize this workaround will lead a lot of duplication in your
553export declarations and will be onerous for large type libraries. Patches and
554detailed test cases welcome. See the tests directory for a start on this.
686e5888 555
8af0a70d 556=head1 SEE ALSO
557
16ddefbf 558L<Moose>,
559L<Moose::Util::TypeConstraints>,
560L<MooseX::Types::Moose>,
561L<Sub::Exporter>
8af0a70d 562
563=head1 AUTHOR AND COPYRIGHT
564
565Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
566the C<#moose> cabal on C<irc.perl.org>.
567
475bbd1d 568Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
569
8af0a70d 570=head1 LICENSE
571
572This program is free software; you can redistribute it and/or modify
573it under the same terms as perl itself.
574
575=cut
576
5771;