use
5.008001;
our
$TLC_VERSION
=
"0.008"
;
our
@ISA
=
qw( Exporter )
;
our
@EXPORT
;
our
@EXPORT_OK
;
our
%EXPORT_TAGS
= (
is
=> [],
types
=> [],
assert
=> [],
);
BEGIN {
our
$LIBRARY
=
"TLC::Example"
;
fallback
=> !!1,
'|'
=>
'union'
,
bool
=>
sub
{ !! 1 },
'""'
=>
sub
{
shift
->{name} },
'&{}'
=>
sub
{
my
$self
=
shift
;
return
sub
{
$self
->assert_return(
@_
) };
},
);
sub
union {
my
@types
=
grep
ref
(
$_
),
@_
;
my
@checks
=
map
$_
->{check},
@types
;
bless
{
check
=>
sub
{
for
(
@checks
) {
return
1
if
$_
->(
@_
) }
return
0 },
name
=>
join
(
'|'
,
map
$_
->{name},
@types
),
union
=> \
@types
,
}, __PACKAGE__;
}
sub
check {
$_
[0]{check}->(
$_
[1] );
}
sub
get_message {
sprintf
'%s did not pass type constraint "%s"'
,
defined
(
$_
[1] ) ?
$_
[1] :
'Undef'
,
$_
[0]{name};
}
sub
validate {
$_
[0]{check}->(
$_
[1] )
?
undef
:
$_
[0]->get_message(
$_
[1] );
}
sub
assert_valid {
$_
[0]{check}->(
$_
[1] )
? 1
: Carp::croak(
$_
[0]->get_message(
$_
[1] ) );
}
sub
assert_return {
$_
[0]{check}->(
$_
[1] )
?
$_
[1]
: Carp::croak(
$_
[0]->get_message(
$_
[1] ) );
}
sub
to_TypeTiny {
if
(
$_
[0]{union} ) {
return
'Type::Tiny::Union'
->new(
display_name
=>
$_
[0]{name},
type_constraints
=> [
map
$_
->to_TypeTiny, @{
$_
[0]{union} } ],
);
}
if
(
my
$library
=
$_
[0]{library} ) {
local
$@;
eval
"require $library; 1"
or
die
$@;
my
$type
=
$library
->get_type(
$_
[0]{library_name} );
return
$type
if
$type
;
}
my
$check
=
$_
[0]{check};
my
$name
=
$_
[0]{name};
return
'Type::Tiny'
->new(
name
=>
$name
,
constraint
=>
sub
{
$check
->(
$_
) },
inlined
=>
sub
{
sprintf
'%s::is_%s(%s)'
,
$LIBRARY
,
$name
,
pop
}
);
}
sub
DOES {
return
1
if
$_
[1] eq
'Type::API::Constraint'
;
return
1
if
$_
[1] eq
'Type::Library::Compiler::TypeConstraint'
;
shift
->SUPER::DOES(
@_
);
}
};
{
my
$type
;
sub
Any () {
$type
||=
bless
( {
check
=> \
&is_Any
,
name
=>
"Any"
,
library
=>
"Types::Standard"
,
library_name
=>
"Any"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Any ($) {
(!!1)
}
sub
assert_Any ($) {
(!!1) ?
$_
[0] : Any->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Any"
} = [
qw( Any is_Any assert_Any )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Any"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Any"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Any"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Any"
;
}
{
my
$type
;
sub
Array () {
$type
||=
bless
( {
check
=> \
&is_Array
,
name
=>
"Array"
,
library
=>
"Types::Standard"
,
library_name
=>
"ArrayRef"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Array ($) {
(
ref
(
$_
[0]) eq
'ARRAY'
)
}
sub
assert_Array ($) {
(
ref
(
$_
[0]) eq
'ARRAY'
) ?
$_
[0] : Array->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Array"
} = [
qw( Array is_Array assert_Array )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Array"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Array"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Array"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Array"
;
}
{
my
$type
;
sub
Directory () {
$type
||=
bless
( {
check
=> \
&is_Directory
,
name
=>
"Directory"
,
library
=>
"Types::Path::Tiny"
,
library_name
=>
"Dir"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Directory ($) {
do
{ (
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) })&& (-d
$_
[0]) }
}
sub
assert_Directory ($) {
do
{ (
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) })&& (-d
$_
[0]) } ?
$_
[0] : Directory->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Directory"
} = [
qw( Directory is_Directory assert_Directory )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Directory"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Directory"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Directory"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Directory"
;
}
{
my
$type
;
sub
File () {
$type
||=
bless
( {
check
=> \
&is_File
,
name
=>
"File"
,
library
=>
"Types::Path::Tiny"
,
library_name
=>
"File"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_File ($) {
do
{ (
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) })&& (-f
$_
[0]) }
}
sub
assert_File ($) {
do
{ (
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) })&& (-f
$_
[0]) } ?
$_
[0] : File->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"File"
} = [
qw( File is_File assert_File )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"File"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"File"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_File"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_File"
;
}
{
my
$type
;
sub
Hash () {
$type
||=
bless
( {
check
=> \
&is_Hash
,
name
=>
"Hash"
,
library
=>
"Types::Standard"
,
library_name
=>
"HashRef"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Hash ($) {
(
ref
(
$_
[0]) eq
'HASH'
)
}
sub
assert_Hash ($) {
(
ref
(
$_
[0]) eq
'HASH'
) ?
$_
[0] : Hash->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Hash"
} = [
qw( Hash is_Hash assert_Hash )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Hash"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Hash"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Hash"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Hash"
;
}
{
my
$type
;
sub
Integer () {
$type
||=
bless
( {
check
=> \
&is_Integer
,
name
=>
"Integer"
,
library
=>
"Types::Standard"
,
library_name
=>
"Int"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Integer ($) {
(
do
{
my
$tmp
=
$_
[0];
defined
(
$tmp
) and !
ref
(
$tmp
) and
$tmp
=~ /\A-?[0-9]+\z/ })
}
sub
assert_Integer ($) {
(
do
{
my
$tmp
=
$_
[0];
defined
(
$tmp
) and !
ref
(
$tmp
) and
$tmp
=~ /\A-?[0-9]+\z/ }) ?
$_
[0] : Integer->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Integer"
} = [
qw( Integer is_Integer assert_Integer )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Integer"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Integer"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Integer"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Integer"
;
}
{
my
$type
;
sub
NonEmptyString () {
$type
||=
bless
( {
check
=> \
&is_NonEmptyString
,
name
=>
"NonEmptyString"
,
library
=>
"Types::Common::String"
,
library_name
=>
"NonEmptyStr"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_NonEmptyString ($) {
((
do
{
defined
(
$_
[0]) and
do
{
ref
(\
$_
[0]) eq
'SCALAR'
or
ref
(\(
my
$val
=
$_
[0])) eq
'SCALAR'
} }) && (
length
(
$_
[0]) > 0))
}
sub
assert_NonEmptyString ($) {
((
do
{
defined
(
$_
[0]) and
do
{
ref
(\
$_
[0]) eq
'SCALAR'
or
ref
(\(
my
$val
=
$_
[0])) eq
'SCALAR'
} }) && (
length
(
$_
[0]) > 0)) ?
$_
[0] : NonEmptyString->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"NonEmptyString"
} = [
qw( NonEmptyString is_NonEmptyString assert_NonEmptyString )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"NonEmptyString"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"NonEmptyString"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_NonEmptyString"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_NonEmptyString"
;
}
{
my
$type
;
sub
Null () {
$type
||=
bless
( {
check
=> \
&is_Null
,
name
=>
"Null"
,
library
=>
"Types::Standard"
,
library_name
=>
"Undef"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Null ($) {
(!
defined
(
$_
[0]))
}
sub
assert_Null ($) {
(!
defined
(
$_
[0])) ?
$_
[0] : Null->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Null"
} = [
qw( Null is_Null assert_Null )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Null"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Null"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Null"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Null"
;
}
{
my
$type
;
sub
Number () {
$type
||=
bless
( {
check
=> \
&is_Number
,
name
=>
"Number"
,
library
=>
"Types::Standard"
,
library_name
=>
"Num"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Number ($) {
(
do
{
use
Scalar::Util ();
defined
(
$_
[0]) && !
ref
(
$_
[0]) && Scalar::Util::looks_like_number(
$_
[0]) })
}
sub
assert_Number ($) {
(
do
{
use
Scalar::Util ();
defined
(
$_
[0]) && !
ref
(
$_
[0]) && Scalar::Util::looks_like_number(
$_
[0]) }) ?
$_
[0] : Number->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Number"
} = [
qw( Number is_Number assert_Number )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Number"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Number"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Number"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Number"
;
}
{
my
$type
;
sub
Object () {
$type
||=
bless
( {
check
=> \
&is_Object
,
name
=>
"Object"
,
library
=>
"Types::Standard"
,
library_name
=>
"Object"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Object ($) {
}
sub
assert_Object ($) {
(
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) }) ?
$_
[0] : Object->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Object"
} = [
qw( Object is_Object assert_Object )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Object"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Object"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Object"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Object"
;
}
{
my
$type
;
sub
Path () {
$type
||=
bless
( {
check
=> \
&is_Path
,
name
=>
"Path"
,
library
=>
"Types::Path::Tiny"
,
library_name
=>
"Path"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_Path ($) {
(
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) })
}
sub
assert_Path ($) {
(
do
{
use
Scalar::Util (); Scalar::Util::blessed(
$_
[0]) and
$_
[0]->isa(
q[Path::Tiny]
) }) ?
$_
[0] : Path->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"Path"
} = [
qw( Path is_Path assert_Path )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"Path"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"Path"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_Path"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_Path"
;
}
{
my
$type
;
sub
String () {
$type
||=
bless
( {
check
=> \
&is_String
,
name
=>
"String"
,
library
=>
"Types::Standard"
,
library_name
=>
"Str"
},
"TLC::Example::TypeConstraint"
);
}
sub
is_String ($) {
do
{
defined
(
$_
[0]) and
do
{
ref
(\
$_
[0]) eq
'SCALAR'
or
ref
(\(
my
$val
=
$_
[0])) eq
'SCALAR'
} }
}
sub
assert_String ($) {
do
{
defined
(
$_
[0]) and
do
{
ref
(\
$_
[0]) eq
'SCALAR'
or
ref
(\(
my
$val
=
$_
[0])) eq
'SCALAR'
} } ?
$_
[0] : String->get_message(
$_
[0] );
}
$EXPORT_TAGS
{
"String"
} = [
qw( String is_String assert_String )
];
push
@EXPORT_OK
, @{
$EXPORT_TAGS
{
"String"
} };
push
@{
$EXPORT_TAGS
{
"types"
} },
"String"
;
push
@{
$EXPORT_TAGS
{
"is"
} },
"is_String"
;
push
@{
$EXPORT_TAGS
{
"assert"
} },
"assert_String"
;
}
1;