
use MooseX::Types -declare [qw/Str/]; 
use MooseX::Types::Faceted qw(Str);

subtype Name()
 => as Str()
 => with hasMaxLength(25), 
 isWordCharacters(), 
 callBack { 
 
 
 
 => as Faceted[
 	Str(),
 	hasMaxLength(25),
 ],


use MooseX::Types::Moose qw(Int Str ArrayRef HashRef Object);
use MooseX::Types::Structured qw(Dict);

use MooseX::Types
	-declare => [qw/PositiveInt Length/];

use MooseX::Types::Parameterizable 
	-declare => [qw/MinLength MaxLength Size/];

subtype PositiveInt,
	as Int,
	where { $_ >= 0 };

type Length,
	where { exists $_ && defined $_ };

coerce Length,
	from PositiveInt,
	via { $_ },
	from Str,
	via { length $_ },
	from ArrayRef,
	via { scalar @$_ },
	from HashRef,
	via { scalar keys %$_ };

subtype MinLength[Length],
	as Value,
	where {
		my ($check, $parameter) = @_
		return $parameter < length($check) ? 1:0;
	};

subtype MaxLength[Length],
	as Value,
	where {
		my ($check, $parameter) = @_
		return $parameter >= length($check) ? 1:0;
	};

subtype Size[Dict[max=>MaxLength,min=>MinLength]],
	as Value,
	where {
		my ($check, $parameter) = @_;
		$parameter->{max} > $parameter->{min};
	}


	Size[min=>5,max=>10]->check('aabbcc');  ## OK, length 6 in range
	Size[min=>5,max=>10]->check('aa'); ## Not OK, length 2 out of range
	Size[min=>5,max=>10]->check([1..8]); ## OK via coercion
	Size[min=>1,max=>3]->check({a=>1,b=>2}); ## Ok via coercion
	Size[min=>5,max=>10]->check($object); ## Not at least an Int

	Size[min=>-10,max=>100]; ## NOT PositiveInt
	Size[min=>'aaa', max=>100]; ## Not an Int
	Size[min=>5, max=>2]; ## Not a Range
 

