X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMouse%2FTypeRegistry.pm;h=4a97237fa38ecbc9278e2f703ffabb4da484ab43;hb=b3b74cc602b1f2490396e407aa38970b5aa6921a;hp=c1f4d36019911d074612429e1c4731ab31aeb154;hpb=61a02a3addc8542afac0bbd222610d7e050137ce;p=gitmo%2FMouse.git diff --git a/lib/Mouse/TypeRegistry.pm b/lib/Mouse/TypeRegistry.pm index c1f4d36..4a97237 100644 --- a/lib/Mouse/TypeRegistry.pm +++ b/lib/Mouse/TypeRegistry.pm @@ -6,18 +6,15 @@ use warnings; use Carp (); use Mouse::Util qw/blessed looks_like_number openhandle/; -my $SUBTYPE = +{}; -my $COERCE = +{}; +my %SUBTYPE; +my %COERCE; +my %COERCE_KEYS; +#find_type_constraint register_type_constraint sub import { my $class = shift; my %args = @_; - my $caller = caller(0); - - if (defined $args{'-export'} && ref($args{'-export'}) eq 'ARRAY') { - no strict 'refs'; - *{"$caller\::import"} = sub { _import(@_) }; - } + my $caller = $args{callee} || caller(0); no strict 'refs'; *{"$caller\::as"} = \&_as; @@ -47,42 +44,79 @@ sub _via (&) { $_[0] } -sub _import { - my($class, @types) = @_; - return unless exists $SUBTYPE->{$class} && exists $COERCE->{$class}; - my $pkg = caller(1); - return unless @types; - copy_types($class, $pkg, @types); +my $optimized_constraints; +my $optimized_constraints_base; +{ + no warnings 'uninitialized'; + %SUBTYPE = ( + Any => sub { 1 }, + Item => sub { 1 }, + Bool => sub { + !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' + }, + Undef => sub { !defined($_) }, + Defined => sub { defined($_) }, + Value => sub { defined($_) && !ref($_) }, + Num => sub { !ref($_) && looks_like_number($_) }, + Int => sub { defined($_) && !ref($_) && /^-?[0-9]+$/ }, + Str => sub { defined($_) && !ref($_) }, + ClassName => sub { Mouse::is_class_loaded($_) }, + Ref => sub { ref($_) }, + + ScalarRef => sub { ref($_) eq 'SCALAR' }, + ArrayRef => sub { ref($_) eq 'ARRAY' }, + HashRef => sub { ref($_) eq 'HASH' }, + CodeRef => sub { ref($_) eq 'CODE' }, + RegexpRef => sub { ref($_) eq 'Regexp' }, + GlobRef => sub { ref($_) eq 'GLOB' }, + + FileHandle => sub { + ref($_) eq 'GLOB' + && openhandle($_) + or + blessed($_) + && $_->isa("IO::Handle") + }, + + Object => sub { blessed($_) && blessed($_) ne 'Regexp' }, + ); + + sub optimized_constraints { \%SUBTYPE } + my @SUBTYPE_KEYS = keys %SUBTYPE; + sub list_all_builtin_type_constraints { @SUBTYPE_KEYS } } sub _subtype { my $pkg = caller(0); my($name, %conf) = @_; - if (my $type = $SUBTYPE->{$name}) { + if (my $type = $SUBTYPE{$name}) { Carp::croak "The type constraint '$name' has already been created, cannot be created again in $pkg"; }; my $as = $conf{as}; - my $stuff = $conf{where} || optimized_constraints()->{$as}; + my $stuff = $conf{where} || $SUBTYPE{$as}; - $SUBTYPE->{$name} = $stuff; + $SUBTYPE{$name} = $stuff; } sub _coerce { my($name, %conf) = @_; Carp::croak "Cannot find type '$name', perhaps you forgot to load it." - unless optimized_constraints()->{$name}; + unless $SUBTYPE{$name}; - my $subtypes = optimized_constraints(); - $COERCE->{$name} ||= {}; + unless ($COERCE{$name}) { + $COERCE{$name} = {}; + $COERCE_KEYS{$name} = []; + } while (my($type, $code) = each %conf) { Carp::croak "A coercion action already exists for '$type'" - if $COERCE->{$name}->{$type}; + if $COERCE{$name}->{$type}; Carp::croak "Could not find the type constraint ($type) to coerce from" - unless $subtypes->{$type}; + unless $SUBTYPE{$type}; - $COERCE->{$name}->{$type} = $code; + push @{ $COERCE_KEYS{$name} }, $type; + $COERCE{$name}->{$type} = $code; } } @@ -109,60 +143,22 @@ sub _role_type { } sub typecast_constraints { - my($class, $pkg, $type, $value) = @_; - return $value unless $COERCE->{$type}; - - my $optimized_constraints = optimized_constraints(); - for my $coerce_type (keys %{ $COERCE->{$type} }) { - local $_ = $value; - if ($optimized_constraints->{$coerce_type}->()) { - local $_ = $value; - return $COERCE->{$type}->{$coerce_type}->(); + my($class, $pkg, $type_constraint, $types, $value) = @_; + + local $_; + for my $type (ref($types) eq 'ARRAY' ? @{ $types } : ( $types )) { + next unless $COERCE{$type}; + for my $coerce_type (@{ $COERCE_KEYS{$type}}) { + $_ = $value; + next unless $SUBTYPE{$coerce_type}->(); + $_ = $value; + $_ = $COERCE{$type}->{$coerce_type}->(); + return $_ if $type_constraint->(); } } - return $value; } -{ - no warnings 'uninitialized'; - my $optimized_constraints = { - Any => sub { 1 }, - Item => sub { 1 }, - Bool => sub { - !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' - }, - Undef => sub { !defined($_) }, - Defined => sub { defined($_) }, - Value => sub { defined($_) && !ref($_) }, - Num => sub { !ref($_) && looks_like_number($_) }, - Int => sub { defined($_) && !ref($_) && /^-?[0-9]+$/ }, - Str => sub { defined($_) && !ref($_) }, - ClassName => sub { Mouse::is_class_loaded($_) }, - Ref => sub { ref($_) }, - - ScalarRef => sub { ref($_) eq 'SCALAR' }, - ArrayRef => sub { ref($_) eq 'ARRAY' }, - HashRef => sub { ref($_) eq 'HASH' }, - CodeRef => sub { ref($_) eq 'CODE' }, - RegexpRef => sub { ref($_) eq 'Regexp' }, - GlobRef => sub { ref($_) eq 'GLOB' }, - - FileHandle => sub { - ref($_) eq 'GLOB' - && openhandle($_) - or - blessed($_) - && $_->isa("IO::Handle") - }, - - Object => sub { blessed($_) && blessed($_) ne 'Regexp' }, - }; - sub optimized_constraints { - return { %{ $SUBTYPE }, %{ $optimized_constraints } }; - } -} - 1; __END__