bump version to 0.89
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint / DuckType.pm
CommitLineData
0a6bff54 1package Moose::Meta::TypeConstraint::DuckType;
2
3use strict;
4use warnings;
5use metaclass;
6
7use List::MoreUtils qw(all);
8use Moose::Util 'english_list';
9
10use Moose::Util::TypeConstraints ();
11
b9e554fa 12our $VERSION = '0.89';
0a6bff54 13$VERSION = eval $VERSION;
14our $AUTHORITY = 'cpan:STEVAN';
15
16use base 'Moose::Meta::TypeConstraint';
17
18__PACKAGE__->meta->add_attribute('methods' => (
19 accessor => 'methods',
20));
21
22sub new {
23 my ( $class, %args ) = @_;
24
25 $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Object');
26
27 my $self = $class->_new(\%args);
28
29 $self->compile_type_constraint()
30 unless $self->_has_compiled_type_constraint;
31
32 return $self;
33}
34
35sub equals {
36 my ( $self, $type_or_name ) = @_;
37
38 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
39
40 return unless $other->isa(__PACKAGE__);
41
42 my @self_methods = sort @{ $self->methods };
43 my @other_methods = sort @{ $other->methods };
44
45 return unless @self_methods == @other_methods;
46
47 while ( @self_methods ) {
48 my $method = shift @self_methods;
49 my $other_method = shift @other_methods;
50
51 return unless $method eq $other_method;
52 }
53
54 return 1;
55}
56
57sub constraint {
58 my $self = shift;
59
60 my @methods = @{ $self->methods };
61
62 return sub {
63 my $obj = shift;
64 return all { $obj->can($_) } @methods
65 };
66}
67
68sub _compile_hand_optimized_type_constraint {
69 my $self = shift;
70
71 my @methods = @{ $self->methods };
72
73 sub {
74 my $obj = shift;
75
76 return blessed($obj)
77 && blessed($obj) ne 'Regexp'
78 && all { $obj->can($_) } @methods;
79 };
80}
81
82sub create_child_type {
83 my ($self, @args) = @_;
84 return Moose::Meta::TypeConstraint->new(@args, parent => $self);
85}
86
87sub get_message {
88 my $self = shift;
89 my ($value) = @_;
90
91 if ($self->has_message) {
92 return $self->SUPER::get_message(@_);
93 }
94
95 my @methods = grep { !$value->can($_) } @{ $self->methods };
96 my $class = blessed $value;
97 return $class
98 . " is missing methods "
99 . english_list(map { "'$_'" } @methods);
100}
101
1021;
103
104__END__
105
106=pod
107
108=head1 NAME
109
110Moose::Meta::TypeConstraint::DuckType - Type constraint for duck typing
111
112=head1 DESCRIPTION
113
114This class represents type constraints based on an enumerated list of
115required methods.
116
117=head1 INHERITANCE
118
119C<Moose::Meta::TypeConstraint::DuckType> is a subclass of
120L<Moose::Meta::TypeConstraint>.
121
122=head1 METHODS
123
124=over 4
125
126=item B<< Moose::Meta::TypeConstraint::DuckType->new(%options) >>
127
128This creates a new duck type constraint based on the given
129C<%options>.
130
131It takes the same options as its parent, with several
132exceptions. First, it requires an additional option, C<methods>. This
133should be an array reference containing a list of required method
134names. Second, it automatically sets the parent to the C<Object> type.
135
136Finally, it ignores any provided C<constraint> option. The constraint
137is generated automatically based on the provided C<methods>.
138
139=item B<< $constraint->methods >>
140
141Returns the array reference of required methods provided to the
142constructor.
143
144=item B<< $constraint->create_child_type >>
145
146This returns a new L<Moose::Meta::TypeConstraint> object with the type
147as its parent.
148
149Note that it does I<not> return a C<Moose::Meta::TypeConstraint::DuckType>
150object!
151
152=back
153
154=head1 BUGS
155
156All complex software has bugs lurking in it, and this module is no
157exception. If you find a bug please either email me, or add the bug
158to cpan-RT.
159
160=head1 AUTHOR
161
162Chris Prather E<lt>chris@prather.orgE<gt>
163
164Shawn M Moore E<lt>sartak@gmail.comE<gt>
165
166=head1 COPYRIGHT AND LICENSE
167
168Copyright 2006-2009 by Infinity Interactive, Inc.
169
170L<http://www.iinteractive.com>
171
172This library is free software; you can redistribute it and/or modify
173it under the same terms as Perl itself.
174
175=cut
176