bah
[gitmo/Moose.git] / lib / Moose / Meta / TypeCoercion.pm
CommitLineData
6bf30233 1
2package Moose::Meta::TypeCoercion;
3
4use strict;
5use warnings;
6use metaclass;
7
8use Carp 'confess';
9
a27aa600 10use Moose::Meta::Attribute;
a3c7e2fe 11use Moose::Util::TypeConstraints ();
a27aa600 12
eaa35e6e 13our $VERSION = '0.50';
d44714be 14our $AUTHORITY = 'cpan:STEVAN';
6bf30233 15
a27aa600 16__PACKAGE__->meta->add_attribute('type_coercion_map' => (
17 reader => 'type_coercion_map',
18 default => sub { [] }
19));
d44714be 20
a27aa600 21__PACKAGE__->meta->add_attribute(
22 Moose::Meta::Attribute->new('type_constraint' => (
23 reader => 'type_constraint',
24 weak_ref => 1
25 ))
26);
27
28# private accessor
29__PACKAGE__->meta->add_attribute('compiled_type_coercion' => (
30 accessor => '_compiled_type_coercion'
31));
32
33sub new {
34 my $class = shift;
35 my $self = $class->meta->new_object(@_);
41e007e4 36 $self->compile_type_coercion;
a27aa600 37 return $self;
38}
39
40sub compile_type_coercion {
41 my $self = shift;
42 my @coercion_map = @{$self->type_coercion_map};
43 my @coercions;
44 while (@coercion_map) {
45 my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
9c637fca 46 my $type_constraint = ref $constraint_name ? $constraint_name : Moose::Util::TypeConstraints::find_or_parse_type_constraint($constraint_name);
e95c7c42 47 (defined $type_constraint)
48 || confess "Could not find the type constraint ($constraint_name) to coerce from";
49 push @coercions => [
50 $type_constraint->_compiled_type_constraint,
51 $action
52 ];
a27aa600 53 }
54 $self->_compiled_type_coercion(sub {
55 my $thing = shift;
56 foreach my $coercion (@coercions) {
57 my ($constraint, $converter) = @$coercion;
42bc21a4 58 if ($constraint->($thing)) {
6f9ff1af 59 local $_ = $thing;
a27aa600 60 return $converter->($thing);
61 }
62 }
63 return $thing;
64 });
65}
66
41e007e4 67sub has_coercion_for_type {
68 my ($self, $type_name) = @_;
69 my %coercion_map = @{$self->type_coercion_map};
70 exists $coercion_map{$type_name} ? 1 : 0;
71}
72
73sub add_type_coercions {
74 my ($self, @new_coercion_map) = @_;
75
76 my $coercion_map = $self->type_coercion_map;
77 my %has_coercion = @$coercion_map;
78
79 while (@new_coercion_map) {
80 my ($constraint_name, $action) = splice(@new_coercion_map, 0, 2);
81
82 confess "A coercion action already exists for '$constraint_name'"
83 if exists $has_coercion{$constraint_name};
84
85 push @{$coercion_map} => ($constraint_name, $action);
86 }
87
88 # and re-compile ...
89 $self->compile_type_coercion;
90}
91
a27aa600 92sub coerce { $_[0]->_compiled_type_coercion->($_[1]) }
93
94
6bf30233 951;
96
97__END__
98
99=pod
100
101=head1 NAME
102
6ba6d68c 103Moose::Meta::TypeCoercion - The Moose Type Coercion metaclass
6bf30233 104
105=head1 DESCRIPTION
106
6ba6d68c 107For the most part, the only time you will ever encounter an
108instance of this class is if you are doing some serious deep
109introspection. This API should not be considered final, but
110it is B<highly unlikely> that this will matter to a regular
111Moose user.
112
113If you wish to use features at this depth, please come to the
114#moose IRC channel on irc.perl.org and we can talk :)
115
6bf30233 116=head1 METHODS
117
118=over 4
119
120=item B<meta>
121
a27aa600 122=item B<new>
123
a27aa600 124=item B<compile_type_coercion>
125
6ba6d68c 126=item B<coerce>
127
a27aa600 128=item B<type_coercion_map>
129
130=item B<type_constraint>
131
41e007e4 132=item B<has_coercion_for_type>
133
134=item B<add_type_coercions>
135
6bf30233 136=back
137
138=head1 BUGS
139
140All complex software has bugs lurking in it, and this module is no
141exception. If you find a bug please either email me, or add the bug
142to cpan-RT.
143
144=head1 AUTHOR
145
146Stevan Little E<lt>stevan@iinteractive.comE<gt>
147
148=head1 COPYRIGHT AND LICENSE
149
778db3ac 150Copyright 2006-2008 by Infinity Interactive, Inc.
6bf30233 151
152L<http://www.iinteractive.com>
153
154This library is free software; you can redistribute it and/or modify
155it under the same terms as Perl itself.
156
42bc21a4 157=cut