use Scalar::Util 'blessed';
use Carp 'confess';
+use Moose::Util::TypeConstraints;
our $VERSION = '0.01';
our $AUTHORITY = 'cpan:STEVAN';
|| confess "The type parameter must be a Moose meta type";
my $constraint;
-
+ my $name = $self->parent->name;
+
+ my $array_coercion =
+ Moose::Util::TypeConstraints::find_type_constraint('ArrayRef')
+ ->coercion;
+
+ my $hash_coercion =
+ Moose::Util::TypeConstraints::find_type_constraint('HashRef')
+ ->coercion;
+
my $array_constraint = sub {
foreach my $x (@$_) {
($type_parameter->check($x)) || return
elsif ($self->is_subtype_of('HashRef')) {
$constraint = $hash_constraint;
}
+ elsif ($array_coercion && $array_coercion->has_coercion_for_type($name)) {
+ $constraint = sub {
+ local $_ = $array_coercion->coerce($_);
+ $array_constraint->(@_);
+ };
+ }
+ elsif ($hash_coercion && $hash_coercion->has_coercion_for_type($name)) {
+ $constraint = sub {
+ local $_ = $hash_coercion->coerce($_);
+ $hash_constraint->(@_);
+ };
+ }
else {
- confess "The " . $self->name . " constraint cannot be used, because " . $self->parent->name . " doesn't subtype ArrayRef or HashRef.";
+ confess "The " . $self->name . " constraint cannot be used, because " . $name . " doesn't subtype or coerce ArrayRef or HashRef.";
}
$self->_set_constraint($constraint);
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+use Test::Exception;
+
+BEGIN {
+ use_ok("Moose::Util::TypeConstraints");
+ use_ok('Moose::Meta::TypeConstraint::Parameterized');
+}
+
+BEGIN {
+ package MyList;
+ sub new {
+ my $class = shift;
+ bless { items => \@_ }, $class;
+ }
+
+ sub items {
+ my $self = shift;
+ return @{ $self->{items} };
+ }
+}
+
+subtype 'MyList' => as 'Object' => where { $_->isa('MyList') };
+
+lives_ok {
+ coerce 'ArrayRef'
+ => from 'MyList'
+ => via { [ $_->items ] }
+} '... created the coercion okay';
+
+my $mylist = Moose::Meta::TypeConstraint::Parameterized->new(
+ name => 'MyList[Int]',
+ parent => find_type_constraint('MyList'),
+ type_parameter => find_type_constraint('Int'),
+);
+
+ok($mylist->check(MyList->new(10, 20, 30)), '... validated it correctly');
+ok(!$mylist->check(MyList->new(10, "two")), '... validated it correctly');
+ok(!$mylist->check([10]), '... validated it correctly');
+
+subtype 'EvenList' => as 'MyList' => where { $_->items % 2 == 0 };
+
+# XXX: get this to work *without* the declaration. I suspect it'll be a new
+# method in Moose::Meta::TypeCoercion that will look at the parents of the
+# coerced type as well. but will that be too "action at a distance"-ey?
+lives_ok {
+ coerce 'ArrayRef'
+ => from 'EvenList'
+ => via { [ $_->items ] }
+} '... created the coercion okay';
+
+my $evenlist = Moose::Meta::TypeConstraint::Parameterized->new(
+ name => 'EvenList[Int]',
+ parent => find_type_constraint('EvenList'),
+ type_parameter => find_type_constraint('Int'),
+);
+
+ok(!$evenlist->check(MyList->new(10, 20, 30)), '... validated it correctly');
+ok($evenlist->check(MyList->new(10, 20, 30, 40)), '... validated it correctly');
+ok(!$evenlist->check(MyList->new(10, "two")), '... validated it correctly');
+ok(!$evenlist->check([10, 20]), '... validated it correctly');
+