basic requirements complete, missing the optional and slurpy stuff, and waiting on...
John Napiorkowski [Tue, 30 Sep 2008 21:48:14 +0000 (21:48 +0000)]
18 files changed:
Changes
Makefile.PL
README [deleted file]
lib/MooseX/Meta/TypeConstraint/Role/Structured.pm [deleted file]
lib/MooseX/Meta/TypeConstraint/Structured.pm [new file with mode: 0644]
lib/MooseX/Meta/TypeConstraint/Structured/Generator.pm [deleted file]
lib/MooseX/Meta/TypeConstraint/Structured/Named.pm [deleted file]
lib/MooseX/Meta/TypeConstraint/Structured/Optional.pm [deleted file]
lib/MooseX/Meta/TypeConstraint/Structured/Positional.pm [deleted file]
lib/MooseX/Types/Structured.pm
t/00-load.t
t/01-basic.t [changed mode: 0755->0644]
t/02-constraints.t [deleted file]
t/02-tuple.t [new file with mode: 0644]
t/03-dict.t [new file with mode: 0644]
t/04-combined.t [new file with mode: 0644]
t/optional.t [deleted file]
t/suger.t [deleted file]

diff --git a/Changes b/Changes
index e04f086..e86d2d2 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
 Revision history for MooseX-Types-Structured
 
-0.01    05 September 2008
+0.01    25 September 2008
         Completed basic requirements, documentation and tests.
index d03d7c8..2511465 100644 (file)
@@ -10,7 +10,8 @@ license 'perl';
 perl_version '5.8.8';
 
 ## Module dependencies
-requires 'Moose' => '0.57';
+requires 'Moose' => '0.58';
+requires 'MooseX::TypeLibrary' => '';
 
 ## Testing dependencies
 build_requires 'Test::More' => '0.70';
diff --git a/README b/README
deleted file mode 100644 (file)
index c9f8fa3..0000000
--- a/README
+++ /dev/null
@@ -1,31 +0,0 @@
-MooseX-Type-Structured
-
-Structured Type Constraints for Moose.  This is an extension which provides
-additional type contraint abilities for L<Moose>.
-
-INSTALLATION
-
-To install this module, run the following commands:
-
-       perl Makefile.PL
-       make
-       make test
-       make install
-
-SUPPORT AND DOCUMENTATION
-
-After installing, you can find documentation for this module with the
-perldoc command.
-
-    perldoc MooseX::Type::Structured
-
-AUTHOR
-
-See L<MooseX::Type::Structured> for more information regarding authors.
-
-LICENSE
-
-See L<MooseX::Type::Structured> for the license.
-
-=cut
-
diff --git a/lib/MooseX/Meta/TypeConstraint/Role/Structured.pm b/lib/MooseX/Meta/TypeConstraint/Role/Structured.pm
deleted file mode 100644 (file)
index 6f2afff..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-package MooseX::Meta::TypeConstraint::Role::Structured;
-
-use Moose::Role;
-use Moose::Util::TypeConstraints;
-requires qw(_normalize_args signature_equals);
-
-=head1 NAME
-
-MooseX::Meta::TypeConstraint::Role::Structured - Structured Type Constraints
-
-=head1 DESCRIPTION
-
-This Role defines the interface and basic behavior of Structured Type Constraints.
-
-Structured type constraints let you assign an internal pattern of type
-constraints to a 'container' constraint.  The goal is to make it easier to
-declare constraints like "ArrayRef[Int, Int, Str]" where the constraint is an
-ArrayRef of three elements and the internal constraint on the three is Int, Int
-and Str.
-
-To accomplish this, we add an attribute to the base L<Moose::Meta::TypeConstraint>
-to hold a L</signature>, which is a reference to a pattern of type constraints.
-We then override L</constraint> to check our incoming value to the attribute
-against this signature pattern.  Additionally we allow L</optional_signature> to
-hold any optional type constraints.  The overall goal is to support something
-like:
-
-    has 'attr' => (isa=>'Tuple[Int, Str, Optional[Int, Int]]');
-
-These classes define how the underlying support for this works.
-
-=head1 TYPES
-
-The following types are defined in this class.
-
-=head2 Moose::Meta::TypeConstraint
-
-Used to make sure we can properly validate incoming signatures.
-
-=cut
-
-class_type 'Moose::Meta::TypeConstraint';
-
-=head1 ATTRIBUTES
-
-This class defines the following attributes.
-
-=head2 signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.
-
-=cut
-
-has 'signature' => (
-    is=>'ro',
-    isa=>'Ref',
-    required=>1,
-);
-
-=head2 optional_signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.  These are optional constraints.
-
-=cut
-
-has 'optional_signature' => (
-    is=>'ro',
-    isa=>'Ref',
-    predicate=>'has_optional_signature',
-);
-
-=head1 METHODS
-
-This class defines the following methods.
-
-=head2 equals
-
-modifier to make sure equals descends into the L</signature>
-
-=cut
-
-around 'equals' => sub {
-    my ($equals, $self, $compared_type_constraint) = @_;
-    
-    ## Make sure we are comparing typeconstraints of the same base class
-    return unless $compared_type_constraint->isa(__PACKAGE__);
-    
-    ## Make sure the base equals is also good
-    return unless $self->$equals($compared_type_constraint);
-    
-    ## Make sure the signatures match
-    return unless $self->signature_equals($compared_type_constraint);
-   
-    ## If we get this far, the two are equal
-    return 1;
-};
-
-=head1 AUTHOR
-
-John James Napiorkowski <jjnapiork@cpan.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
-1;
diff --git a/lib/MooseX/Meta/TypeConstraint/Structured.pm b/lib/MooseX/Meta/TypeConstraint/Structured.pm
new file mode 100644 (file)
index 0000000..eea8d51
--- /dev/null
@@ -0,0 +1,119 @@
+package MooseX::Meta::TypeConstraint::Structured;
+
+use Moose;
+use Moose::Util::TypeConstraints ();
+extends 'Moose::Meta::TypeConstraint';
+
+=head1 NAME
+
+MooseX::Meta::TypeConstraint::Structured - Structured type constraints.
+
+=head1 DESCRIPTION
+
+A structure is a set of L<Moose::Meta::TypeConstraint> that are 'aggregated' in
+such a way as that they are all applied to an incoming list of arguments.  The
+idea here is that a Type Constraint could be something like, "An Int followed by
+an Int and then a Str" and that this could be done so with a declaration like:
+
+    Tuple[Int,Int,Str]; ## Example syntax
+    
+So a structure is a list of Type constraints (the "Int,Int,Str" in the above
+example) which are intended to function together.
+
+=head1 ATTRIBUTES
+
+This class defines the following attributes.
+
+=head2 type_constraints
+
+A list of L<Moose::Meta::TypeConstraint> objects.
+
+=cut
+
+has 'type_constraints' => (
+    is=>'ro',
+    isa=>'Ref',
+    predicate=>'has_type_constraints',
+);
+
+=head2 constraint_generator
+
+A subref or closure that contains the way we validate incoming values against
+a set of type constraints.
+
+=cut
+
+has 'constraint_generator' => (is=>'ro', isa=>'CodeRef');
+
+=head1 METHODS
+
+This class defines the following methods.
+
+=head2 generate_constraint_for ($type_constraints)
+
+Given some type constraints, use them to generate validation rules for an ref
+of values (to be passed at check time)
+
+=cut
+
+sub generate_constraint_for {
+    my ($self, $type_constraints) = @_;
+    return sub {
+        my $constraint_generator = $self->constraint_generator;
+        return $constraint_generator->($type_constraints, @_);
+    };
+}
+
+=head2 parameterize (@type_constraints)
+
+Given a ref of type constraints, create a structured type.
+
+=cut
+
+sub parameterize {
+    my ($self, @type_constraints) = @_;
+    my $name = $self->name .'['. join(',', map {"$_"} @type_constraints) .']';
+    return __PACKAGE__->new(
+        name => $name,
+        parent => $self,
+        type_constraints => \@type_constraints,
+        constraint_generator => $self->constraint_generator,
+    );
+}
+
+=head2 compile_type_constraint
+
+hook into compile_type_constraint so we can set the correct validation rules.
+
+=cut
+
+around 'compile_type_constraint' => sub {
+    my ($compile_type_constraint, $self, @args) = @_;
+    
+    if($self->has_type_constraints) {
+        my $type_constraints = $self->type_constraints;
+        my $constraint = $self->generate_constraint_for($type_constraints);
+        $self->_set_constraint($constraint);        
+    }
+
+    return $self->$compile_type_constraint(@args);
+};
+
+=head1 SEE ALSO
+
+The following modules or resources may be of interest.
+
+L<Moose>, L<Moose::Meta::TypeConstraint>
+
+=head1 AUTHOR
+
+John Napiorkowski, C<< <jjnapiork@cpan.org> >>
+
+=head1 COPYRIGHT & LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
\ No newline at end of file
diff --git a/lib/MooseX/Meta/TypeConstraint/Structured/Generator.pm b/lib/MooseX/Meta/TypeConstraint/Structured/Generator.pm
deleted file mode 100755 (executable)
index f7925f5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package MooseX::Meta::TypeConstraint::Structured::Generator;
-
-use strict;
-use warnings;
-
-use metaclass;
-
-use base 'Moose::Meta::TypeConstraint';
-use Moose::Util::TypeConstraints ();
-
-__PACKAGE__->meta->add_attribute('structured_type' => (
-    accessor  => 'structured_type',
-    predicate => 'has_structured_type',
-));
-
-sub _parse_type_parameter {
-       my ($self, $type_str) = @_;
-       return $self->structured_type->_parse_type_parameter($type_str);
-}
-
-sub parameterize {
-       my ($self, $parameter_string) = @_;
-       my @contained_tcs = $self->_parse_type_parameter($parameter_string);
-       my $tc_name = $self->name .'['. join(',', map {$_->name} @contained_tcs) .']';
-       
-       return $self->structured_type->new(
-               name => $tc_name,
-               parent => $self->parent,
-               package_defined_in => __PACKAGE__,
-               signature => \@contained_tcs, 
-       );                      
-}
-
-1;
diff --git a/lib/MooseX/Meta/TypeConstraint/Structured/Named.pm b/lib/MooseX/Meta/TypeConstraint/Structured/Named.pm
deleted file mode 100644 (file)
index ee4b195..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-package MooseX::Meta::TypeConstraint::Structured::Named;
-
-use Moose;
-use Moose::Meta::TypeConstraint ();
-
-extends 'Moose::Meta::TypeConstraint';
-with 'MooseX::Meta::TypeConstraint::Role::Structured';
-
-=head1 NAME
-
-MooseX::Meta::TypeConstraint::Structured::Named - Structured Type Constraints
-
-=head1 SYNOPSIS
-
-The follow is example usage:
-
-    use Moose::Util::TypeConstraints;
-    use MooseX::Meta::TypeConstraint::Structured::Named;
-    
-    my %required = (key1='Str', key2=>'Int');
-    my %optional = (key3=>'Object');
-    
-    my $tc = MooseX::Meta::TypeConstraint::Structured::Named->new(
-        name => 'Dict',
-        parent => find_type_constraint('HashRef'),
-        package_defined_in => __PACKAGE__,
-        signature => {map {
-            $_ => find_type_constraint($required{$_});
-        } keys %required},
-        optional_signature => {map {
-            $_ => find_type_constraint($optional{$_});
-        } keys %optional},
-    );
-
-=head1 DESCRIPTION
-
-Named structured Constraints expect the internal constraints to be in keys or
-fields similar to what we expect in a HashRef.  Basically, this allows you to
-easily add type constraint checks against values in the wrapping HashRef
-identified by the key name.
-
-=head1 ATTRIBUTES
-
-This class defines the following attributes.
-
-=head2 signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.
-
-=cut
-
-has '+signature' => (isa=>'HashRef[Moose::Meta::TypeConstraint]');
-
-=head2 optional_signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.  These are optional constraints.
-
-=cut
-
-has '+optional_signature' => (isa=>'HashRef[Moose::Meta::TypeConstraint]');
-
-=head1 METHODS
-
-This class defines the following methods.
-
-=head2 _normalize_args
-
-Get arguments into a known state or die trying.  Ideally we try to make this
-into a HashRef so we can match it up with the L</signature> HashRef.
-
-=cut
-
-sub _normalize_args {
-    my ($self, $args) = @_;
-    if(defined $args) {
-        if(ref $args eq 'HASH') {
-            %$args
-        } else {
-            confess 'Signature must be an HashRef type';
-        }
-    } else {
-        confess 'Signature cannot be empty';
-    }
-}
-    
-=head2 constraint
-
-The constraint is basically validating the L</signature> against the incoming
-
-=cut
-
-sub constraint {
-    my $self = shift;
-    return sub {
-        my %args = $self->_normalize_args(shift);
-        
-        ## First make sure all the required type constraints match        
-        foreach my $sig_key (keys %{$self->signature}) {
-            my $type_constraint = $self->signature->{$sig_key};
-            if(my $error = $type_constraint->validate($args{$sig_key})) {
-                confess $error;
-            } else {
-                delete $args{$sig_key};
-            }
-        }
-        
-        ## Now test the option type constraints.
-        foreach my $arg_key (keys %args) {
-            my $optional_type_constraint = $self->optional_signature->{$arg_key};
-            if(my $error = $optional_type_constraint->validate($args{$arg_key})) {
-                confess $error;
-            }              
-        }
-        
-        ## If we got this far we passed!
-        return 1;
-    };
-}
-
-=head2 signature_equals
-
-Check that the signature equals another signature.
-
-=cut
-
-sub signature_equals {
-    my ($self, $compared_type_constraint) = @_;
-    
-    foreach my $idx (keys %{$self->signature}) {
-        my $this = $self->signature->{$idx};
-        my $that = $compared_type_constraint->signature->{$idx};
-        return unless $this->equals($that);
-    }
-    
-    if($self->has_optional_signature) {
-        foreach my $idx (keys %{$self->optional_signature}) {
-            my $this = $self->optional_signature->{$idx};
-            my $that = $compared_type_constraint->optional_signature->{$idx};
-            return unless $this->equals($that);
-        }        
-    }
-
-    return 1;
-}
-
-
-
-=head1 AUTHOR
-
-John James Napiorkowski <jjnapiork@cpan.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
-no Moose; 1;
diff --git a/lib/MooseX/Meta/TypeConstraint/Structured/Optional.pm b/lib/MooseX/Meta/TypeConstraint/Structured/Optional.pm
deleted file mode 100755 (executable)
index af3a23b..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-package MooseX::Meta::TypeConstraint::Structured::Optional;
-
-use Moose;
-use Moose::Meta::TypeConstraint ();
-
-#extends 'Moose::Meta::TypeConstraint';
-extends 'MooseX::Meta::TypeConstraint::Structured::Positional';
-with 'MooseX::Meta::TypeConstraint::Role::Structured';
-
-=head1 NAME
-
-MooseX::Meta::TypeConstraint::Structured::Optional - Structured Type Constraints
-
-=head1 SYNOPSIS
-
-The follow is example usage:
-
-    use Moose::Util::TypeConstraints;
-    use MooseX::Meta::TypeConstraint::Structured::Optional;
-    
-    my @options = ('Str', 'Int');
-    
-    my $tc = MooseX::Meta::TypeConstraint::Structured::Optional->new(
-        name => 'Dict',
-        parent => find_type_constraint('ArrayRef'),
-        signature => [map {
-            find_type_constraint($_);
-        } @options],
-    );
-    
-=head1 DESCRIPTION
-
-Optional Type Constraints are additional constraints on a 'base' structured
-type constraint which extends those constraints with additional optional
-fields.  Basically this constraint get's it's constraint logic and args
-from a a Structured Type Constraint that contains it.  So basically:
-
-       MyType[Int,Str,Optional[Int, Int]]
-
-In this example, the structured Type constraint 'MyType' is the container for
-this Optional type called 'Optional'.  What will happen here is that the
-MyType will get the first elements for validation and a third one will go
-to optional.  Optional will 'inline' itself so that you can validate with:
-
-       ->validate(1,'hello',2,3);
-       ->validate(1,'hello',2);
-       ->validate(1,'hello');  
-
-and not:
-
-       ->validate(1,'hello',[2,3]]);
-       ->validate(1,'hello',[2]]);     
-
-as you might expect.  Basically it sucks up args to the length of it's declared
-type constraints.  So Optional args are validated against the definition, but if
-they are missing this does not cause a validation error.
-
-Please keep in mind the type constraint names given in this example are for
-example use only and any similarity between them, actual Type Constraints and
-package names are coincidental.
-
-=head1 ATTRIBUTES
-
-This class defines the following attributes.
-
-=head2 containing_type_constraint ($structured_type_constraint)
-
-This is the type constraint that contains the Optional parameters.
-
-=cut
-
-#has 'containing_type_constraint' => (
-#      is=>'ro', 
-#      does=>'MooseX::Meta::TypeConstraint::Role::Structured',
-#      required=>1,
-#);
-
-=head2 signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.
-
-=cut
-
-has '+signature' => (isa=>'ArrayRef[Moose::Meta::TypeConstraint]');
-
-=head1 METHODS
-
-This class defines the following methods.
-
-=head2 _normalize_args
-
-Get arguments into a known state or die trying.  Ideally we try to make this
-into a HashRef so we can match it up with the L</signature> HashRef.  This gets
-delegated to the containing class (L</containing_type_constraint>).
-
-=cut
-
-#sub _normalize_args {
-#    return shift->containing_type_constraint->_normalize_args(@_);
-#}
-    
-=head2 constraint
-
-The constraint is basically validating the L</signature> against the incoming
-
-=cut
-
-#sub constraint {
-#      return 1;
- #   return shift->containing_type_constraint->constraint(@_);
-#}
-
-=head2 _parse_type_parameter ($str)
-
-Given a $string that is the parameter information part of a parameterized
-constraint, parses it for internal constraint information.  This is delegated
-to the containing class.
-
-=cut
-
-#sub _parse_type_parameter {
-#    return shift->containing_type_constraint->_parse_type_parameter(@_);
-#}
-
-
-=head2 signature_equals
-
-Check that the signature equals another signature.  Delegated to the containing
-class.
-
-=cut
-
-#sub signature_equals {
-#    return shift->containing_type_constraint->signature_equals(@_);
-#}
-
-=head1 AUTHOR
-
-John James Napiorkowski <jjnapiork@cpan.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
-no Moose; 1;
diff --git a/lib/MooseX/Meta/TypeConstraint/Structured/Positional.pm b/lib/MooseX/Meta/TypeConstraint/Structured/Positional.pm
deleted file mode 100644 (file)
index d29ed46..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-package MooseX::Meta::TypeConstraint::Structured::Positional;
-
-use Moose;
-use Moose::Meta::TypeConstraint ();
-
-extends 'Moose::Meta::TypeConstraint';
-with 'MooseX::Meta::TypeConstraint::Role::Structured';
-
-=head1 NAME
-
-MooseX::Meta::TypeConstraint::Structured::Positional - Structured Type Constraints
-
-=head1 SYNOPSIS
-
-The follow is example usage:
-
-    use Moose::Util::TypeConstraints;
-    use MooseX::Meta::TypeConstraint::Structured::Positional;
-    
-    my @required = ('Str', 'Int');
-    my @optional = ('Object');
-    
-    my $tc = MooseX::Meta::TypeConstraint::Structured::Positional->new(
-        name => 'Dict',
-        parent => find_type_constraint('ArrayRef'),
-        signature => [map {
-            find_type_constraint($_);
-        } @required],
-        optional_signature => [map {
-            find_type_constraint($_);
-        } @optional],
-    );
-    
-=head1 DESCRIPTION
-
-Positionally structured Constraints expect the internal constraints to be in
-'positioned' or ArrayRef style order.  This allows you to add type constraints
-to the internal values of the Arrayref.
-
-=head1 ATTRIBUTES
-
-This class defines the following attributes.
-
-=head2 signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.
-
-=cut
-
-has '+signature' => (isa=>'ArrayRef[Moose::Meta::TypeConstraint]');
-
-=head2 optional_signature
-
-This is a signature of internal contraints for the contents of the outer
-contraint container.  These are optional constraints.
-
-=cut
-
-has '+optional_signature' => (isa=>'ArrayRef[Moose::Meta::TypeConstraint]');
-
-=head1 METHODS
-
-This class defines the following methods.
-
-=head2 _normalize_args
-
-Get arguments into a known state or die trying.  Ideally we try to make this
-into a HashRef so we can match it up with the L</signature> HashRef.
-
-=cut
-
-sub _normalize_args {
-    my ($self, $args) = @_;
-    if(defined $args) {
-        if(ref $args eq 'ARRAY') {
-            @$args
-        } else {
-            confess 'Signature must be an ArrayRef type';
-        }
-    } else {
-        confess 'Signature cannot be empty';
-    }
-}
-    
-=head2 constraint
-
-The constraint is basically validating the L</signature> against the incoming
-
-=cut
-
-sub constraint {
-    my $self = shift;
-    return sub {
-        my @args = $self->_normalize_args(shift);
-        my @signature = @{$self->signature};
-               my @optional_signature = @{$self->optional_signature}
-               if $self->has_optional_signature; 
-        
-        ## First make sure all the required type constraints match        
-        while( my $type_constraint = shift @signature) {
-            if(my $error = $type_constraint->validate(shift @args)) {
-                confess $error;
-            }            
-        }
-        
-        ## Now test the option type constraints.
-        while( my $arg = shift @args) {
-            if(my $optional_type_constraint = shift @optional_signature) {
-                if(my $error = $optional_type_constraint->validate($arg)) {
-                    confess $error;
-                }                              
-            } else {
-                confess "Too Many arguments for the available type constraints";
-            }
-        }
-        
-        ## If we got this far we passed!
-        return 1;
-    };
-}
-
-=head2 signature_equals
-
-Check that the signature equals another signature.
-
-=cut
-
-sub signature_equals {
-    my ($self, $compared_type_constraint) = @_;
-    
-    foreach my $idx (0..$#{$self->signature}) {
-        my $this = $self->signature->[$idx];
-        my $that = $compared_type_constraint->signature->[$idx];
-        return unless $this->equals($that);
-    }
-    
-    if($self->has_optional_signature) {
-        foreach my $idx (0..$#{$self->optional_signature}) {
-            my $this = $self->optional_signature->[$idx];
-            my $that = $compared_type_constraint->optional_signature->[$idx];
-            return unless $this->equals($that);
-        }        
-    }
-
-    return 1;
-}
-
-=head1 AUTHOR
-
-John James Napiorkowski <jjnapiork@cpan.org>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
-
-no Moose; 1;
index 67d3f46..9a66f19 100644 (file)
@@ -2,12 +2,9 @@ package MooseX::Types::Structured;
 
 use Moose;
 use Moose::Util::TypeConstraints;
-use MooseX::Meta::TypeConstraint::Structured::Positional;
-use MooseX::Meta::TypeConstraint::Structured::Named;
+use MooseX::Meta::TypeConstraint::Structured;
+use MooseX::Types -declare => [qw(Dict Tuple)];
 
-#use MooseX::Types -declare => [qw(Dict  Tuple  Optional)];
-use Sub::Exporter
-  -setup => { exports => [ qw( Dict  Tuple  Optional) ] };
        
 our $VERSION = '0.01';
 our $AUTHORITY = 'cpan:JJNAPIORK';
@@ -107,95 +104,94 @@ method, granting some interesting possibilities for coercion.  Try:
         };
        
 
-=head1 TYPES
+=head1 METHODS
 
-This class defines the following types and subtypes.
+This class defines the following methods
 
-=cut
+=head2 type_storage
 
-sub Optional($) {
-    return bless {args=>shift}, 'MooseX::Types::Optional';
-}
+Override the type_storage method so that we can inline the types.  We do this
+because if we try to say "type Dict, $dict" or similar, I found that
+L<Moose::Util::TypeConstraints> automatically wraps a L<Moose::Meta::TypeConstraint>
+object around my Structured type, which then throws an error since the base
+Type Constraint object doesn't have a parameterize method.
 
-sub Tuple($) {
-       my ($args, $optional) = _normalize_args(@_);
-       my @args = @$args;
-       my @optional = ref $optional eq 'ARRAY' ? @$optional : ();
-
-       return MooseX::Meta::TypeConstraint::Structured::Positional->new(
-               name => 'Tuple',
-               parent => find_type_constraint('ArrayRef'),
-               package_defined_in => __PACKAGE__,
-               signature => [map {
-                       _normalize_type_constraint($_);
-               } @args],
-               optional_signature => [map {
-                       _normalize_type_constraint($_);
-               } @optional],
-       );
-}
-use Data::Dump qw/dump/;
-sub Dict($) {
-       my ($args, $optional) = _normalize_args(@_);
-       my %args = @$args;
-       my %optional = ref $optional eq 'ARRAY' ? @$optional : ();
-       
-       
-       return MooseX::Meta::TypeConstraint::Structured::Named->new(
-               name => 'Dict',
-               parent => find_type_constraint('HashRef'),
-               package_defined_in => __PACKAGE__,
-               signature => {map {
-                       $_ => _normalize_type_constraint($args{$_});
-               } keys %args},
-               optional_signature => {map {
-
-                       warn dump $_;
-                       warn dump $optional{$_};
-                       warn dump _normalize_type_constraint($optional{$_});
-                       
-                       $_ => _normalize_type_constraint($optional{$_});
-                       
-               } keys %optional},
-       );
-}
+In the future, might make all these play more nicely with Parameterized types,
+and then this nasty override can go away.
 
-sub _normalize_args {
-    my $args = shift @_;
-    confess "Structured Type Constraints can only accept an ArrayRef as arguments"
-     unless ref $args eq 'ARRAY';
-     
-    my @args = @$args;
-    my $last = pop @args;
-    
-    if(blessed $last && $last->isa('MooseX::Types::Optional')) {
-        return ([@args], $last->{args});
-    } else {
-        return ([@args, $last]);
-    }
-    
-}
-sub _normalize_type_constraint {
-       my ($tc) = @_;
-               
-       ## If incoming is an object, we will assume it's something that implements
-       ## what a type constraint is.  We should probably have a Role for this...
-       if(defined $tc && blessed $tc) {
-               return $tc;
-       } elsif($tc) {
-               return Moose::Util::TypeConstraints::find_or_parse_type_constraint($tc);
-       }
+=cut
+
+sub type_storage {
+       return {
+               Tuple => MooseX::Meta::TypeConstraint::Structured->new(
+                       name => 'Tuple',
+                       parent => find_type_constraint('ArrayRef'),
+                       constraint_generator=> sub {
+                               ## Get the constraints and values to check
+                               my @type_constraints = @{shift @_};            
+                               my @values = @{shift @_};
+                               ## Perform the checking
+                               while(@type_constraints) {
+                                       my $type_constraint = shift @type_constraints;
+                                       if(@values) {
+                                               my $value = shift @values;
+                                               unless($type_constraint->check($value)) {
+                                                       return;
+                                               }                               
+                                       } else {
+                                               return;
+                                       }
+                               }
+                               ## Make sure there are no leftovers.
+                               if(@values) {
+                                       return;
+                               } elsif(@type_constraints) {
+                                       return;
+                               }else {
+                                       return 1;
+                               }
+                       }
+               ),
+               Dict => MooseX::Meta::TypeConstraint::Structured->new(
+                       name => 'Dict',
+                       parent => find_type_constraint('HashRef'),
+                       constraint_generator=> sub {
+                               ## Get the constraints and values to check
+                               my %type_constraints = @{shift @_};            
+                               my %values = %{shift @_};
+                               ## Perform the checking
+                               while(%type_constraints) {
+                                       my($key, $type_constraint) = each %type_constraints;
+                                       delete $type_constraints{$key};
+                                       if(exists $values{$key}) {
+                                               my $value = $values{$key};
+                                               delete $values{$key};
+                                               unless($type_constraint->check($value)) {
+                                                       return;
+                                               }
+                                       } else {
+                                               return;
+                                       }
+                               }
+                               ## Make sure there are no leftovers.
+                               if(%values) {
+                                       return;
+                               } elsif(%type_constraints) {
+                                       return;
+                               }else {
+                                       return 1;
+                               }
+                       },
+               ),
+       };
 }
 
 =head1 SEE ALSO
 
 The following modules or resources may be of interest.
 
-L<Moose>, L<MooseX::TypeLibrary>, L<Moose::Meta::TypeConstraint>
-
-=head1 BUGS
-
-No known or reported bugs.
+L<Moose>, L<MooseX::TypeLibrary>, L<Moose::Meta::TypeConstraint>,
+L<MooseX::Meta::TypeConstraint::Structured>
 
 =head1 AUTHOR
 
index 788a9f2..0fb6c2b 100644 (file)
@@ -1,12 +1,8 @@
 use strict;
 use warnings;
 
-use Test::More tests=>5;
+use Test::More tests=>2;
 
 ## List all the modules we want to make sure can at least compile
-
-use_ok 'MooseX::Meta::TypeConstraint::Structured::Named';
-use_ok 'MooseX::Meta::TypeConstraint::Structured::Positional';
-use_ok 'MooseX::Meta::TypeConstraint::Structured::Optional';
-use_ok 'MooseX::Meta::TypeConstraint::Structured::Generator';
+use_ok 'MooseX::Meta::TypeConstraint::Structured';
 use_ok 'MooseX::Types::Structured';
\ No newline at end of file
old mode 100755 (executable)
new mode 100644 (file)
index a4c3f74..071f231
-BEGIN {
-       use strict;
-       use warnings;
-       use Test::More tests=>37;
-       use Test::Exception;
-       
-       use_ok 'Moose::Util::TypeConstraints';
-       use_ok 'MooseX::Meta::TypeConstraint::Structured::Generator';
-       use_ok 'MooseX::Meta::TypeConstraint::Structured::Positional';
-       use_ok 'MooseX::Meta::TypeConstraint::Structured::Optional';    
-       use_ok 'MooseX::Meta::TypeConstraint::Structured::Named';
-}
-
-my $optional = MooseX::Meta::TypeConstraint::Structured::Generator->new(
-               name => 'Optional',
-               structured_type => 'MooseX::Meta::TypeConstraint::Structured::Optional',
-               package_defined_in => __PACKAGE__,
-               parent => find_type_constraint('ArrayRef'),
-       );
-
-my $tuple = MooseX::Meta::TypeConstraint::Structured::Generator->new(
-               name => 'Tuple',
-               structured_type => 'MooseX::Meta::TypeConstraint::Structured::Positional',
-               package_defined_in => __PACKAGE__,
-               parent => find_type_constraint('ArrayRef'),
-       );
-       
-my $dict = MooseX::Meta::TypeConstraint::Structured::Generator->new(
-               name => 'Dict',
-               structured_type => 'MooseX::Meta::TypeConstraint::Structured::Named',
-               package_defined_in => __PACKAGE__,
-               parent => find_type_constraint('HashRef'),
-       );
-
-Moose::Util::TypeConstraints::register_type_constraint($optional);
-Moose::Util::TypeConstraints::register_type_constraint($tuple);
-Moose::Util::TypeConstraints::register_type_constraint($dict);
-
-## Make sure the new type constraints have been registered
-
-ok Moose::Util::TypeConstraints::find_type_constraint('Tuple')
- => 'Found the Tuple Type';
-ok Moose::Util::TypeConstraints::find_type_constraint('Dict')
- => 'Found the Tuple Type';
-ok Moose::Util::TypeConstraints::find_type_constraint('Optional')
- => 'Found the Tuple Type';
-
-{
-       package Test::MooseX::Types::Structured::BasicAttributes;
-       
-       use Moose;
-       use Moose::Util::TypeConstraints;
-       
-       has 'tuple' => (is=>'rw', isa=>'Tuple[Int,Str,Int]');
-       has 'tuple_with_parameterized' => (is=>'rw', isa=>'Tuple[Int,Str,Int,ArrayRef[Int]]');
-       has 'tuple_with_optional' => (is=>'rw', isa=>'Tuple[Int,Str,Int,Optional[Int,Int]]');
-       has 'tuple_with_union' => (is=>'rw', isa=>'Tuple[Int,Str,Int|Object,Optional[Int|Object,Int]]');
-       
-       has 'dict' => (is=>'rw', isa=>'Dict[name=>Str,age=>Int]');
-       has 'dict_with_parameterized' => (is=>'rw', isa=>'Dict[name=>Str, age=>Int, telephone=>ArrayRef[Int]]');
-       has 'dict_with_optional' => (is=>'rw', isa=>'Dict[name=>Str, age=>Int, Optional[opt1=>Str,opt2=>Object]]');
-
-}
-
-
-ok my $obj = Test::MooseX::Types::Structured::BasicAttributes->new,
- => 'Got a good object';
-
-ok Moose::Util::TypeConstraints::find_type_constraint('Tuple[Int,Str,Int]')
- => 'Found expected type constraint';
-
-ok Moose::Util::TypeConstraints::find_type_constraint('Tuple[Int,Str,Int,Optional[Int,Int]]')
- => 'Found expected type constraint';
-## dict Dict[name=>Str, Age=>Int]
-
-ok $obj->dict({name=>'John', age=>39})
- => 'Dict[name=>Str, Age=>Int] properly succeeds';
-## Test tuple (Tuple[Int,Str,Int])
-
-ok $obj->tuple([1,'hello',3])
- => "[1,'hello',3] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-
-## Test tuple_with_parameterized (Tuple[Int,Str,Int,ArrayRef[Int]])
-
-ok $obj->tuple_with_parameterized([1,'hello',3,[1,2,3]])
- => "[1,'hello',3,[1,2,3]] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized([1,'hello',3,[1,2,'world']]);
-}, qr/Validation failed for 'ArrayRef\[Int\]'/ => "[1,'hello',3,[1,2,'world']] properly fails";
-
-
-## Test tuple_with_optional (Tuple[Int,Str,Int,Optional[Int,Int]])
-
-ok $obj->tuple_with_optional([1,'hello',3])
- => "[1,'hello',3] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,1])
- => "[1,'hello',3,1] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,4])
- => "[1,'hello',3,4] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,4,5])
- => "[1,'hello',3,4,5] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple_with_optional([1,'hello',3,4,5,6]);
-}, qr/Too Many arguments for the available type constraints/ => "[1,'hello',3,4,5,6] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-## tuple_with_union Tuple[Int,Str,Int|Object,Optional[Int|Object,Int]]
-
-SKIP: {
-
-       skip "Unions not supported for string parsed type constraints" => 8;
-
-       ok $obj->tuple_with_union([1,'hello',3])
-        => "[1,'hello',3] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,1])
-        => "[1,'hello',3,1] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,4])
-        => "[1,'hello',3,4] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,4,5])
-        => "[1,'hello',3,4,5] properly suceeds";
-
-       throws_ok sub {
-               $obj->tuple_with_union([1,'hello',3,4,5,6]);
-       }, qr/Too Many arguments for the available type constraints/ => "[1,'hello',3,4,5,6] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union([1,2,'world']);
-       }, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union(['hello1',2,3]);
-       }, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union(['hello2',2,'world']);
-       }, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-}
-
+use strict;
+use warnings;
+
+use Test::More tests=>14;
+
+use_ok 'MooseX::Meta::TypeConstraint::Structured';
+use_ok 'Moose::Util::TypeConstraints';
+
+ok my $int = find_type_constraint('Int') => 'Got Int';
+ok my $str = find_type_constraint('Str') => 'Got Str';
+ok my $arrayref = find_type_constraint('ArrayRef') => 'Got ArrayRef';
+
+my $list_tc = MooseX::Meta::TypeConstraint::Structured->new(
+    name => 'list_tc',
+    parent => $arrayref,
+    type_constraints => [$int, $str],
+    constraint_generator=> sub {
+        my @type_constraints = @{shift @_};            
+        my @values = @{shift @_};
+
+        while(my $type_constraint = shift @type_constraints) {
+            my $value = shift @values || return;
+            $type_constraint->check($value) || return;
+        }
+        if(@values) {
+            return;
+        } else {
+            return 1;
+        }
+    }
+);
+
+isa_ok $list_tc, 'MooseX::Meta::TypeConstraint::Structured';
+
+ok !$arrayref->check() => 'Parent undef fails';
+ok !$list_tc->check() => 'undef fails';
+ok !$list_tc->check(1) => '1 fails';
+ok !$list_tc->check([]) => '[] fails';
+ok !$list_tc->check([1]) => '[1] fails';
+ok !$list_tc->check([1,2,3]) => '[1,2,3] fails';
+ok !$list_tc->check(['a','b']) => '["a","b"] fails';
+
+ok $list_tc->check([1,'a']) => '[1,"a"] passes';
diff --git a/t/02-constraints.t b/t/02-constraints.t
deleted file mode 100644 (file)
index 86c4e6c..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-BEGIN {
-       use strict;
-       use warnings;
-       use Test::More tests=>47;
-       use Test::Exception;
-}
-
-{
-    package Test::MooseX::Meta::TypeConstraint::Structured;
-
-    use Moose;
-    use MooseX::Types::Structured qw(Tuple Dict Optional);
-       use MooseX::Types::Moose qw(Int Str Object ArrayRef HashRef Maybe);
-       use MooseX::Types -declare => [qw(MyString)];
-       use Moose::Util::TypeConstraints;
-
-    subtype MyString,
-     as 'Str',
-     where { $_=~m/abc/};
-
-    has 'tuple' => (is=>'rw', isa=>Tuple[Int, Str, MyString]);
-    has 'dict' => (is=>'rw', isa=>Dict[name=>Str, age=>Int]);
-    has 'dict_with_maybe' => (is=>'rw', isa=>Dict[name=>Str, age=>Maybe[Int]]);        
-       has 'tuple_with_param' => (is=>'rw', isa=>Tuple[Int, Str, ArrayRef[Int]]);
-       has 'tuple_with_maybe' => (is=>'rw', isa=>Tuple[Int, Str, Maybe[Int]]);
-       has 'dict_with_tuple' => (is=>'rw', isa=>Dict[key1=>Str, key2=>Tuple[Int,Str]]);
-    has 'optional_tuple' => (is=>'rw', isa=>Tuple[Int, Int, Optional[Int]] );
-    has 'optional_dict' => (is=>'rw', isa=>Dict[key1=>Int, Optional[key2=>Int]] );
-    has 'dict_with_tuple_with_union' => (is=>'rw', isa=>Dict[key1=>Str|Object, key2=>Tuple[Int,Str|Object]] );
-       
-    has 'crazy' => (
-        is=>'rw',
-        isa=>Tuple
-            ## First ArrayRef Arg is the required type constraints for the top
-            ## level Tuple.
-            [
-                Int,
-                MyString,
-                ## The third required element is a Dict type constraint, which
-                ## itself has two required keys and a third optional key.
-                Dict[name=>Str,age=>Int, Optional[visits=>Int]],
-                Optional[
-                    Int,
-                    ## This Tuple has one required type constraint and two optional.
-                    Tuple[Int, Optional[Int,HashRef]],                    
-                ],
-            ],      
-    );
-}
-
-## Instantiate a new test object
-
-ok my $record = Test::MooseX::Meta::TypeConstraint::Structured->new
- => 'Instantiated new Record test class.';
-isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured'
- => 'Created correct object type.';
-## Test crazy
-
-lives_ok sub {
-    $record->crazy([1,'hello.abc.world', {name=>'John', age=>39}]);
-} => 'Set crazy attribute with no optionals used';
-
-is_deeply $record->crazy, [1, 'hello.abc.world', {name=>'John', age=>39}]
- => 'correct values for crazy attributes no optionals';
-lives_ok sub {
-    $record->crazy([1,'hello.abc.world', {name=>'John', age=>39, visits=>10},10, [1,2,{key=>'value'}]]);
-} => 'Set crazy attribute with all optionals used';
-
-is_deeply $record->crazy, [1,'hello.abc.world', {name=>'John', age=>39, visits=>10},10, [1,2,{key=>'value'}]]
- => 'correct values for crazy attributes all optionals';
-
-lives_ok sub {
-    $record->crazy([1,'hello.abc.world', {name=>'John', age=>39},10, [1,2]]);
-} => 'Set crazy attribute with some optionals used';
-
-throws_ok sub {
-    $record->crazy([1,'hello', 'test.xxx.test']);    
-}, qr/Validation failed for 'MyString'/
- => 'Properly failed for bad value in crazy attribute 01';
-
-throws_ok sub {
-    $record->crazy([1,'hello.abc.world', {notname=>'John', notage=>39}]);    
-}, qr/Validation failed for 'Str'/
- => 'Properly failed for bad value in crazy attribute 02';
-## Test Tuple type constraint
-
-lives_ok sub {
-    $record->tuple([1,'hello', 'test.abc.test']);
-} => 'Set tuple attribute without error';
-
-is $record->tuple->[0], 1
- => 'correct set the tuple attribute index 0';
-
-is $record->tuple->[1], 'hello'
- => 'correct set the tuple attribute index 1';
-
-is $record->tuple->[2], 'test.abc.test'
- => 'correct set the tuple attribute index 2';
-
-throws_ok sub {
-    $record->tuple([1,'hello', 'test.xxx.test']);    
-}, qr/Validation failed for 'MyString'/
- => 'Properly failed for bad value in custom type constraint';
-throws_ok sub {
-    $record->tuple(['asdasd',2, 'test.abc.test']);      
-}, qr/Validation failed for 'Int'/
- => 'Got Expected Error for violating constraints';
-
-## Test the Dictionary type constraint
-lives_ok sub {
-    $record->dict({name=>'frith', age=>23});
-} => 'Set dict attribute without error';
-
-is $record->dict->{name}, 'frith'
- => 'correct set the dict attribute name';
-
-is $record->dict->{age}, 23
- => 'correct set the dict attribute age';
-throws_ok sub {
-    $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});      
-}, qr/Validation failed for 'Str'/
- => 'Got Expected Error for bad value in dict';
-
-## Test tuple_with_maybe
-
-lives_ok sub {
-    $record->tuple_with_maybe([1,'hello', 1]);
-} => 'Set tuple attribute without error';
-
-throws_ok sub {
-    $record->tuple_with_maybe([1,'hello', 'a']);
-}, qr/Validation failed for 'Maybe\[Int\]'/
- => 'Properly failed for bad value parameterized constraint';
-
-lives_ok sub {
-    $record->tuple_with_maybe([1,'hello']);
-} => 'Set tuple attribute without error skipping optional parameter';
-
-## Test Tuple with parameterized type
-
-lives_ok sub {
-    $record->tuple_with_param([1,'hello', [1,2,3]]);
-} => 'Set tuple attribute without error';
-
-throws_ok sub {
-    $record->tuple_with_param([1,'hello', [qw/a b c/]]);
-}, qr/Validation failed for 'ArrayRef\[Int\]'/
- => 'Properly failed for bad value parameterized constraint';
-
-## Test dict_with_maybe
-
-lives_ok sub {
-    $record->dict_with_maybe({name=>'frith', age=>23});
-} => 'Set dict attribute without error';
-
-is $record->dict_with_maybe->{name}, 'frith'
- => 'correct set the dict attribute name';
-
-is $record->dict_with_maybe->{age}, 23
- => 'correct set the dict attribute age';
-throws_ok sub {
-    $record->dict_with_maybe({name=>[1,2,3], age=>'sdfsdfsd'});      
-}, qr/Validation failed for 'Str'/
- => 'Got Expected Error for bad value in dict';
-
-throws_ok sub {
-    $record->dict_with_maybe({age=>30});      
-}, qr/Validation failed for 'Str'/
- => 'Got Expected Error for missing named parameter';
-
-lives_ok sub {
-    $record->dict_with_maybe({name=>'usal'});
-} => 'Set dict attribute without error, skipping optional';
-
-## Test dict_with_tuple
-
-lives_ok sub {
-    $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
-} => 'Set tuple attribute without error';
-
-throws_ok sub {
-    $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
-}, qr/Validation failed for 'Int'/
- => 'Threw error on bad constraint';
-
-## Test optional_tuple
-
-lives_ok sub {
-    $record->optional_tuple([1,2,3]);
-} => 'Set tuple attribute with optional bits';
-
-is_deeply $record->optional_tuple, [1,2,3]
- => 'correct values set';
-lives_ok sub {
-    $record->optional_tuple([4,5]);
-} => 'Set tuple attribute withOUT optional bits';
-
-is_deeply $record->optional_tuple, [4,5]
- => 'correct values set again';
-throws_ok sub {
-    $record->optional_tuple([1,2,'bad']);   
-}, qr/Validation failed for 'Int'/
- => 'Properly failed for bad value in optional bit';
-
-# Test optional_dict
-
-lives_ok sub {
-    $record->optional_dict({key1=>1,key2=>2});
-} => 'Set tuple attribute with optional bits';
-
-is_deeply $record->optional_dict, {key1=>1,key2=>2}
- => 'correct values set';
-lives_ok sub {
-    $record->optional_dict({key1=>3});
-} => 'Set tuple attribute withOUT optional bits';
-
-is_deeply $record->optional_dict, {key1=>3}
- => 'correct values set again';
-throws_ok sub {
-    $record->optional_dict({key1=>1,key2=>'bad'});   
-}, qr/Validation failed for 'Int'/
- => 'Properly failed for bad value in optional bit';
-
-
-## Test dict_with_tuple_with_union: Dict[key1=>'Str|Object', key2=>Tuple['Int','Str|Object']]
-
-lives_ok sub {
-    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,'World']});
-} => 'Set tuple attribute without error';
-
-throws_ok sub {
-    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>['World',2]});
-}, qr/Validation failed for 'Int'/
- => 'Threw error on bad constraint';
-lives_ok sub {
-    $record->dict_with_tuple_with_union({key1=>$record, key2=>[1,'World']});
-} => 'Set tuple attribute without error';
-
-lives_ok sub {
-    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,$record]});
-} => 'Set tuple attribute without error';
-
-throws_ok sub {
-    $record->dict_with_tuple_with_union({key1=>1, key2=>['World',2]});
-}, qr/Validation failed for 'Int'/
- => 'Threw error on bad constraint';
diff --git a/t/02-tuple.t b/t/02-tuple.t
new file mode 100644 (file)
index 0000000..b214f9a
--- /dev/null
@@ -0,0 +1,151 @@
+BEGIN {
+       use strict;
+       use warnings;
+       use Test::More tests=>26;
+       use Test::Exception;
+}
+
+{
+    package Test::MooseX::Meta::TypeConstraint::Structured::Tuple;
+
+    use Moose;
+    use MooseX::Types::Structured qw(Tuple);
+       use MooseX::Types::Moose qw(Int Str Object ArrayRef HashRef Maybe);
+       use MooseX::Types -declare => [qw(MyString)];
+       
+    subtype MyString,
+     as 'Str',
+     where { $_=~m/abc/};
+     
+    #use Data::Dump qw/dump/; warn dump Tuple;
+
+    has 'tuple' => (is=>'rw', isa=>Tuple[Int, Str, MyString]);
+       has 'tuple_with_param' => (is=>'rw', isa=>Tuple[Int, Str, ArrayRef[Int]]);
+       has 'tuple_with_maybe' => (is=>'rw', isa=>Tuple[Int, Str, Maybe[Int], Object]);
+       has 'tuple_with_maybe2' => (is=>'rw', isa=>Tuple[Int, Str, Maybe[Int]]);        
+       has 'tuple_with_union' => (is=>'rw', isa=>Tuple[Int,Str,Int|Object,Int]);
+       has 'tuple2' => (is=>'rw', isa=>Tuple[Int,Str,Int]);
+       has 'tuple_with_parameterized' => (is=>'rw', isa=>Tuple[Int,Str,Int,ArrayRef[Int]]);
+}
+
+## Instantiate a new test object
+
+ok my $record = Test::MooseX::Meta::TypeConstraint::Structured::Tuple->new
+ => 'Instantiated new Record test class.';
+isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured::Tuple'
+ => 'Created correct object type.';
+## Test Tuple type constraint
+
+lives_ok sub {
+    $record->tuple([1,'hello', 'test.abc.test']);
+} => 'Set tuple attribute without error';
+
+is $record->tuple->[0], 1
+ => 'correct set the tuple attribute index 0';
+
+is $record->tuple->[1], 'hello'
+ => 'correct set the tuple attribute index 1';
+
+is $record->tuple->[2], 'test.abc.test'
+ => 'correct set the tuple attribute index 2';
+
+throws_ok sub {
+    $record->tuple([1,'hello', 'test.xxx.test']);    
+}, qr/Attribute \(tuple\) does not pass the type constraint/
+ => 'Properly failed for bad value in custom type constraint';
+throws_ok sub {
+    $record->tuple(['asdasd',2, 'test.abc.test']);      
+}, qr/Attribute \(tuple\) does not pass the type constraint/
+ => 'Got Expected Error for violating constraints';
+
+## Test tuple_with_maybe
+
+lives_ok sub {
+    $record->tuple_with_maybe([1,'hello', 1, $record]);
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->tuple_with_maybe([1,'hello', 'a', $record]);
+}, qr/Attribute \(tuple_with_maybe\) does not pass the type constraint/
+ => 'Properly failed for bad value parameterized constraint';
+
+lives_ok sub {
+    $record->tuple_with_maybe([1,'hello',undef, $record]);
+} => 'Set tuple attribute without error skipping optional parameter';
+
+## Test tuple_with_maybe2
+
+lives_ok sub {
+    $record->tuple_with_maybe2([1,'hello', 1]);
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->tuple_with_maybe2([1,'hello', 'a']);
+}, qr/Attribute \(tuple_with_maybe2\) does not pass the type constraint/
+ => 'Properly failed for bad value parameterized constraint';
+
+lives_ok sub {
+    $record->tuple_with_maybe2([1,'hello',undef]);
+} => 'Set tuple attribute without error skipping optional parameter';
+
+throws_ok sub {
+    $record->tuple_with_maybe2([1,'hello']);
+}, qr/Attribute \(tuple_with_maybe2\) does not pass the type constraint/
+ => 'Properly fails for missing maybe (needs to be at least undef)';
+
+## Test Tuple with parameterized type
+
+lives_ok sub {
+    $record->tuple_with_param([1,'hello', [1,2,3]]);
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->tuple_with_param([1,'hello', [qw/a b c/]]);
+}, qr/Attribute \(tuple_with_param\) does not pass the type constraint/
+ => 'Properly failed for bad value parameterized constraint';
+
+## Test tuple2 (Tuple[Int,Str,Int])
+
+ok $record->tuple2([1,'hello',3])
+ => "[1,'hello',3] properly suceeds";
+
+throws_ok sub {
+       $record->tuple2([1,2,'world']);
+}, qr/Attribute \(tuple2\) does not pass the type constraint/ => "[1,2,'world'] properly fails";
+
+throws_ok sub {
+       $record->tuple2(['hello1',2,3]);
+}, qr/Attribute \(tuple2\) does not pass the type constraint/ => "['hello',2,3] properly fails";
+
+throws_ok sub {
+       $record->tuple2(['hello2',2,'world']);
+}, qr/Attribute \(tuple2\) does not pass the type constraint/ => "['hello',2,'world'] properly fails";
+
+
+## Test tuple_with_parameterized (Tuple[Int,Str,Int,ArrayRef[Int]])
+
+ok $record->tuple_with_parameterized([1,'hello',3,[1,2,3]])
+ => "[1,'hello',3,[1,2,3]] properly suceeds";
+
+throws_ok sub {
+       $record->tuple_with_parameterized([1,2,'world']);
+}, qr/Attribute \(tuple_with_parameterized\) does not pass the type constraint/
+ => "[1,2,'world'] properly fails";
+
+throws_ok sub {
+       $record->tuple_with_parameterized(['hello1',2,3]);
+}, qr/Attribute \(tuple_with_parameterized\) does not pass the type constraint/
+ => "['hello',2,3] properly fails";
+
+throws_ok sub {
+       $record->tuple_with_parameterized(['hello2',2,'world']);
+}, qr/Attribute \(tuple_with_parameterized\) does not pass the type constraint/
+ => "['hello',2,'world'] properly fails";
+
+throws_ok sub {
+       $record->tuple_with_parameterized([1,'hello',3,[1,2,'world']]);
+}, qr/Attribute \(tuple_with_parameterized\) does not pass the type constraint/
+ => "[1,'hello',3,[1,2,'world']] properly fails";
diff --git a/t/03-dict.t b/t/03-dict.t
new file mode 100644 (file)
index 0000000..058d34c
--- /dev/null
@@ -0,0 +1,98 @@
+BEGIN {
+       use strict;
+       use warnings;
+       use Test::More tests=>17;
+       use Test::Exception;
+}
+
+{
+    package Test::MooseX::Meta::TypeConstraint::Structured::Dict;
+
+    use Moose;
+    use MooseX::Types::Structured qw(Dict Tuple);
+       use MooseX::Types::Moose qw(Int Str Object ArrayRef HashRef Maybe);
+       use MooseX::Types -declare => [qw(MyString)];
+       
+    subtype MyString,
+     as 'Str',
+     where { $_=~m/abc/};
+        
+    has 'dict' => (is=>'rw', isa=>Dict[name=>Str, age=>Int]);
+    has 'dict_with_maybe' => (is=>'rw', isa=>Dict[name=>Str, age=>Maybe[Int]]);        
+    has 'dict_with_tuple_with_union' => (is=>'rw', isa=>Dict[key1=>Str|Object, key2=>Tuple[Int,Str|Object]] );
+}
+
+## Instantiate a new test object
+
+ok my $record = Test::MooseX::Meta::TypeConstraint::Structured::Dict->new
+ => 'Instantiated new Record test class.';
+isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured::Dict'
+ => 'Created correct object type.';
+# Test dict Dict[name=>Str, age=>Int]
+lives_ok sub {
+    $record->dict({name=>'frith', age=>23});
+} => 'Set dict attribute without error';
+
+is $record->dict->{name}, 'frith'
+ => 'correct set the dict attribute name';
+
+is $record->dict->{age}, 23
+ => 'correct set the dict attribute age';
+throws_ok sub {
+    $record->dict({name=>[1,2,3], age=>'sdfsdfsd'});      
+}, qr/Attribute \(dict\) does not pass the type constraint/
+ => 'Got Expected Error for bad value in dict';
+## Test dict_with_maybe
+
+lives_ok sub {
+    $record->dict_with_maybe({name=>'frith', age=>23});
+} => 'Set dict attribute without error';
+
+is $record->dict_with_maybe->{name}, 'frith'
+ => 'correct set the dict attribute name';
+
+is $record->dict_with_maybe->{age}, 23
+ => 'correct set the dict attribute age';
+throws_ok sub {
+    $record->dict_with_maybe({name=>[1,2,3], age=>'sdfsdfsd'});      
+}, qr/Attribute \(dict_with_maybe\) does not pass the type constraint/
+ => 'Got Expected Error for bad value in dict';
+
+throws_ok sub {
+    $record->dict_with_maybe({age=>30});      
+}, qr/Attribute \(dict_with_maybe\) does not pass the type constraint/
+ => 'Got Expected Error for missing named parameter';
+
+lives_ok sub {
+    $record->dict_with_maybe({name=>'usal', age=>undef});
+} => 'Set dict attribute without error, skipping maybe';
+
+## Test dict_with_tuple_with_union: Dict[key1=>'Str|Object', key2=>Tuple['Int','Str|Object']]
+
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,'World']});
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>['World',2]});
+}, qr/Attribute \(dict_with_tuple_with_union\) does not pass the type constraint/
+ => 'Threw error on bad constraint';
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>$record, key2=>[1,'World']});
+} => 'Set tuple attribute without error';
+
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,$record]});
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->dict_with_tuple_with_union({key1=>1, key2=>['World',2]});
+}, qr/Attribute \(dict_with_tuple_with_union\) does not pass the type constraint/
+ => 'Threw error on bad constraint';
\ No newline at end of file
diff --git a/t/04-combined.t b/t/04-combined.t
new file mode 100644 (file)
index 0000000..242d2b5
--- /dev/null
@@ -0,0 +1,60 @@
+BEGIN {
+       use strict;
+       use warnings;
+       use Test::More tests=>9;
+       use Test::Exception;
+}
+
+{
+    package Test::MooseX::Meta::TypeConstraint::Structured::Combined;
+
+    use Moose;
+    use MooseX::Types::Structured qw(Dict Tuple);
+       use MooseX::Types::Moose qw(Int Str Object ArrayRef HashRef Maybe);
+        
+       has 'dict_with_tuple' => (is=>'rw', isa=>Dict[key1=>Str, key2=>Tuple[Int,Str]]);
+    has 'dict_with_tuple_with_union' => (is=>'rw', isa=>Dict[key1=>Str|Object, key2=>Tuple[Int,Str|Object]] );
+}
+
+## Instantiate a new test object
+
+ok my $record = Test::MooseX::Meta::TypeConstraint::Structured::Combined->new
+ => 'Instantiated new Record test class.';
+isa_ok $record => 'Test::MooseX::Meta::TypeConstraint::Structured::Combined'
+ => 'Created correct object type.';
+## Test dict_with_tuple
+
+lives_ok sub {
+    $record->dict_with_tuple({key1=>'Hello', key2=>[1,'World']});
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->dict_with_tuple({key1=>'Hello', key2=>['World',2]});
+}, qr/Attribute \(dict_with_tuple\) does not pass the type constraint/
+ => 'Threw error on bad constraint';
+## Test dict_with_tuple_with_union: Dict[key1=>'Str|Object', key2=>Tuple['Int','Str|Object']]
+
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,'World']});
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>['World',2]});
+}, qr/Attribute \(dict_with_tuple_with_union\) does not pass the type constraint/
+ => 'Threw error on bad constraint';
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>$record, key2=>[1,'World']});
+} => 'Set tuple attribute without error';
+
+lives_ok sub {
+    $record->dict_with_tuple_with_union({key1=>'Hello', key2=>[1,$record]});
+} => 'Set tuple attribute without error';
+
+throws_ok sub {
+    $record->dict_with_tuple_with_union({key1=>1, key2=>['World',2]});
+}, qr/Attribute \(dict_with_tuple_with_union\) does not pass the type constraint/
+ => 'Threw error on bad constraint';
diff --git a/t/optional.t b/t/optional.t
deleted file mode 100755 (executable)
index 4bfa0fc..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-BEGIN {
-       use strict;
-       use warnings;
-       use Test::More tests=>16;
-       use Test::Exception;
-       use Data::Dump qw/dump/;
-       
-       use_ok 'Moose::Util::TypeConstraints';
-}
-
-Moose::Util::TypeConstraints::register_type_constraint(
-       Moose::Meta::TypeConstraint::Parameterizable->new(
-               name  => 'Optional',
-               package_defined_in => __PACKAGE__,
-               parent => find_type_constraint('Item'),
-               constraint => sub { 1 },
-               constraint_generator => sub {
-                       my $type_parameter = shift;
-                       my $check = $type_parameter->_compiled_type_constraint;
-                       return sub {
-                               use Data::Dump qw/dump/;
-                               warn dump @_;
-                               return 1 if not(defined($_)) || $check->($_);
-                               return;
-                       }
-               }
-       )
-);
-
-ok Moose::Util::TypeConstraints::find_type_constraint('Optional')
- => 'Found the Optional Type';
-
-{
-       package Test::MooseX::Types::Optional;
-       use Moose;
-       
-       has 'Maybe_Int' => (is=>'rw', isa=>'Maybe[Int]');
-       has 'Maybe_ArrayRef' => (is=>'rw', isa=>'Maybe[ArrayRef]');     
-       has 'Maybe_HashRef' => (is=>'rw', isa=>'Maybe[HashRef]');       
-       has 'Maybe_ArrayRefInt' => (is=>'rw', isa=>'Maybe[ArrayRef[Int]]');     
-       has 'Maybe_HashRefInt' => (is=>'rw', isa=>'Maybe[HashRef[Int]]');       
-}
-
-ok my $obj = Test::MooseX::Types::Optional->new
- => 'Create good test object';
-
-##  Maybe[Int]
-
-ok my $Maybe_Int  = Moose::Util::TypeConstraints::find_or_parse_type_constraint('Maybe[Int]')
- => 'made TC Maybe[Int]';
-ok $Maybe_Int->check(1)
- => 'passed (1)';
-       ok $obj->Maybe_Int(1)
-        => 'assigned (1)';
-ok $Maybe_Int->check()
- => 'passed ()';
-
-       ok $obj->Maybe_Int()
-        => 'assigned ()';
-
-ok $Maybe_Int->check(0)
- => 'passed (0)';
-
-       ok defined $obj->Maybe_Int(0)
-        => 'assigned (0)';
-ok $Maybe_Int->check(undef)
- => 'passed (undef)';
-       ok sub {$obj->Maybe_Int(undef); 1}->()
-        => 'assigned (undef)';
-ok !$Maybe_Int->check("")
- => 'failed ("")';
-       throws_ok sub { $obj->Maybe_Int("") }, 
-        qr/Attribute \(Maybe_Int\) does not pass the type constraint/
-        => 'failed assigned ("")';
-
-ok !$Maybe_Int->check("a")
- => 'failed ("a")';
-
-       throws_ok sub { $obj->Maybe_Int("a") }, 
-        qr/Attribute \(Maybe_Int\) does not pass the type constraint/
-        => 'failed assigned ("a")';
-
-__END__
-
-
-ok $obj->Maybe_Int(undef)
- => 'passed 1';
-ok $obj->Maybe_Int();
-ok $obj->Maybe_Int('')
- => 'passed 1';
-
-ok $obj->Maybe_Int('a')
- => 'passed 1';
-
-
-
-
-ok $obj->tuple([1,'hello',3])
- => "[1,'hello',3] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-
-## Test tuple_with_parameterized (Tuple[Int,Str,Int,ArrayRef[Int]])
-
-ok $obj->tuple_with_parameterized([1,'hello',3,[1,2,3]])
- => "[1,'hello',3,[1,2,3]] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_parameterized([1,'hello',3,[1,2,'world']]);
-}, qr/Validation failed for 'ArrayRef\[Int\]'/ => "[1,'hello',3,[1,2,'world']] properly fails";
-
-
-## Test tuple_with_optional (Tuple[Int,Str,Int,Optional[Int,Int]])
-
-ok $obj->tuple_with_optional([1,'hello',3])
- => "[1,'hello',3] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,1])
- => "[1,'hello',3,1] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,4])
- => "[1,'hello',3,4] properly suceeds";
-
-ok $obj->tuple_with_optional([1,'hello',3,4,5])
- => "[1,'hello',3,4,5] properly suceeds";
-
-throws_ok sub {
-       $obj->tuple_with_optional([1,'hello',3,4,5,6]);
-}, qr/Too Many arguments for the available type constraints/ => "[1,'hello',3,4,5,6] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional([1,2,'world']);
-}, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional(['hello1',2,3]);
-}, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-throws_ok sub {
-       $obj->tuple_with_optional(['hello2',2,'world']);
-}, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-
-## tuple_with_union Tuple[Int,Str,Int|Object,Optional[Int|Object,Int]]
-
-SKIP: {
-
-       skip "Unions not supported for string parsed type constraints" => 8;
-
-       ok $obj->tuple_with_union([1,'hello',3])
-        => "[1,'hello',3] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,1])
-        => "[1,'hello',3,1] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,4])
-        => "[1,'hello',3,4] properly suceeds";
-
-       ok $obj->tuple_with_union([1,'hello',3,4,5])
-        => "[1,'hello',3,4,5] properly suceeds";
-
-       throws_ok sub {
-               $obj->tuple_with_union([1,'hello',3,4,5,6]);
-       }, qr/Too Many arguments for the available type constraints/ => "[1,'hello',3,4,5,6] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union([1,2,'world']);
-       }, qr/Validation failed for 'Int' failed with value world/ => "[1,2,'world'] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union(['hello1',2,3]);
-       }, qr/Validation failed for 'Int' failed with value hello1/ => "['hello',2,3] properly fails";
-
-       throws_ok sub {
-               $obj->tuple_with_union(['hello2',2,'world']);
-       }, qr/Validation failed for 'Int' failed with value hello2/ => "['hello',2,'world'] properly fails";
-}
-
diff --git a/t/suger.t b/t/suger.t
deleted file mode 100644 (file)
index 8e09c77..0000000
--- a/t/suger.t
+++ /dev/null
@@ -1,60 +0,0 @@
-BEGIN {
-       use strict;
-       use warnings;
-       use Test::More tests=>3;
-}
-
-## This is a first pass at what the regex enhancements to
-## Moose::Util::TypeConstraints is going to look like.  Basically I copyied
-## bits and added a little more parsing ability.
-{
-    ## Copied from Moose::Util::TypeConstraints
-    use re "eval";
-
-    my $any;
-    my $valid_chars = qr{[\w:]};
-    my $type_atom   = qr{ $valid_chars+ };
-    
-    my $type                = qr{  $valid_chars+  (?: \[  (??{$any})  \] )? }x;
-    my $type_capture_parts  = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
-    my $type_with_parameter = qr{  $valid_chars+      \[  (??{$any})  \]    }x;
-    
-    my $op_union = qr{ \s* \| \s* }x;
-    my $union    = qr{ $type (?: $op_union $type )+ }x;
-    
-    ## New Stuff for structured types.
-    my $comma = qr{,};
-    my $indirection = qr{=>};
-    my $divider_ops = qr{ $comma | $indirection }x;
-    my $structure_divider = qr{\s* $divider_ops \s*}x;    
-    my $structure_elements = qr{ ($type $structure_divider*)+ }x;
-
-       ## Addd the | $structure_elements to this.
-    $any = qr{ $type | $union | $structure_elements }x;
-    
-    ## New Proposed methods to parse and create
-    sub _parse_structured_type_constraint {
-        { no warnings 'void'; $any; } # force capture of interpolated lexical
-        
-        my($base, $elements) = ($_[0] =~ m{ $type_capture_parts }x);
-        return ($base, [split($structure_divider, $elements)]);
-    }
-    
-    is_deeply
-        [_parse_structured_type_constraint('ArrayRef[Int,Str]')],
-        ["ArrayRef", ["Int", "Str"]]
-     => 'Correctly parsed ArrayRef[Int,Str]';
-     
-    is_deeply
-        [_parse_structured_type_constraint('ArrayRef[ArrayRef[Int],Str]')],
-        ["ArrayRef", ["ArrayRef[Int]", "Str"]]
-     => 'Correctly parsed ArrayRef[ArrayRef[Int],Str]';
-         
-    is_deeply 
-        [_parse_structured_type_constraint('HashRef[key1 => Int, key2=>Int, key3=>ArrayRef[Int]]')],
-        ["HashRef", ["key1", "Int", "key2", "Int", "key3", "ArrayRef[Int]"]]
-     => 'Correctly parsed HashRef[key1 => Int, key2=>Int, key3=>ArrayRef[Int]]';
-
-}
\ No newline at end of file