Bumped version to 0.05
[gitmo/MooseX-Types.git] / lib / MooseX / Types.pm
CommitLineData
52d358e2 1package MooseX::Types;
8af0a70d 2
3=head1 NAME
4
52d358e2 5MooseX::Types - Organise your Moose types in libraries
8af0a70d 6
7=cut
8
3df5416a 9#use warnings;
10#use strict;
8af0a70d 11
12use Sub::Uplevel;
13use Moose::Util::TypeConstraints;
9616cebc 14use MooseX::Types::Base ();
15use MooseX::Types::Util qw( filter_tags );
52d358e2 16use MooseX::Types::UndefinedType;
9616cebc 17use Sub::Install qw( install_sub );
249888e7 18use Carp qw( croak );
3df5416a 19use Moose;
9616cebc 20
21use namespace::clean -except => [qw( meta )];
8af0a70d 22
badcd0e5 23our $VERSION = 0.05;
8af0a70d 24
25my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
26
27=head1 SYNOPSIS
28
9616cebc 29=head2 Library Definition
30
8af0a70d 31 package MyLibrary;
8af0a70d 32
33 # predeclare our own types
52d358e2 34 use MooseX::Types
8af0a70d 35 -declare => [qw( PositiveInt NegativeInt )];
36
37 # import builtin types
52d358e2 38 use MooseX::Types::Moose 'Int';
8af0a70d 39
40 # type definition
41 subtype PositiveInt,
42 as Int,
43 where { $_ > 0 },
44 message { "Int is not larger than 0" };
45
46 subtype NegativeInt,
47 as Int,
48 where { $_ < 0 },
49 message { "Int is not smaller than 0" };
50
51 # type coercion
52 coerce PositiveInt,
53 from Int,
54 via { 1 };
55
56 1;
57
9616cebc 58=head2 Usage
59
8af0a70d 60 package Foo;
61 use Moose;
62 use MyLibrary qw( PositiveInt NegativeInt );
63
64 # use the exported constants as type names
65 has 'bar',
66 isa => PositiveInt,
67 is => 'rw';
68 has 'baz',
69 isa => NegativeInt,
70 is => 'rw';
71
72 sub quux {
73 my ($self, $value);
74
75 # test the value
76 print "positive\n" if is_PositiveInt($value);
77 print "negative\n" if is_NegativeInt($value);
78
79 # coerce the value, NegativeInt doesn't have a coercion
80 # helper, since it didn't define any coercions.
81 $value = to_PositiveInt($value) or die "Cannot coerce";
82 }
83
84 1;
85
86=head1 DESCRIPTION
87
88The types provided with L<Moose> are by design global. This package helps
89you to organise and selectively import your own and the built-in types in
90libraries. As a nice side effect, it catches typos at compile-time too.
91
92However, the main reason for this module is to provide an easy way to not
93have conflicts with your type names, since the internal fully qualified
94names of the types will be prefixed with the library's name.
95
96This module will also provide you with some helper functions to make it
97easier to use Moose types in your code.
98
99=head1 TYPE HANDLER FUNCTIONS
100
101=head2 $type
102
103A constant with the name of your type. It contains the type's fully
104qualified name. Takes no value, as all constants.
105
106=head2 is_$type
107
108This handler takes a value and tests if it is a valid value for this
109C<$type>. It will return true or false.
110
111=head2 to_$type
112
113A handler that will take a value and coerce it into the C<$type>. It will
114return a false value if the type could not be coerced.
115
116B<Important Note>: This handler will only be exported for types that can
117do type coercion. This has the advantage that a coercion to a type that
118cannot hasn't defined any coercions will lead to a compile-time error.
119
120=head1 LIBRARY DEFINITION
121
52d358e2 122A MooseX::Types is just a normal Perl module. Unlike Moose
8af0a70d 123itself, it does not install C<use strict> and C<use warnings> in your
124class by default, so this is up to you.
125
126The only thing a library is required to do is
127
52d358e2 128 use MooseX::Types -declare => \@types;
8af0a70d 129
130with C<@types> being a list of types you wish to define in this library.
131This line will install a proper base class in your package as well as the
132full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared
133types. It will then hand control over to L<Moose::Util::TypeConstraints>'
134C<import> method to export the functions you will need to declare your
135types.
136
137If you want to use Moose' built-in types (e.g. for subtyping) you will
138want to
139
52d358e2 140 use MooseX::Types::Moose @types;
8af0a70d 141
52d358e2 142to import the helpers from the shipped L<MooseX::Types::Moose>
8af0a70d 143library which can export all types that come with Moose.
144
145You will have to define coercions for your types or your library won't
146export a L</to_$type> coercion helper for it.
147
21a1dfe2 148Note that you currently cannot define types containing C<::>, since
249888e7 149exporting would be a problem.
150
559cf3d8 151You also don't need to use C<warnings> and C<strict>, since the
152definition of a library automatically exports those.
153
8af0a70d 154=head1 LIBRARY USAGE
155
156You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
157library by C<use>ing it with a list of types to import as arguments. If
158you want all of them, use the C<:all> tag. For example:
159
160 use MyLibrary ':all';
161 use MyOtherLibrary qw( TypeA TypeB );
162
52d358e2 163MooseX::Types comes with a library of Moose' built-in types called
164L<MooseX::Types::Moose>.
8af0a70d 165
c20dc98b 166=head1 WRAPPING A LIBRARY
167
168You can define your own wrapper subclasses to manipulate the behaviour
169of a set of library exports. Here is an example:
170
171 package MyWrapper;
172 use strict;
173 use Class::C3;
52d358e2 174 use base 'MooseX::Types::Wrapper';
c20dc98b 175
176 sub coercion_export_generator {
177 my $class = shift;
178 my $code = $class->next::method(@_);
179 return sub {
180 my $value = $code->(@_);
181 warn "Coercion returned undef!"
182 unless defined $value;
183 return $value;
184 };
185 }
186
187 1;
188
189This class wraps the coercion generator (e.g., C<to_Int()>) and warns
190if a coercion returned an undefined value. You can wrap any library
191with this:
192
193 package Foo;
194 use strict;
195 use MyWrapper MyLibrary => [qw( Foo Bar )],
196 Moose => [qw( Str Int )];
197
198 ...
199 1;
200
201The C<Moose> library name is a special shortcut for
52d358e2 202L<MooseX::Types::Moose>.
c20dc98b 203
204=head2 Generator methods you can overload
205
206=over 4
207
208=item type_export_generator( $short, $full )
209
210Creates a closure returning the type's L<Moose::Meta::TypeConstraint>
211object.
212
213=item check_export_generator( $short, $full, $undef_message )
214
215This creates the closure used to test if a value is valid for this type.
216
217=item coercion_export_generator( $short, $full, $undef_message )
218
219This is the closure that's doing coercions.
220
221=back
222
223=head2 Provided Parameters
224
225=over 4
226
227=item $short
228
229The short, exported name of the type.
230
231=item $full
232
233The fully qualified name of this type as L<Moose> knows it.
234
235=item $undef_message
236
237A message that will be thrown when type functionality is used but the
238type does not yet exist.
239
240=back
241
8af0a70d 242=head1 METHODS
243
244=head2 import
245
52d358e2 246Installs the L<MooseX::Types::Base> class into the caller and
e211870f 247exports types according to the specification described in
248L</"LIBRARY DEFINITION">. This will continue to
249L<Moose::Util::TypeConstraints>' C<import> method to export helper
250functions you will need to declare your types.
251
8af0a70d 252=cut
253
254sub import {
255 my ($class, %args) = @_;
256 my $callee = caller;
257
559cf3d8 258 # everyone should want this
259 strict->import;
260 warnings->import;
261
8af0a70d 262 # inject base class into new library
263 { no strict 'refs';
52d358e2 264 unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
8af0a70d 265 }
266
267 # generate predeclared type helpers
e211870f 268 if (my @orig_declare = @{ $args{ -declare } || [] }) {
269 my ($tags, $declare) = filter_tags @orig_declare;
270
271 for my $type (@$declare) {
249888e7 272
273 croak "Cannot create a type containing '::' ($type) at the moment"
274 if $type =~ /::/;
275
8af0a70d 276 $callee->add_type($type);
277 $callee->export_type_into(
278 $callee, $type,
279 sprintf($UndefMsg, $type, $callee),
280 -full => 1,
281 );
282 }
283 }
284
285 # run type constraints import
c20dc98b 286 return Moose::Util::TypeConstraints->import({ into => $callee });
8af0a70d 287}
288
289=head2 type_export_generator
290
e211870f 291Generate a type export, e.g. C<Int()>. This will return either a
292L<Moose::Meta::TypeConstraint> object, or alternatively a
52d358e2 293L<MooseX::Types::UndefinedType> object if the type was not
e211870f 294yet defined.
295
8af0a70d 296=cut
297
298sub type_export_generator {
299 my ($class, $type, $full) = @_;
e211870f 300 return sub {
301 return find_type_constraint($full)
52d358e2 302 || MooseX::Types::UndefinedType->new($full);
e211870f 303 };
8af0a70d 304}
305
306=head2 coercion_export_generator
307
e211870f 308This generates a coercion handler function, e.g. C<to_Int($value)>.
309
8af0a70d 310=cut
311
312sub coercion_export_generator {
313 my ($class, $type, $full, $undef_msg) = @_;
314 return sub {
315 my ($value) = @_;
316
317 # we need a type object
318 my $tobj = find_type_constraint($full) or croak $undef_msg;
319 my $return = $tobj->coerce($value);
320
321 # non-successful coercion returns false
322 return unless $tobj->check($return);
323
324 return $return;
325 }
326}
327
328=head2 check_export_generator
329
e211870f 330Generates a constraint check closure, e.g. C<is_Int($value)>.
331
8af0a70d 332=cut
333
334sub check_export_generator {
335 my ($class, $type, $full, $undef_msg) = @_;
336 return sub {
337 my ($value) = @_;
338
339 # we need a type object
340 my $tobj = find_type_constraint($full) or croak $undef_msg;
341
342 return $tobj->check($value);
343 }
344}
345
e211870f 346=head1 CAVEATS
347
348A library makes the types quasi-unique by prefixing their names with (by
349default) the library package name. If you're only using the type handler
52d358e2 350functions provided by MooseX::Types, you shouldn't ever have to use
e211870f 351a type's actual full name.
352
8af0a70d 353=head1 SEE ALSO
354
52d358e2 355L<Moose>, L<Moose::Util::TypeConstraints>, L<MooseX::Types::Moose>
8af0a70d 356
357=head1 AUTHOR AND COPYRIGHT
358
359Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
360the C<#moose> cabal on C<irc.perl.org>.
361
362=head1 LICENSE
363
364This program is free software; you can redistribute it and/or modify
365it under the same terms as perl itself.
366
367=cut
368
3691;