Initial Commit
This commit is contained in:
324
database/perl/vendor/lib/Specio/Coercion.pm
vendored
Normal file
324
database/perl/vendor/lib/Specio/Coercion.pm
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
package Specio::Coercion;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Specio::OO;
|
||||
|
||||
use Role::Tiny::With;
|
||||
|
||||
use Specio::Role::Inlinable;
|
||||
with 'Specio::Role::Inlinable';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $role_attrs = Specio::Role::Inlinable::_attrs();
|
||||
## use critic
|
||||
|
||||
my $attrs = {
|
||||
%{$role_attrs},
|
||||
from => {
|
||||
does => 'Specio::Constraint::Role::Interface',
|
||||
required => 1,
|
||||
},
|
||||
to => {
|
||||
does => 'Specio::Constraint::Role::Interface',
|
||||
required => 1,
|
||||
weak_ref => 1,
|
||||
},
|
||||
_coercion => {
|
||||
isa => 'CodeRef',
|
||||
predicate => '_has_coercion',
|
||||
init_arg => 'coercion',
|
||||
},
|
||||
_optimized_coercion => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_optimized_coercion',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
die
|
||||
'A type coercion should have either a coercion or inline_generator parameter, not both'
|
||||
if $self->_has_coercion && $self->_has_inline_generator;
|
||||
|
||||
die
|
||||
'A type coercion must have either a coercion or inline_generator parameter'
|
||||
unless $self->_has_coercion || $self->_has_inline_generator;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub coerce {
|
||||
my $self = shift;
|
||||
my $value = shift;
|
||||
|
||||
return $self->_optimized_coercion->($value);
|
||||
}
|
||||
|
||||
sub inline_coercion {
|
||||
my $self = shift;
|
||||
|
||||
return $self->_inline_generator->( $self, @_ );
|
||||
}
|
||||
|
||||
sub _build_optimized_coercion {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->_has_inline_generator ) {
|
||||
return $self->_generated_inline_sub;
|
||||
}
|
||||
else {
|
||||
return $self->_coercion;
|
||||
}
|
||||
}
|
||||
|
||||
sub can_be_inlined {
|
||||
my $self = shift;
|
||||
|
||||
return $self->_has_inline_generator && $self->from->can_be_inlined;
|
||||
}
|
||||
|
||||
sub _build_description {
|
||||
my $self = shift;
|
||||
|
||||
my $from_name
|
||||
= defined $self->from->name ? $self->from->name : 'anonymous type';
|
||||
my $to_name
|
||||
= defined $self->to->name ? $self->to->name : 'anonymous type';
|
||||
my $desc = "coercion from $from_name to $to_name";
|
||||
|
||||
$desc .= q{ } . $self->declared_at->description;
|
||||
|
||||
return $desc;
|
||||
}
|
||||
|
||||
sub clone_with_new_to {
|
||||
my $self = shift;
|
||||
my $new_to = shift;
|
||||
|
||||
my $from = $self->from;
|
||||
|
||||
local $self->{from} = undef;
|
||||
local $self->{to} = undef;
|
||||
|
||||
my $clone = $self->clone;
|
||||
|
||||
$clone->{from} = $from;
|
||||
$clone->{to} = $new_to;
|
||||
|
||||
return $clone;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class representing a coercion from one type to another
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Coercion - A class representing a coercion from one type to another
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $coercion = $type->coercion_from_type('Int');
|
||||
|
||||
my $new_value = $coercion->coerce_value(42);
|
||||
|
||||
if ( $coercion->can_be_inlined() ) {
|
||||
my $code = $coercion->inline_coercion('$_[0]');
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class represents a coercion from one type to another. Internally, a
|
||||
coercion is a piece of code that takes a value of one type returns a new value
|
||||
of a new type. For example, a coercion from c<Num> to C<Int> might round a
|
||||
number to its nearest integer and return that integer.
|
||||
|
||||
Coercions can be implemented either as a simple subroutine reference or as an
|
||||
inline generator subroutine. Using an inline generator is faster but more
|
||||
complicated.
|
||||
|
||||
=for Pod::Coverage BUILD clone_with_new_to
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides the following methods.
|
||||
|
||||
=head2 Specio::Coercion->new( ... )
|
||||
|
||||
This method creates a new coercion object. It accepts the following named
|
||||
parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * from => $type
|
||||
|
||||
The type this coercion is from. The type must be an object which does the
|
||||
L<Specio::Constraint::Role::Interface> interface.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * to => $type
|
||||
|
||||
The type this coercion is to. The type must be an object which does the
|
||||
L<Specio::Constraint::Role::Interface> interface.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * coercion => sub { ... }
|
||||
|
||||
A subroutine reference implementing the coercion. It will be called as a
|
||||
method on the object and passed a single argument, the value to coerce.
|
||||
|
||||
It should return the new value.
|
||||
|
||||
This parameter is mutually exclusive with C<inline_generator>.
|
||||
|
||||
Either this parameter or the C<inline_generator> parameter is required.
|
||||
|
||||
You can also pass this option with the key C<using> in the parameter list.
|
||||
|
||||
=item * inline_generator => sub { ... }
|
||||
|
||||
This should be a subroutine reference which returns a string containing a
|
||||
single term. This code should I<not> end in a semicolon. This code should
|
||||
implement the coercion.
|
||||
|
||||
The generator will be called as a method on the coercion with a single
|
||||
argument. That argument is the name of the variable being coerced, something
|
||||
like C<'$_[0]'> or C<'$var'>.
|
||||
|
||||
This parameter is mutually exclusive with C<coercion>.
|
||||
|
||||
Either this parameter or the C<coercion> parameter is required.
|
||||
|
||||
You can also pass this option with the key C<inline> in the parameter list.
|
||||
|
||||
=item * inline_environment => {}
|
||||
|
||||
This should be a hash reference of variable names (with sigils) and values for
|
||||
that variable. The values should be I<references> to the values of the
|
||||
variables.
|
||||
|
||||
This environment will be used when compiling the coercion as part of a
|
||||
subroutine. The named variables will be captured as closures in the generated
|
||||
subroutine, using L<Eval::Closure>.
|
||||
|
||||
It should be very rare to need to set this in the constructor. It's more
|
||||
likely that a special coercion subclass would need to provide values that it
|
||||
generates internally.
|
||||
|
||||
This parameter defaults to an empty hash reference.
|
||||
|
||||
=item * declared_at => $declared_at
|
||||
|
||||
This parameter must be a L<Specio::DeclaredAt> object.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=back
|
||||
|
||||
=head2 $coercion->from(), $coercion->to(), $coercion->declared_at()
|
||||
|
||||
These methods are all read-only attribute accessors for the corresponding
|
||||
attribute.
|
||||
|
||||
=head2 $coercion->description
|
||||
|
||||
This returns a string describing the coercion. This includes the names of the
|
||||
to and from type and where the coercion was declared, so you end up with
|
||||
something like C<'coercion from Foo to Bar declared in package My::Lib
|
||||
(lib/My/Lib.pm) at line 42'>.
|
||||
|
||||
=head2 $coercion->coerce($value)
|
||||
|
||||
Given a value of the right "from" type, returns a new value of the "to" type.
|
||||
|
||||
This method does not actually check that the types of given or return values.
|
||||
|
||||
=head2 $coercion->inline_coercion($var)
|
||||
|
||||
Given a variable name like C<'$_[0]'> this returns a string with code for the
|
||||
coercion.
|
||||
|
||||
Note that this method will die if the coercion does not have an inline
|
||||
generator.
|
||||
|
||||
=head2 $coercion->can_be_inlined()
|
||||
|
||||
This returns true if the coercion has an inline generator I<and> the
|
||||
constraint it is from can be inlined. This exists primarily for the benefit of
|
||||
the C<inline_coercion_and_check()> method for type constraint object.
|
||||
|
||||
=head2 $coercion->inline_environment()
|
||||
|
||||
This returns a hash defining the variables that need to be closed over when
|
||||
inlining the coercion. The keys are full variable names like C<'$foo'> or
|
||||
C<'@bar'>. The values are I<references> to a variable of the matching type.
|
||||
|
||||
=head2 $coercion->clone()
|
||||
|
||||
Returns a clone of this object.
|
||||
|
||||
=head2 $coercion->clone_with_new_to($new_to_type)
|
||||
|
||||
This returns a clone of the coercion, replacing the "to" type with a new
|
||||
one. This is intended for use when the to type itself is being cloned as part
|
||||
of importing that type. We need to make sure the newly cloned coercion has the
|
||||
newly cloned type as well.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Role::Inlinable> role.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
150
database/perl/vendor/lib/Specio/Constraint/AnyCan.pm
vendored
Normal file
150
database/perl/vendor/lib/Specio/Constraint/AnyCan.pm
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
package Specio::Constraint::AnyCan;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use List::Util 1.33 ();
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::CanType;
|
||||
with 'Specio::Constraint::Role::CanType';
|
||||
|
||||
{
|
||||
my $Defined = t('Defined');
|
||||
sub _build_parent {$Defined}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
my $methods = join ', ', map { perlstring($_) } @{ $self->methods };
|
||||
return sprintf( <<'EOF', $val, $methods );
|
||||
(
|
||||
do {
|
||||
# We need to assign this since if it's something like $_[0] then
|
||||
# inside the all block @_ gets redefined and we can no longer get at
|
||||
# the value.
|
||||
my $v = %s;
|
||||
(
|
||||
Scalar::Util::blessed($v) || (
|
||||
defined($v)
|
||||
&& !ref($v)
|
||||
&& length($v)
|
||||
&& $v !~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
|
||||
# Passing a GLOB from (my $glob = *GLOB) gives us a very weird
|
||||
# scalar. It's not a ref and it has a length but trying to
|
||||
# call ->can on it throws an exception
|
||||
&& ref( \$v ) ne 'GLOB'
|
||||
)
|
||||
) && List::Util::all { $v->can($_) } %s;
|
||||
}
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {1}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require a class name or object with a set of methods
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::AnyCan - A class for constraints which require a class name or object with a set of methods
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::AnyCan->new(...);
|
||||
print $_, "\n" for @{ $type->methods };
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require a class
|
||||
name or object with a defined set of methods.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::AnyCan->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Defined> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<methods>. This must be
|
||||
an array reference of method names which the constraint requires. You can also
|
||||
pass a single string and it will be converted to an array reference
|
||||
internally.
|
||||
|
||||
=head2 $any_can->methods
|
||||
|
||||
Returns an array reference containing the methods this constraint requires.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::IsaType>,
|
||||
L<Specio::Constraint::Role::Interface>, and L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
139
database/perl/vendor/lib/Specio/Constraint/AnyDoes.pm
vendored
Normal file
139
database/perl/vendor/lib/Specio/Constraint/AnyDoes.pm
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
package Specio::Constraint::AnyDoes;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::DoesType;
|
||||
with 'Specio::Constraint::Role::DoesType';
|
||||
|
||||
{
|
||||
my $Defined = t('Defined');
|
||||
sub _build_parent {$Defined}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', ($val) x 8, perlstring( $self->role ) );
|
||||
(
|
||||
(
|
||||
Scalar::Util::blessed(%s) || (
|
||||
!ref(%s)
|
||||
&& defined(%s)
|
||||
&& length(%s)
|
||||
&& %s !~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
&& ref( \%s ) ne 'GLOB'
|
||||
)
|
||||
)
|
||||
&& %s->can('does')
|
||||
&& %s->does(%s)
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {1}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require a class name or an object that does a specific role
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::AnyDoes - A class for constraints which require a class name or an object that does a specific role
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::AnyDoes->new(...);
|
||||
print $type->role;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require a class
|
||||
name or an object that does a specific role.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::AnyDoes->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Defined> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<role>. This must be a
|
||||
single role name.
|
||||
|
||||
=head2 $any_isa->role
|
||||
|
||||
Returns the role name passed to the constructor.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::DoesType>,
|
||||
L<Specio::Constraint::Role::Interface>, L<Specio::Role::Inlinable>, and
|
||||
L<MooseX::Clone> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
142
database/perl/vendor/lib/Specio/Constraint/AnyIsa.pm
vendored
Normal file
142
database/perl/vendor/lib/Specio/Constraint/AnyIsa.pm
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
package Specio::Constraint::AnyIsa;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::IsaType;
|
||||
with 'Specio::Constraint::Role::IsaType';
|
||||
|
||||
{
|
||||
my $Defined = t('Defined');
|
||||
sub _build_parent {$Defined}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', ($val) x 7, perlstring( $self->class ) );
|
||||
(
|
||||
(
|
||||
Scalar::Util::blessed(%s)
|
||||
|| (
|
||||
defined(%s)
|
||||
&& !ref(%s)
|
||||
&& length(%s)
|
||||
&& %s !~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
|
||||
# Passing a GLOB from (my $glob = *GLOB) gives us a very weird
|
||||
# scalar. It's not a ref and it has a length but trying to
|
||||
# call ->can on it throws an exception
|
||||
&& ref( \%s ) ne 'GLOB'
|
||||
)
|
||||
)
|
||||
&& %s->isa(%s)
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {1}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require a class name or an object that inherit from a specific class
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::AnyIsa - A class for constraints which require a class name or an object that inherit from a specific class
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::AnyIsa->new(...);
|
||||
print $type->class;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require a class
|
||||
name or an object that inherit from a specific class.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::AnyIsa->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Defined> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<class>. This must be a
|
||||
single class name.
|
||||
|
||||
=head2 $any_isa->class
|
||||
|
||||
Returns the class name passed to the constructor.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::IsaType>,
|
||||
L<Specio::Constraint::Role::Interface>, and L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
151
database/perl/vendor/lib/Specio/Constraint/Enum.pm
vendored
Normal file
151
database/perl/vendor/lib/Specio/Constraint/Enum.pm
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
package Specio::Constraint::Enum;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util qw( refaddr );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( parent _inline_generator )) {
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
$attrs->{values} = {
|
||||
isa => 'ArrayRef',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $Str = t('Str');
|
||||
sub _build_parent {$Str}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', ($val) x 2, $self->_env_var_name, $val );
|
||||
( !ref( %s ) && defined( %s ) && $%s{ %s } )
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
sub _build_inline_environment {
|
||||
my $self = shift;
|
||||
|
||||
my %values = map { $_ => 1 } @{ $self->values };
|
||||
|
||||
return { '%' . $self->_env_var_name => \%values };
|
||||
}
|
||||
|
||||
sub _env_var_name {
|
||||
my $self = shift;
|
||||
|
||||
return '_Specio_Constraint_Enum_' . refaddr($self);
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require a string matching one of a set of values
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Enum - A class for constraints which require a string matching one of a set of values
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::Enum->new(...);
|
||||
print $_, "\n" for @{ $type->values };
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require a string
|
||||
that matches one of a list of values.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::Enum->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Str> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
Finally, this class requires an additional parameter, C<values>. This must be a
|
||||
an arrayref of valid strings for the type.
|
||||
|
||||
=head2 $enum->values
|
||||
|
||||
Returns an array reference of valid values for the type.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::Interface> and
|
||||
L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
199
database/perl/vendor/lib/Specio/Constraint/Intersection.pm
vendored
Normal file
199
database/perl/vendor/lib/Specio/Constraint/Intersection.pm
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
package Specio::Constraint::Intersection;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use List::Util qw( all );
|
||||
use Role::Tiny::With;
|
||||
use Specio::OO;
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( _constraint _inline_generator )) {
|
||||
delete $attrs->{$name}{predicate};
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{lazy} = 1;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
delete $attrs->{parent};
|
||||
|
||||
delete $attrs->{name}{predicate};
|
||||
$attrs->{name}{lazy} = 1;
|
||||
$attrs->{name}{builder} = '_build_name';
|
||||
|
||||
$attrs->{of} = {
|
||||
isa => 'ArrayRef',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub parent {undef}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _has_parent {0}
|
||||
|
||||
sub _has_name {
|
||||
my $self = shift;
|
||||
return defined $self->name;
|
||||
}
|
||||
|
||||
sub _build_name {
|
||||
my $self = shift;
|
||||
|
||||
return unless all { $_->_has_name } @{ $self->of };
|
||||
return join q{ & }, map { $_->name } @{ $self->of };
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _has_constraint {
|
||||
my $self = shift;
|
||||
|
||||
return !$self->_has_inline_generator;
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _build_constraint {
|
||||
return $_[0]->_optimized_constraint;
|
||||
}
|
||||
|
||||
sub _build_optimized_constraint {
|
||||
my $self = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my @c = map { $_->_optimized_constraint } @{ $self->of };
|
||||
return sub {
|
||||
return all { $_->( $_[0] ) } @c;
|
||||
};
|
||||
}
|
||||
|
||||
sub _has_inline_generator {
|
||||
my $self = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
return all { $_->_has_inline_generator } @{ $self->of };
|
||||
}
|
||||
|
||||
sub _build_inline_generator {
|
||||
my $self = shift;
|
||||
|
||||
return sub {
|
||||
return '(' . (
|
||||
join q{ && },
|
||||
map { sprintf( '( %s )', $_->_inline_generator->( $_, $_[1] ) ) }
|
||||
@{ $self->of }
|
||||
) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
sub _build_inline_environment {
|
||||
my $self = shift;
|
||||
|
||||
my %env;
|
||||
for my $type ( @{ $self->of } ) {
|
||||
%env = (
|
||||
%env,
|
||||
%{ $type->inline_environment },
|
||||
);
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for intersection constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Intersection - A class for intersection constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::Untion->new(...);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for intersections, which will
|
||||
allow a value which matches each one of several distinct types.
|
||||
|
||||
=for Pod::Coverage parent
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::Intersection->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always C<undef>
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
Finally, this class requires an additional parameter, C<of>. This must be an
|
||||
arrayref of type objects.
|
||||
|
||||
=head2 $union->of
|
||||
|
||||
Returns an array reference of the individual types which makes up this
|
||||
intersection.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::Interface> and
|
||||
L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
131
database/perl/vendor/lib/Specio/Constraint/ObjectCan.pm
vendored
Normal file
131
database/perl/vendor/lib/Specio/Constraint/ObjectCan.pm
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
package Specio::Constraint::ObjectCan;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use List::Util 1.33 ();
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::CanType;
|
||||
with 'Specio::Constraint::Role::CanType';
|
||||
|
||||
{
|
||||
my $Object = t('Object');
|
||||
sub _build_parent {$Object}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
my $methods = join ', ', map { perlstring($_) } @{ $self->methods };
|
||||
return sprintf( <<'EOF', $val, $methods );
|
||||
(
|
||||
do {
|
||||
my $v = %s;
|
||||
Scalar::Util::blessed($v)
|
||||
&& List::Util::all { $v->can($_) } %s;
|
||||
}
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {0}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require an object with a set of methods
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::ObjectCan - A class for constraints which require an object with a set of methods
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::ObjectCan->new(...);
|
||||
print $_, "\n" for @{ $type->methods };
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require an object
|
||||
with a defined set of methods.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::ObjectCan->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Object> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<methods>. This must be
|
||||
an array reference of method names which the constraint requires. You can also
|
||||
pass a single string and it will be converted to an array reference
|
||||
internally.
|
||||
|
||||
=head2 $object_can->methods
|
||||
|
||||
Returns an array reference containing the methods this constraint requires.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::CanType>,
|
||||
L<Specio::Constraint::Role::Interface>, and L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
121
database/perl/vendor/lib/Specio/Constraint/ObjectDoes.pm
vendored
Normal file
121
database/perl/vendor/lib/Specio/Constraint/ObjectDoes.pm
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package Specio::Constraint::ObjectDoes;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::DoesType;
|
||||
with 'Specio::Constraint::Role::DoesType';
|
||||
|
||||
{
|
||||
my $Object = t('Object');
|
||||
sub _build_parent {$Object}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', ($val) x 3, perlstring( $self->role ) );
|
||||
( Scalar::Util::blessed(%s) && %s->can('does') && %s->does(%s) )
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {0}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require an object that does a specific role
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::ObjectDoes - A class for constraints which require an object that does a specific role
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::ObjectDoes->new(...);
|
||||
print $type->role;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require an object
|
||||
that does a specific role.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::ObjectDoes->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Defined> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<role>. This must be a
|
||||
single role name.
|
||||
|
||||
=head2 $object_isa->role
|
||||
|
||||
Returns the role name passed to the constructor.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::DoesType>,
|
||||
L<Specio::Constraint::Role::Interface>, and L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
121
database/perl/vendor/lib/Specio/Constraint/ObjectIsa.pm
vendored
Normal file
121
database/perl/vendor/lib/Specio/Constraint/ObjectIsa.pm
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package Specio::Constraint::ObjectIsa;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util ();
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::OO;
|
||||
|
||||
use Specio::Constraint::Role::IsaType;
|
||||
with 'Specio::Constraint::Role::IsaType';
|
||||
|
||||
{
|
||||
my $Object = t('Object');
|
||||
sub _build_parent {$Object}
|
||||
}
|
||||
|
||||
{
|
||||
my $_inline_generator = sub {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', $val, $val, perlstring( $self->class ) );
|
||||
( Scalar::Util::blessed( %s ) && %s->isa(%s) )
|
||||
EOF
|
||||
};
|
||||
|
||||
sub _build_inline_generator {$_inline_generator}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _allow_classes {0}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for constraints which require an object that inherits from a specific class
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::ObjectIsa - A class for constraints which require an object that inherits from a specific class
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::ObjectIsa->new(...);
|
||||
print $type->class;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for types which require an object
|
||||
that inherits from a specific class.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::ObjectIsa->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always set to the
|
||||
C<Defined> type.
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
This class overrides the C<message_generator> default if none is provided.
|
||||
|
||||
Finally, this class requires an additional parameter, C<class>. This must be a
|
||||
single class name.
|
||||
|
||||
=head2 $object_isa->class
|
||||
|
||||
Returns the class name passed to the constructor.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::IsaType>,
|
||||
L<Specio::Constraint::Role::Interface>, and L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
209
database/perl/vendor/lib/Specio/Constraint/Parameterizable.pm
vendored
Normal file
209
database/perl/vendor/lib/Specio/Constraint/Parameterizable.pm
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
package Specio::Constraint::Parameterizable;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use Role::Tiny::With;
|
||||
use Specio::Constraint::Parameterized;
|
||||
use Specio::DeclaredAt;
|
||||
use Specio::OO;
|
||||
use Specio::TypeChecks qw( does_role isa_class );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $role_attrs = Specio::Constraint::Role::Interface::_attrs();
|
||||
## use critic
|
||||
|
||||
my $attrs = {
|
||||
%{$role_attrs},
|
||||
_parameterized_constraint_generator => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'parameterized_constraint_generator',
|
||||
predicate => '_has_parameterized_constraint_generator',
|
||||
},
|
||||
_parameterized_inline_generator => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'parameterized_inline_generator',
|
||||
predicate => '_has_parameterized_inline_generator',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->_has_constraint ) {
|
||||
die
|
||||
'A parameterizable constraint with a constraint parameter must also have a parameterized_constraint_generator'
|
||||
unless $self->_has_parameterized_constraint_generator;
|
||||
}
|
||||
|
||||
if ( $self->_has_inline_generator ) {
|
||||
die
|
||||
'A parameterizable constraint with an inline_generator parameter must also have a parameterized_inline_generator'
|
||||
unless $self->_has_parameterized_inline_generator;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub parameterize {
|
||||
my $self = shift;
|
||||
my %args = @_;
|
||||
|
||||
my ( $parameter, $declared_at ) = @args{qw( of declared_at )};
|
||||
does_role( $parameter, 'Specio::Constraint::Role::Interface' )
|
||||
or confess
|
||||
'The "of" parameter passed to ->parameterize must be an object which does the Specio::Constraint::Role::Interface role';
|
||||
|
||||
if ($declared_at) {
|
||||
isa_class( $declared_at, 'Specio::DeclaredAt' )
|
||||
or confess
|
||||
'The "declared_at" parameter passed to ->parameterize must be a Specio::DeclaredAt object';
|
||||
}
|
||||
|
||||
$declared_at = Specio::DeclaredAt->new_from_caller(1)
|
||||
unless defined $declared_at;
|
||||
|
||||
my %p = (
|
||||
parent => $self,
|
||||
parameter => $parameter,
|
||||
declared_at => $declared_at,
|
||||
);
|
||||
|
||||
if ( $self->_has_parameterized_constraint_generator ) {
|
||||
$p{constraint}
|
||||
= $self->_parameterized_constraint_generator->($parameter);
|
||||
}
|
||||
else {
|
||||
confess
|
||||
'The "of" parameter passed to ->parameterize must be an inlinable constraint if the parameterizable type has an inline_generator'
|
||||
unless $parameter->can_be_inlined;
|
||||
|
||||
my $ig = $self->_parameterized_inline_generator;
|
||||
$p{inline_generator} = sub { $ig->( shift, $parameter, @_ ) };
|
||||
}
|
||||
|
||||
return Specio::Constraint::Parameterized->new(%p);
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class which represents parameterizable constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Parameterizable - A class which represents parameterizable constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $arrayref = t('ArrayRef');
|
||||
|
||||
my $arrayref_of_int = $arrayref->parameterize( of => t('Int') );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class implements the API for parameterizable types like C<ArrayRef> and
|
||||
C<Maybe>.
|
||||
|
||||
=for Pod::Coverage BUILD
|
||||
|
||||
=head1 API
|
||||
|
||||
This class implements the same API as L<Specio::Constraint::Simple>, with a few
|
||||
additions.
|
||||
|
||||
=head2 Specio::Constraint::Parameterizable->new(...)
|
||||
|
||||
This class's constructor accepts two additional parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * parameterized_constraint_generator
|
||||
|
||||
This is a subroutine that generates a new constraint subroutine when the type
|
||||
is parameterized.
|
||||
|
||||
It will be called as a method on the type and will be passed a single
|
||||
argument, the type object for the type parameter.
|
||||
|
||||
This parameter is mutually exclusive with the
|
||||
C<parameterized_inline_generator> parameter.
|
||||
|
||||
=item * parameterized_inline_generator
|
||||
|
||||
This is a subroutine that generates a new inline generator subroutine when the
|
||||
type is parameterized.
|
||||
|
||||
It will be called as a method on the L<Specio::Constraint::Parameterized>
|
||||
object when that object needs to generate an inline constraint. It will
|
||||
receive the type parameter as the first argument and the variable name as a
|
||||
string as the second.
|
||||
|
||||
This probably seems fairly confusing, so looking at the examples in the
|
||||
L<Specio::Library::Builtins> code may be helpful.
|
||||
|
||||
This parameter is mutually exclusive with the
|
||||
C<parameterized_constraint_generator> parameter.
|
||||
|
||||
=back
|
||||
|
||||
=head2 $type->parameterize(...)
|
||||
|
||||
This method takes two arguments. The C<of> argument should be an object which
|
||||
does the L<Specio::Constraint::Role::Interface> role, and is required.
|
||||
|
||||
The other argument, C<declared_at>, is optional. If it is not given, then a
|
||||
new L<Specio::DeclaredAt> object is creating using a call stack depth of 1.
|
||||
|
||||
This method returns a new L<Specio::Constraint::Parameterized> object.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
156
database/perl/vendor/lib/Specio/Constraint/Parameterized.pm
vendored
Normal file
156
database/perl/vendor/lib/Specio/Constraint/Parameterized.pm
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
package Specio::Constraint::Parameterized;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Specio::OO;
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
$attrs->{parent}{isa} = 'Specio::Constraint::Parameterizable';
|
||||
$attrs->{parent}{required} = 1;
|
||||
|
||||
delete $attrs->{name}{predicate};
|
||||
$attrs->{name}{lazy} = 1;
|
||||
$attrs->{name}{builder} = '_build_name';
|
||||
|
||||
$attrs->{parameter} = {
|
||||
does => 'Specio::Constraint::Role::Interface',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub _has_name {
|
||||
my $self = shift;
|
||||
return defined $self->name;
|
||||
}
|
||||
|
||||
sub _build_name {
|
||||
my $self = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
return unless $self->parent->_has_name && $self->parameter->_has_name;
|
||||
return $self->parent->name . '[' . $self->parameter->name . ']';
|
||||
}
|
||||
|
||||
sub can_be_inlined {
|
||||
my $self = shift;
|
||||
|
||||
return $self->_has_inline_generator
|
||||
&& $self->parameter->can_be_inlined;
|
||||
}
|
||||
|
||||
# Moose compatibility methods - these exist as a temporary hack to make Specio
|
||||
# work with Moose.
|
||||
|
||||
sub type_parameter {
|
||||
shift->parameter;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class which represents parameterized constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Parameterized - A class which represents parameterized constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $arrayref = t('ArrayRef');
|
||||
|
||||
my $arrayref_of_int = $arrayref->parameterize( of => t('Int') );
|
||||
|
||||
my $parent = $arrayref_of_int->parent; # returns ArrayRef
|
||||
my $parameter = $arrayref_of_int->parameter; # returns Int
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class implements the API for parameterized types.
|
||||
|
||||
=for Pod::Coverage can_be_inlined type_parameter
|
||||
|
||||
=head1 API
|
||||
|
||||
This class implements the same API as L<Specio::Constraint::Simple>, with a few
|
||||
additions.
|
||||
|
||||
=head2 Specio::Constraint::Parameterized->new(...)
|
||||
|
||||
This class's constructor accepts two additional parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * parent
|
||||
|
||||
This should be the L<Specio::Constraint::Parameterizable> object from which this
|
||||
object was created.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * parameter
|
||||
|
||||
This is the type parameter for the parameterized type. This must be an object
|
||||
which does the L<Specio::Constraint::Role::Interface> role.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=back
|
||||
|
||||
=head2 $type->parameter
|
||||
|
||||
Returns the type that was passed to the constructor.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
178
database/perl/vendor/lib/Specio/Constraint/Role/CanType.pm
vendored
Normal file
178
database/perl/vendor/lib/Specio/Constraint/Role/CanType.pm
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
package Specio::Constraint::Role::CanType;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Role::Tiny;
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( parent _inline_generator )) {
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
$attrs->{methods} = {
|
||||
isa => 'ArrayRef',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _wrap_message_generator {
|
||||
my $self = shift;
|
||||
my $generator = shift;
|
||||
|
||||
my $type = ( split /::/, blessed $self)[-1];
|
||||
my @methods = @{ $self->methods };
|
||||
my $all_word_list = _word_list(@methods);
|
||||
my $allow_classes = $self->_allow_classes;
|
||||
|
||||
unless ( defined $generator ) {
|
||||
$generator = sub {
|
||||
shift;
|
||||
my $value = shift;
|
||||
|
||||
return
|
||||
"An undef will never pass an $type check (wants $all_word_list)"
|
||||
unless defined $value;
|
||||
|
||||
my $class = blessed $value;
|
||||
if ( !defined $class ) {
|
||||
|
||||
# If we got here we know that blessed returned undef, so if
|
||||
# it's a ref then it must not be blessed.
|
||||
if ( ref $value ) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"An unblessed reference ($dump) will never pass an $type check (wants $all_word_list)";
|
||||
}
|
||||
|
||||
# If it's defined and not an unblessed ref it must be a
|
||||
# string. If we allow classes (vs just objects) then it might
|
||||
# be a valid class name. But an empty string is never a valid
|
||||
# class name. We cannot call q{}->can.
|
||||
return
|
||||
"An empty string will never pass an $type check (wants $all_word_list)"
|
||||
unless length $value;
|
||||
|
||||
if ( ref \$value eq 'GLOB' ) {
|
||||
return
|
||||
"A glob will never pass an $type check (wants $all_word_list)";
|
||||
}
|
||||
|
||||
if (
|
||||
$value =~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
) {
|
||||
return
|
||||
"A number ($value) will never pass an $type check (wants $all_word_list)";
|
||||
}
|
||||
|
||||
$class = $value if $allow_classes;
|
||||
|
||||
# At this point we either have undef or a non-empty string in
|
||||
# $class.
|
||||
unless ( defined $class ) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"A plain scalar ($dump) will never pass an $type check (wants $all_word_list)";
|
||||
}
|
||||
}
|
||||
|
||||
my @missing = grep { !$value->can($_) } @methods;
|
||||
|
||||
my $noun = @missing == 1 ? 'method' : 'methods';
|
||||
my $list = _word_list( map {qq['$_']} @missing );
|
||||
|
||||
return "The $class class is missing the $list $noun";
|
||||
};
|
||||
}
|
||||
|
||||
return sub { $generator->( undef, @_ ) };
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _word_list {
|
||||
my @items = sort { $a cmp $b } @_;
|
||||
|
||||
return $items[0] if @items == 1;
|
||||
return join ' and ', @items if @items == 2;
|
||||
|
||||
my $final = pop @items;
|
||||
my $list = join ', ', @items;
|
||||
$list .= ', and ' . $final;
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Provides a common implementation for Specio::Constraint::AnyCan and Specio::Constraint::ObjectCan
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Role::CanType - Provides a common implementation for Specio::Constraint::AnyCan and Specio::Constraint::ObjectCan
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
See L<Specio::Constraint::AnyCan> and L<Specio::Constraint::ObjectCan> for details.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
144
database/perl/vendor/lib/Specio/Constraint/Role/DoesType.pm
vendored
Normal file
144
database/perl/vendor/lib/Specio/Constraint/Role/DoesType.pm
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
package Specio::Constraint::Role::DoesType;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny;
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( parent _inline_generator )) {
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
$attrs->{role} = {
|
||||
isa => 'Str',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _wrap_message_generator {
|
||||
my $self = shift;
|
||||
my $generator = shift;
|
||||
|
||||
my $type = ( split /::/, blessed $self)[-1];
|
||||
my $role = $self->role;
|
||||
my $allow_classes = $self->_allow_classes;
|
||||
|
||||
unless ( defined $generator ) {
|
||||
$generator = sub {
|
||||
shift;
|
||||
my $value = shift;
|
||||
|
||||
return "An undef will never pass an $type check (wants $role)"
|
||||
unless defined $value;
|
||||
|
||||
if ( ref $value && !blessed $value ) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"An unblessed reference ($dump) will never pass an $type check (wants $role)";
|
||||
}
|
||||
|
||||
if ( !blessed $value) {
|
||||
return
|
||||
"An empty string will never pass an $type check (wants $role)"
|
||||
unless length $value;
|
||||
|
||||
if (
|
||||
$value =~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
) {
|
||||
return
|
||||
"A number ($value) will never pass an $type check (wants $role)";
|
||||
}
|
||||
|
||||
if ( !$allow_classes ) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"A plain scalar ($dump) will never pass an $type check (wants $role)";
|
||||
}
|
||||
}
|
||||
|
||||
my $got = blessed $value;
|
||||
$got ||= $value;
|
||||
|
||||
return "The $got class does not consume the $role role";
|
||||
};
|
||||
}
|
||||
|
||||
return sub { $generator->( undef, @_ ) };
|
||||
}
|
||||
## use critic
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Provides a common implementation for Specio::Constraint::AnyDoes and Specio::Constraint::ObjectDoes
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Role::DoesType - Provides a common implementation for Specio::Constraint::AnyDoes and Specio::Constraint::ObjectDoes
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
See L<Specio::Constraint::AnyDoes> and L<Specio::Constraint::ObjectDoes> for
|
||||
details.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
667
database/perl/vendor/lib/Specio/Constraint/Role/Interface.pm
vendored
Normal file
667
database/perl/vendor/lib/Specio/Constraint/Role/Interface.pm
vendored
Normal file
@@ -0,0 +1,667 @@
|
||||
package Specio::Constraint::Role::Interface;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use Eval::Closure qw( eval_closure );
|
||||
use List::Util 1.33 qw( all any first );
|
||||
use Specio::Exception;
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
use Specio::TypeChecks qw( is_CodeRef );
|
||||
|
||||
use Role::Tiny 1.003003;
|
||||
|
||||
use Specio::Role::Inlinable;
|
||||
with 'Specio::Role::Inlinable';
|
||||
|
||||
use overload(
|
||||
q{""} => sub { $_[0] },
|
||||
'&{}' => '_subification',
|
||||
'bool' => sub {1},
|
||||
);
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $role_attrs = Specio::Role::Inlinable::_attrs();
|
||||
## use critic
|
||||
|
||||
my $attrs = {
|
||||
%{$role_attrs},
|
||||
name => {
|
||||
isa => 'Str',
|
||||
predicate => '_has_name',
|
||||
},
|
||||
parent => {
|
||||
does => 'Specio::Constraint::Role::Interface',
|
||||
predicate => '_has_parent',
|
||||
},
|
||||
_constraint => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'constraint',
|
||||
predicate => '_has_constraint',
|
||||
},
|
||||
_optimized_constraint => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_optimized_constraint',
|
||||
},
|
||||
_ancestors => {
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_ancestors',
|
||||
},
|
||||
_message_generator => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => undef,
|
||||
},
|
||||
_coercions => {
|
||||
builder => '_build_coercions',
|
||||
clone => '_clone_coercions',
|
||||
},
|
||||
_subification => {
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_subification',
|
||||
},
|
||||
|
||||
# Because types are cloned on import, we can't directly compare type
|
||||
# objects. Because type names can be reused between packages (no global
|
||||
# registry) we can't compare types based on name either.
|
||||
_signature => {
|
||||
isa => 'Str',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_signature',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
my $NullConstraint = sub {1};
|
||||
|
||||
# See Specio::OO to see how this is used.
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _Specio_Constraint_Role_Interface_BUILD {
|
||||
my $self = shift;
|
||||
my $p = shift;
|
||||
|
||||
unless ( $self->_has_constraint || $self->_has_inline_generator ) {
|
||||
$self->{_constraint} = $NullConstraint;
|
||||
}
|
||||
|
||||
die
|
||||
'A type constraint should have either a constraint or inline_generator parameter, not both'
|
||||
if $self->_has_constraint && $self->_has_inline_generator;
|
||||
|
||||
$self->{_message_generator}
|
||||
= $self->_wrap_message_generator( $p->{message_generator} );
|
||||
|
||||
return;
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _wrap_message_generator {
|
||||
my $self = shift;
|
||||
my $generator = shift;
|
||||
|
||||
unless ( defined $generator ) {
|
||||
$generator = sub {
|
||||
my $description = shift;
|
||||
my $value = shift;
|
||||
|
||||
return "Validation failed for $description with value "
|
||||
. partial_dump($value);
|
||||
};
|
||||
}
|
||||
|
||||
my $d = $self->description;
|
||||
|
||||
return sub { $generator->( $d, @_ ) };
|
||||
}
|
||||
|
||||
sub coercions { values %{ $_[0]->{_coercions} } }
|
||||
sub coercion_from_type { $_[0]->{_coercions}{ $_[1] } }
|
||||
sub _has_coercion_from_type { exists $_[0]->{_coercions}{ $_[1] } }
|
||||
sub _add_coercion { $_[0]->{_coercions}{ $_[1] } = $_[2] }
|
||||
sub has_coercions { scalar keys %{ $_[0]->{_coercions} } }
|
||||
|
||||
sub validate_or_die {
|
||||
my $self = shift;
|
||||
my $value = shift;
|
||||
|
||||
return if $self->value_is_valid($value);
|
||||
|
||||
Specio::Exception->throw(
|
||||
message => $self->_message_generator->($value),
|
||||
type => $self,
|
||||
value => $value,
|
||||
);
|
||||
}
|
||||
|
||||
sub value_is_valid {
|
||||
my $self = shift;
|
||||
my $value = shift;
|
||||
|
||||
return $self->_optimized_constraint->($value);
|
||||
}
|
||||
|
||||
sub _ancestors_and_self {
|
||||
my $self = shift;
|
||||
|
||||
return ( ( reverse @{ $self->_ancestors } ), $self );
|
||||
}
|
||||
|
||||
sub is_a_type_of {
|
||||
my $self = shift;
|
||||
my $type = shift;
|
||||
|
||||
return any { $_->_signature eq $type->_signature }
|
||||
$self->_ancestors_and_self;
|
||||
}
|
||||
|
||||
sub is_same_type_as {
|
||||
my $self = shift;
|
||||
my $type = shift;
|
||||
|
||||
return $self->_signature eq $type->_signature;
|
||||
}
|
||||
|
||||
sub is_anon {
|
||||
my $self = shift;
|
||||
|
||||
return !$self->_has_name;
|
||||
}
|
||||
|
||||
sub has_real_constraint {
|
||||
my $self = shift;
|
||||
|
||||
return ( $self->_has_constraint && $self->_constraint ne $NullConstraint )
|
||||
|| $self->_has_inline_generator;
|
||||
}
|
||||
|
||||
sub can_be_inlined {
|
||||
my $self = shift;
|
||||
|
||||
return 1 if $self->_has_inline_generator;
|
||||
return 0
|
||||
if $self->_has_constraint && $self->_constraint ne $NullConstraint;
|
||||
|
||||
# If this type is an empty subtype of an inlinable parent, then we can
|
||||
# inline this type as well.
|
||||
return 1 if $self->_has_parent && $self->parent->can_be_inlined;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _build_generated_inline_sub {
|
||||
my $self = shift;
|
||||
|
||||
my $type = $self->_self_or_first_inlinable_ancestor;
|
||||
|
||||
my $source
|
||||
= 'sub { ' . $type->_inline_generator->( $type, '$_[0]' ) . '}';
|
||||
|
||||
return eval_closure(
|
||||
source => $source,
|
||||
environment => $type->inline_environment,
|
||||
description => 'inlined sub for ' . $self->description,
|
||||
);
|
||||
}
|
||||
|
||||
sub _self_or_first_inlinable_ancestor {
|
||||
my $self = shift;
|
||||
|
||||
my $type = first { $_->_has_inline_generator }
|
||||
reverse $self->_ancestors_and_self;
|
||||
|
||||
# This should never happen because ->can_be_inlined should always be
|
||||
# checked before this builder is called.
|
||||
die 'Cannot generate an inline sub' unless $type;
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
sub _build_optimized_constraint {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->can_be_inlined ) {
|
||||
return $self->_generated_inline_sub;
|
||||
}
|
||||
else {
|
||||
return $self->_constraint_with_parents;
|
||||
}
|
||||
}
|
||||
|
||||
sub _constraint_with_parents {
|
||||
my $self = shift;
|
||||
|
||||
my @constraints;
|
||||
for my $type ( $self->_ancestors_and_self ) {
|
||||
next unless $type->has_real_constraint;
|
||||
|
||||
# If a type can be inlined, we can use that and discard all of the
|
||||
# ancestors we've seen so far, since we can assume that the inlined
|
||||
# constraint does all of the ancestor checks in addition to its own.
|
||||
if ( $type->can_be_inlined ) {
|
||||
@constraints = $type->_generated_inline_sub;
|
||||
}
|
||||
else {
|
||||
push @constraints, $type->_constraint;
|
||||
}
|
||||
}
|
||||
|
||||
return $NullConstraint unless @constraints;
|
||||
|
||||
return sub {
|
||||
all { $_->( $_[0] ) } @constraints;
|
||||
};
|
||||
}
|
||||
|
||||
# This is only used for identifying from types as part of coercions, but I
|
||||
# want to leave open the possibility of using something other than
|
||||
# _description in the future.
|
||||
sub id {
|
||||
my $self = shift;
|
||||
|
||||
return $self->description;
|
||||
}
|
||||
|
||||
sub add_coercion {
|
||||
my $self = shift;
|
||||
my $coercion = shift;
|
||||
|
||||
my $from_id = $coercion->from->id;
|
||||
|
||||
confess "Cannot add two coercions fom the same type: $from_id"
|
||||
if $self->_has_coercion_from_type($from_id);
|
||||
|
||||
$self->_add_coercion( $from_id => $coercion );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub has_coercion_from_type {
|
||||
my $self = shift;
|
||||
my $type = shift;
|
||||
|
||||
return $self->_has_coercion_from_type( $type->id );
|
||||
}
|
||||
|
||||
sub coerce_value {
|
||||
my $self = shift;
|
||||
my $value = shift;
|
||||
|
||||
for my $coercion ( $self->coercions ) {
|
||||
next unless $coercion->from->value_is_valid($value);
|
||||
|
||||
return $coercion->coerce($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub can_inline_coercion {
|
||||
my $self = shift;
|
||||
|
||||
return all { $_->can_be_inlined } $self->coercions;
|
||||
}
|
||||
|
||||
sub can_inline_coercion_and_check {
|
||||
my $self = shift;
|
||||
|
||||
return all { $_->can_be_inlined } $self, $self->coercions;
|
||||
}
|
||||
|
||||
sub inline_coercion {
|
||||
my $self = shift;
|
||||
my $arg_name = shift;
|
||||
|
||||
die 'Cannot inline coercion'
|
||||
unless $self->can_inline_coercion;
|
||||
|
||||
my $source = 'do { my $value = ' . $arg_name . ';';
|
||||
|
||||
my ( $coerce, $env );
|
||||
( $coerce, $arg_name, $env ) = $self->_inline_coercion($arg_name);
|
||||
$source .= $coerce . $arg_name . '};';
|
||||
|
||||
return ( $source, $env );
|
||||
}
|
||||
|
||||
sub inline_coercion_and_check {
|
||||
my $self = shift;
|
||||
my $arg_name = shift;
|
||||
|
||||
die 'Cannot inline coercion and check'
|
||||
unless $self->can_inline_coercion_and_check;
|
||||
|
||||
my $source = 'do { my $value = ' . $arg_name . ';';
|
||||
|
||||
my ( $coerce, $env );
|
||||
( $coerce, $arg_name, $env ) = $self->_inline_coercion($arg_name);
|
||||
my ( $assert, $assert_env ) = $self->inline_assert($arg_name);
|
||||
|
||||
$source .= $coerce;
|
||||
$source .= $assert;
|
||||
$source .= $arg_name . '};';
|
||||
|
||||
return ( $source, { %{$env}, %{$assert_env} } );
|
||||
}
|
||||
|
||||
sub _inline_coercion {
|
||||
my $self = shift;
|
||||
my $arg_name = shift;
|
||||
|
||||
return ( q{}, $arg_name, {} ) unless $self->has_coercions;
|
||||
|
||||
my %env;
|
||||
|
||||
$arg_name = '$value';
|
||||
my $source = $arg_name . ' = ';
|
||||
for my $coercion ( $self->coercions ) {
|
||||
$source
|
||||
.= '('
|
||||
. $coercion->from->inline_check($arg_name) . ') ? ('
|
||||
. $coercion->inline_coercion($arg_name) . ') : ';
|
||||
|
||||
%env = (
|
||||
%env,
|
||||
%{ $coercion->inline_environment },
|
||||
%{ $coercion->from->inline_environment },
|
||||
);
|
||||
}
|
||||
$source .= $arg_name . ';';
|
||||
|
||||
return ( $source, $arg_name, \%env );
|
||||
}
|
||||
|
||||
{
|
||||
my $counter = 1;
|
||||
|
||||
sub inline_assert {
|
||||
my $self = shift;
|
||||
|
||||
my $type_var_name = '$_Specio_Constraint_Interface_type' . $counter;
|
||||
my $message_generator_var_name
|
||||
= '$_Specio_Constraint_Interface_message_generator' . $counter;
|
||||
my %env = (
|
||||
$type_var_name => \$self,
|
||||
$message_generator_var_name => \( $self->_message_generator ),
|
||||
%{ $self->inline_environment },
|
||||
);
|
||||
|
||||
my $source = $self->inline_check( $_[0] );
|
||||
$source .= ' or ';
|
||||
$source .= $self->_inline_throw_exception(
|
||||
$_[0],
|
||||
$message_generator_var_name,
|
||||
$type_var_name
|
||||
);
|
||||
$source .= ';';
|
||||
|
||||
$counter++;
|
||||
|
||||
return ( $source, \%env );
|
||||
}
|
||||
}
|
||||
|
||||
sub inline_check {
|
||||
my $self = shift;
|
||||
|
||||
die 'Cannot inline' unless $self->can_be_inlined;
|
||||
|
||||
my $type = $self->_self_or_first_inlinable_ancestor;
|
||||
return $type->_inline_generator->( $type, @_ );
|
||||
}
|
||||
|
||||
# For some idiotic reason I called $type->_subify directly in Code::TidyAll so
|
||||
# I'll leave this in here for now.
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _subify { $_[0]->_subification }
|
||||
## use critic
|
||||
|
||||
sub _build_subification {
|
||||
my $self = shift;
|
||||
|
||||
if ( defined &Sub::Quote::quote_sub && $self->can_be_inlined ) {
|
||||
return Sub::Quote::quote_sub( $self->inline_assert('$_[0]') );
|
||||
}
|
||||
else {
|
||||
return sub { $self->validate_or_die( $_[0] ) };
|
||||
}
|
||||
}
|
||||
|
||||
sub _inline_throw_exception {
|
||||
my $self = shift;
|
||||
my $value_var = shift;
|
||||
my $message_generator_var_name = shift;
|
||||
my $type_var_name = shift;
|
||||
|
||||
#<<<
|
||||
return 'Specio::Exception->throw( '
|
||||
. ' message => ' . $message_generator_var_name . '->(' . $value_var . '),'
|
||||
. ' type => ' . $type_var_name . ','
|
||||
. ' value => ' . $value_var . ' )';
|
||||
#>>>
|
||||
}
|
||||
|
||||
# This exists for the benefit of Moo
|
||||
sub coercion_sub {
|
||||
my $self = shift;
|
||||
|
||||
if ( defined &Sub::Quote::quote_sub
|
||||
&& all { $_->can_be_inlined } $self->coercions ) {
|
||||
|
||||
my $inline = q{};
|
||||
my %env;
|
||||
|
||||
for my $coercion ( $self->coercions ) {
|
||||
$inline .= sprintf(
|
||||
'$_[0] = %s if %s;' . "\n",
|
||||
$coercion->inline_coercion('$_[0]'),
|
||||
$coercion->from->inline_check('$_[0]')
|
||||
);
|
||||
|
||||
%env = (
|
||||
%env,
|
||||
%{ $coercion->inline_environment },
|
||||
%{ $coercion->from->inline_environment },
|
||||
);
|
||||
}
|
||||
|
||||
$inline .= sprintf( "%s;\n", '$_[0]' );
|
||||
|
||||
return Sub::Quote::quote_sub( $inline, \%env );
|
||||
}
|
||||
else {
|
||||
return sub { $self->coerce_value(shift) };
|
||||
}
|
||||
}
|
||||
|
||||
sub _build_ancestors {
|
||||
my $self = shift;
|
||||
|
||||
my @parents;
|
||||
|
||||
my $type = $self;
|
||||
while ( $type = $type->parent ) {
|
||||
push @parents, $type;
|
||||
}
|
||||
|
||||
return \@parents;
|
||||
|
||||
}
|
||||
|
||||
sub _build_description {
|
||||
my $self = shift;
|
||||
|
||||
my $desc
|
||||
= $self->is_anon ? 'anonymous type' : 'type named ' . $self->name;
|
||||
|
||||
$desc .= q{ } . $self->declared_at->description;
|
||||
|
||||
return $desc;
|
||||
}
|
||||
|
||||
sub _build_coercions { {} }
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _clone_coercions {
|
||||
my $self = shift;
|
||||
|
||||
my $coercions = $self->_coercions;
|
||||
my %clones;
|
||||
|
||||
for my $name ( keys %{$coercions} ) {
|
||||
my $coercion = $coercions->{$name};
|
||||
$clones{$name} = $coercion->clone_with_new_to($self);
|
||||
}
|
||||
|
||||
return \%clones;
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _build_signature {
|
||||
my $self = shift;
|
||||
|
||||
# This assumes that when a type is cloned, the underlying constraint or
|
||||
# generator sub is copied by _reference_, so it has the same memory
|
||||
# address and stringifies to the same value. XXX - will this break under
|
||||
# threads?
|
||||
return join "\n",
|
||||
( $self->_has_parent ? $self->parent->_signature : () ),
|
||||
(
|
||||
defined $self->_constraint
|
||||
? $self->_constraint
|
||||
: $self->_inline_generator
|
||||
);
|
||||
}
|
||||
|
||||
# Moose compatibility methods - these exist as a temporary hack to make Specio
|
||||
# work with Moose.
|
||||
|
||||
sub has_coercion {
|
||||
shift->has_coercions;
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _inline_check {
|
||||
shift->inline_check(@_);
|
||||
}
|
||||
|
||||
sub _compiled_type_constraint {
|
||||
shift->_optimized_constraint;
|
||||
}
|
||||
## use critic;
|
||||
|
||||
# This class implements the methods that Moose expects from coercions as well.
|
||||
sub coercion {
|
||||
return shift;
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _compiled_type_coercion {
|
||||
my $self = shift;
|
||||
|
||||
return sub {
|
||||
return $self->coerce_value(shift);
|
||||
};
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub has_message {
|
||||
1;
|
||||
}
|
||||
|
||||
sub message {
|
||||
shift->_message_generator;
|
||||
}
|
||||
|
||||
sub get_message {
|
||||
my $self = shift;
|
||||
my $value = shift;
|
||||
|
||||
return $self->_message_generator->( $self, $value );
|
||||
}
|
||||
|
||||
sub check {
|
||||
shift->value_is_valid(@_);
|
||||
}
|
||||
|
||||
sub coerce {
|
||||
shift->coerce_value(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: The interface all type constraints should provide
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Role::Interface - The interface all type constraints should provide
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This role defines the interface that all type constraints must provide, and
|
||||
provides most (or all) of the implementation. The L<Specio::Constraint::Simple>
|
||||
class simply consumes this role and provides no additional code. Other
|
||||
constraint classes add features or override some of this role's functionality.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 API
|
||||
|
||||
See the L<Specio::Constraint::Simple> documentation for details. See the
|
||||
internals of various constraint classes to see how this role can be overridden
|
||||
or expanded upon.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This role does the L<Specio::Role::Inlinable> role.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
144
database/perl/vendor/lib/Specio/Constraint/Role/IsaType.pm
vendored
Normal file
144
database/perl/vendor/lib/Specio/Constraint/Role/IsaType.pm
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
package Specio::Constraint::Role::IsaType;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Role::Tiny;
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( parent _inline_generator )) {
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
$attrs->{class} = {
|
||||
isa => 'ClassName',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _wrap_message_generator {
|
||||
my $self = shift;
|
||||
my $generator = shift;
|
||||
|
||||
my $type = ( split /::/, blessed $self)[-1];
|
||||
my $class = $self->class;
|
||||
my $allow_classes = $self->_allow_classes;
|
||||
|
||||
unless ( defined $generator ) {
|
||||
$generator = sub {
|
||||
shift;
|
||||
my $value = shift;
|
||||
|
||||
return "An undef will never pass an $type check (wants $class)"
|
||||
unless defined $value;
|
||||
|
||||
if ( ref $value && !blessed $value) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"An unblessed reference ($dump) will never pass an $type check (wants $class)";
|
||||
}
|
||||
|
||||
if ( !blessed $value) {
|
||||
return
|
||||
"An empty string will never pass an $type check (wants $class)"
|
||||
unless length $value;
|
||||
|
||||
if (
|
||||
$value =~ /\A
|
||||
\s*
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\s*
|
||||
\z/xs
|
||||
) {
|
||||
return
|
||||
"A number ($value) will never pass an $type check (wants $class)";
|
||||
}
|
||||
|
||||
if ( !$allow_classes ) {
|
||||
my $dump = partial_dump($value);
|
||||
return
|
||||
"A plain scalar ($dump) will never pass an $type check (wants $class)";
|
||||
}
|
||||
}
|
||||
|
||||
my $got = blessed $value;
|
||||
$got ||= $value;
|
||||
|
||||
return "The $got class is not a subclass of the $class class";
|
||||
};
|
||||
}
|
||||
|
||||
return sub { $generator->( undef, @_ ) };
|
||||
}
|
||||
## use critic
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Provides a common implementation for Specio::Constraint::AnyIsa and Specio::Constraint::ObjectIsa
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Role::IsaType - Provides a common implementation for Specio::Constraint::AnyIsa and Specio::Constraint::ObjectIsa
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
See L<Specio::Constraint::AnyIsa> and L<Specio::Constraint::ObjectIsa> for details.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
351
database/perl/vendor/lib/Specio/Constraint/Simple.pm
vendored
Normal file
351
database/perl/vendor/lib/Specio/Constraint/Simple.pm
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
package Specio::Constraint::Simple;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Role::Tiny::With;
|
||||
use Specio::OO;
|
||||
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Class for simple (non-parameterized or specialized) types
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Simple - Class for simple (non-parameterized or specialized) types
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $str = t('Str');
|
||||
|
||||
print $str->name; # Str
|
||||
|
||||
my $parent = $str->parent;
|
||||
|
||||
if ( $str->value_is_valid($value) ) { ... }
|
||||
|
||||
$str->validate_or_die($value);
|
||||
|
||||
my $code = $str->inline_coercion_and_check('$_[0]');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class implements simple type constraints, constraints without special
|
||||
properties or parameterization.
|
||||
|
||||
It does not actually contain any real code of its own. The entire
|
||||
implementation is provided by the L<Specio::Constraint::Role::Interface> role,
|
||||
but the primary API for type constraints is documented here.
|
||||
|
||||
All other type constraint classes in this distribution implement this API,
|
||||
except where otherwise noted.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides the following methods.
|
||||
|
||||
=head2 Specio::Constraint::Simple->new(...)
|
||||
|
||||
This creates a new constraint. It accepts the following named parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * name => $name
|
||||
|
||||
This is the type's name. The name is optional, but if provided it must be a
|
||||
string.
|
||||
|
||||
=item * parent => $type
|
||||
|
||||
The type's parent type. This must be an object which does the
|
||||
L<Specio::Constraint::Role::Interface> role.
|
||||
|
||||
This parameter is optional.
|
||||
|
||||
=item * constraint => sub { ... }
|
||||
|
||||
A subroutine reference implementing the constraint. It will be called as a
|
||||
method on the object and passed a single argument, the value to check.
|
||||
|
||||
It should return true or false to indicate whether the value matches the
|
||||
constraint.
|
||||
|
||||
This parameter is mutually exclusive with C<inline_generator>.
|
||||
|
||||
You can also pass this option with the key C<where> in the parameter list.
|
||||
|
||||
=item * inline_generator => sub { ... }
|
||||
|
||||
This should be a subroutine reference which returns a string containing a
|
||||
single term. This code should I<not> end in a semicolon. This code should
|
||||
implement the constraint.
|
||||
|
||||
The generator will be called as a method on the constraint with a single
|
||||
argument. That argument is the name of the variable being coerced, something
|
||||
like C<'$_[0]'> or C<'$var'>.
|
||||
|
||||
The inline generator is expected to include code to implement both the current
|
||||
type and all its parents. Typically, the easiest way to do this is to write a
|
||||
subroutine something like this:
|
||||
|
||||
sub {
|
||||
my $self = shift;
|
||||
my $var = shift;
|
||||
|
||||
return $_[0]->parent->inline_check( $_[1] )
|
||||
. ' and more checking code goes here';
|
||||
}
|
||||
|
||||
This parameter is mutually exclusive with C<constraint>.
|
||||
|
||||
You can also pass this option with the key C<inline> in the parameter list.
|
||||
|
||||
=item * inline_environment => {}
|
||||
|
||||
This should be a hash reference of variable names (with sigils) and values for
|
||||
that variable. The values should be I<references> to the values of the
|
||||
variables.
|
||||
|
||||
This environment will be used when compiling the constraint as part of a
|
||||
subroutine. The named variables will be captured as closures in the generated
|
||||
subroutine, using L<Eval::Closure>.
|
||||
|
||||
It should be very rare to need to set this in the constructor. It's more
|
||||
likely that a special type subclass would need to provide values that it
|
||||
generates internally.
|
||||
|
||||
If you do set this, you are responsible for generating variable names that
|
||||
won't clash with anything else in the inlined code.
|
||||
|
||||
This parameter defaults to an empty hash reference.
|
||||
|
||||
=item * message_generator => sub { ... }
|
||||
|
||||
A subroutine to generate an error message when the type check fails. The
|
||||
default message says something like "Validation failed for type named Int
|
||||
declared in package Specio::Library::Builtins
|
||||
(.../Specio/blib/lib/Specio/Library/Builtins.pm) at line 147 in sub named (eval)
|
||||
with value 1.1".
|
||||
|
||||
You can override this to provide something more specific about the way the
|
||||
type failed.
|
||||
|
||||
The subroutine you provide will be called as a subroutine, I<not as a method>,
|
||||
with two arguments. The first is the description of the type (the bit in the
|
||||
message above that starts with "type named Int ..." and ends with "... in sub
|
||||
named (eval)". This description says what the thing is and where it was
|
||||
defined.
|
||||
|
||||
The second argument is the value that failed the type check, after any
|
||||
coercions that might have been applied.
|
||||
|
||||
You can also pass this option with the key C<message> in the parameter list.
|
||||
|
||||
=item * declared_at => $declared_at
|
||||
|
||||
This parameter must be a L<Specio::DeclaredAt> object.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=back
|
||||
|
||||
It is possible to create a type without a constraint of its own.
|
||||
|
||||
=head2 $type->name
|
||||
|
||||
Returns the name of the type as it was passed the constructor.
|
||||
|
||||
=head2 $type->parent
|
||||
|
||||
Returns the parent type passed to the constructor. If the type has no parent
|
||||
this returns C<undef>.
|
||||
|
||||
=head2 $type->is_anon
|
||||
|
||||
Returns false for named types, true otherwise.
|
||||
|
||||
=head2 $type->is_a_type_of($other_type)
|
||||
|
||||
Given a type object, this returns true if the type this method is called on is
|
||||
a descendant of that type or is that type.
|
||||
|
||||
=head2 $type->is_same_type_as($other_type)
|
||||
|
||||
Given a type object, this returns true if the type this method is called on is
|
||||
the same as that type.
|
||||
|
||||
=head2 $type->coercions
|
||||
|
||||
Returns a list of L<Specio::Coercion> objects which belong to this constraint.
|
||||
|
||||
=head2 $type->coercion_from_type($name)
|
||||
|
||||
Given a type name, this method returns a L<Specio::Coercion> object which
|
||||
coerces from that type, if such a coercion exists.
|
||||
|
||||
=head2 $type->validate_or_die($value)
|
||||
|
||||
This method does nothing if the value is valid. If it is not, it throws a
|
||||
L<Specio::Exception>.
|
||||
|
||||
=head2 $type->value_is_valid($value)
|
||||
|
||||
Returns true or false depending on whether the C<$value> passes the type
|
||||
constraint.
|
||||
|
||||
=head2 $type->has_real_constraint
|
||||
|
||||
This returns true if the type was created with a C<constraint> or
|
||||
C<inline_generator> parameter. This is used internally to skip type checks for
|
||||
types that don't actually implement a constraint.
|
||||
|
||||
=head2 $type->description
|
||||
|
||||
This returns a string describing the type. This includes the type's name and
|
||||
where it was declared, so you end up with something like C<'type named Foo
|
||||
declared in package My::Lib (lib/My/Lib.pm) at line 42'>. If the type is
|
||||
anonymous the name will be "anonymous type".
|
||||
|
||||
=head2 $type->id
|
||||
|
||||
This is a unique id for the type as a string. This is useful if you need to
|
||||
make a hash key based on a type, for example. This should be treated as an
|
||||
essentially arbitrary and opaque string, and could change at any time in the
|
||||
future. If you want something human-readable, use the C<< $type->description
|
||||
>> method.
|
||||
|
||||
=head2 $type->add_coercion($coercion)
|
||||
|
||||
This adds a new L<Specio::Coercion> to the type. If the type already has a
|
||||
coercion from the same type as the new coercion, it will throw an error.
|
||||
|
||||
=head2 $type->has_coercion_from_type($other_type)
|
||||
|
||||
This method returns true if the type can coerce from the other type.
|
||||
|
||||
=head2 $type->coerce_value($value)
|
||||
|
||||
This attempts to coerce a value into a new value that matches the type. It
|
||||
checks all of the type's coercions. If it finds one which has a "from" type
|
||||
that accepts the value, it runs the coercion and returns the new value.
|
||||
|
||||
If it cannot find a matching coercion it returns the original value.
|
||||
|
||||
=head2 $type->inline_coercion_and_check($var)
|
||||
|
||||
Given a variable name, this returns a string of code and an environment hash
|
||||
that implements all of the type's coercions as well as the type check itself.
|
||||
|
||||
This will throw an exception unless both the type and all of its coercions are
|
||||
inlinable.
|
||||
|
||||
The generated code will throw a L<Specio::Exception> if the type constraint
|
||||
fails. If the constraint passes, then the generated code returns the (possibly
|
||||
coerced) value.
|
||||
|
||||
The return value is a two-element list. The first element is the code. The
|
||||
second is a hash reference containing variables which need to be in scope for
|
||||
the code to work. This is intended to be passed to L<Eval::Closure>'s
|
||||
C<eval_closure> subroutine.
|
||||
|
||||
The returned code is a single C<do { }> block without a terminating
|
||||
semicolon.
|
||||
|
||||
=head2 $type->inline_assert($var)
|
||||
|
||||
Given a variable name, this generates code that implements the constraint and
|
||||
throws an exception if the variable does not pass the constraint.
|
||||
|
||||
The return value is a two-element list. The first element is the code. The
|
||||
second is a hash reference containing variables which need to be in scope for
|
||||
the code to work. This is intended to be passed to L<Eval::Closure>'s
|
||||
C<eval_closure> subroutine.
|
||||
|
||||
=head2 $type->inline_check($var)
|
||||
|
||||
Given a variable name, this returns a string of code that implements the
|
||||
constraint. If the type is not inlinable, this method throws an error.
|
||||
|
||||
=head2 $type->inline_coercion($var)
|
||||
|
||||
Given a variable name, this returns a string of code and an environment hash
|
||||
that implements all of the type's coercions. I<It does not check that the
|
||||
resulting value is valid.>
|
||||
|
||||
This will throw an exception unless all of the type's coercions are inlinable.
|
||||
|
||||
The return value is a two-element list. The first element is the code. The
|
||||
second is a hash reference containing variables which need to be in scope for
|
||||
the code to work. This is intended to be passed to L<Eval::Closure>'s
|
||||
C<eval_closure> subroutine.
|
||||
|
||||
The returned code is a single C<do { }> block without a terminating
|
||||
semicolon.
|
||||
|
||||
=head2 $type->inline_environment()
|
||||
|
||||
This returns a hash defining the variables that need to be closed over when
|
||||
inlining the type. The keys are full variable names like C<'$foo'> or
|
||||
C<'@bar'>. The values are I<references> to a variable of the matching type.
|
||||
|
||||
=head2 $type->coercion_sub
|
||||
|
||||
This method returns a sub ref that takes a single argument and applied all
|
||||
relevant coercions to it. This sub ref will use L<Sub::Quote> if all the
|
||||
type's coercions are inlinable.
|
||||
|
||||
This method exists primarily for the benefit of L<Moo>.
|
||||
|
||||
=head1 OVERLOADING
|
||||
|
||||
All constraints overloading subroutine de-referencing for the benefit of
|
||||
L<Moo>. The returned subroutine uses L<Sub::Quote> if the type constraint is
|
||||
inlinable.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This role does the L<Specio::Constraint::Role::Interface> and
|
||||
L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
267
database/perl/vendor/lib/Specio/Constraint/Structurable.pm
vendored
Normal file
267
database/perl/vendor/lib/Specio/Constraint/Structurable.pm
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
package Specio::Constraint::Structurable;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use Role::Tiny::With;
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::DeclaredAt;
|
||||
use Specio::OO;
|
||||
use Specio::Constraint::Structured;
|
||||
use Specio::TypeChecks qw( does_role isa_class );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $role_attrs = Specio::Constraint::Role::Interface::_attrs();
|
||||
## use critic
|
||||
|
||||
my $attrs = {
|
||||
%{$role_attrs},
|
||||
_parameterization_args_builder => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'parameterization_args_builder',
|
||||
required => 1,
|
||||
},
|
||||
_name_builder => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'name_builder',
|
||||
required => 1,
|
||||
},
|
||||
_structured_constraint_generator => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'structured_constraint_generator',
|
||||
predicate => '_has_structured_constraint_generator',
|
||||
},
|
||||
_structured_inline_generator => {
|
||||
isa => 'CodeRef',
|
||||
init_arg => 'structured_inline_generator',
|
||||
predicate => '_has_structured_inline_generator',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->_has_constraint ) {
|
||||
die
|
||||
'A structurable constraint with a constraint parameter must also have a structured_constraint_generator'
|
||||
unless $self->_has_structured_constraint_generator;
|
||||
}
|
||||
|
||||
if ( $self->_has_inline_generator ) {
|
||||
die
|
||||
'A structurable constraint with an inline_generator parameter must also have a structured_inline_generator'
|
||||
unless $self->_has_structured_inline_generator;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub parameterize {
|
||||
my $self = shift;
|
||||
my %args = @_;
|
||||
|
||||
my $declared_at = $args{declared_at};
|
||||
|
||||
if ($declared_at) {
|
||||
isa_class( $declared_at, 'Specio::DeclaredAt' )
|
||||
or confess
|
||||
q{The "declared_at" parameter passed to ->parameterize must be a Specio::DeclaredAt object};
|
||||
}
|
||||
|
||||
my %parameters
|
||||
= $self->_parameterization_args_builder->( $self, $args{of} );
|
||||
|
||||
$declared_at = Specio::DeclaredAt->new_from_caller(1)
|
||||
unless defined $declared_at;
|
||||
|
||||
my %new_p = (
|
||||
parent => $self,
|
||||
parameters => \%parameters,
|
||||
declared_at => $declared_at,
|
||||
name => $self->_name_builder->( $self, \%parameters ),
|
||||
);
|
||||
|
||||
if ( $self->_has_structured_constraint_generator ) {
|
||||
$new_p{constraint}
|
||||
= $self->_structured_constraint_generator->(%parameters);
|
||||
}
|
||||
else {
|
||||
for my $p (
|
||||
grep {
|
||||
blessed($_)
|
||||
&& does_role('Specio::Constraint::Role::Interface')
|
||||
} values %parameters
|
||||
) {
|
||||
|
||||
confess
|
||||
q{Any type objects passed to ->parameterize must be inlinable constraints if the structurable type has an inline_generator}
|
||||
unless $p->can_be_inlined;
|
||||
}
|
||||
|
||||
my $ig = $self->_structured_inline_generator;
|
||||
$new_p{inline_generator}
|
||||
= sub { $ig->( shift, shift, %parameters, @_ ) };
|
||||
}
|
||||
|
||||
return Specio::Constraint::Structured->new(%new_p);
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _name_or_anon {
|
||||
return $_[1]->_has_name ? $_[1]->name : 'ANON';
|
||||
}
|
||||
## use critic
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class which represents structurable constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Structurable - A class which represents structurable constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $tuple = t('Tuple');
|
||||
|
||||
my $tuple_of_str_int = $tuple->parameterize( of => [ t('Str'), t('Int') ] );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class implements the API for structurable types like C<Dict>, C<Map>< and
|
||||
C<Tuple>.
|
||||
|
||||
=for Pod::Coverage BUILD
|
||||
|
||||
=head1 API
|
||||
|
||||
This class implements the same API as L<Specio::Constraint::Simple>, with a few
|
||||
additions.
|
||||
|
||||
=head2 Specio::Constraint::Structurable->new(...)
|
||||
|
||||
This class's constructor accepts two additional parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * parameterization_args_builder
|
||||
|
||||
This is a subroutine that takes the values passed to C<of> and returns a hash
|
||||
of named arguments. These arguments will then be passed into the
|
||||
C<structured_constraint_generator> or C<structured_inline_generator>.
|
||||
|
||||
This should also do argument checking to make sure that the argument passed
|
||||
are valid. For example, the C<Tuple> type turns the arrayref passed to C<of>
|
||||
into a hash, along the way checking that the caller did not do things like
|
||||
interleave optional and required elements or mix optional and slurpy together
|
||||
in the definition.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * name_builder
|
||||
|
||||
This is a subroutine that is called to generate a name for the structured type
|
||||
when it is created. This will be called as a method on the
|
||||
C<Specio::Constraint::Structurable> object. It will be passed the hash of
|
||||
arguments returned by the C<parameterization_args_builder>.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * structured_constraint_generator
|
||||
|
||||
This is a subroutine that generates a new constraint subroutine when the type
|
||||
is structured.
|
||||
|
||||
It will be called as a method on the type and will be passed the hash of
|
||||
arguments returned by the C<parameterization_args_builder>.
|
||||
|
||||
This parameter is mutually exclusive with the C<structured_inline_generator>
|
||||
parameter.
|
||||
|
||||
This parameter or the C<structured_inline_generator> parameter is required.
|
||||
|
||||
=item * structured_inline_generator
|
||||
|
||||
This is a subroutine that generates a new inline generator subroutine when the
|
||||
type is structured.
|
||||
|
||||
It will be called as a method on the L<Specio::Constraint::Structured> object
|
||||
when that object needs to generate an inline constraint. It will receive the
|
||||
type parameter as the first argument and the variable name as a string as the
|
||||
second.
|
||||
|
||||
The remaining arguments will be the parameter hash returned by the
|
||||
C<parameterization_args_builder>.
|
||||
|
||||
This probably seems fairly confusing, so looking at the examples in the
|
||||
L<Specio::Library::Structured::*> code may be helpful.
|
||||
|
||||
This parameter is mutually exclusive with the
|
||||
C<structured_constraint_generator> parameter.
|
||||
|
||||
This parameter or the C<structured_constraint_generator> parameter is
|
||||
required.
|
||||
|
||||
=back
|
||||
|
||||
=head2 $type->parameterize(...)
|
||||
|
||||
This method takes two arguments. The C<of> argument should be an object which
|
||||
does the L<Specio::Constraint::Role::Interface> role, and is required.
|
||||
|
||||
The other argument, C<declared_at>, is optional. If it is not given, then a
|
||||
new L<Specio::DeclaredAt> object is creating using a call stack depth of 1.
|
||||
|
||||
This method returns a new L<Specio::Constraint::Structured> object.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
134
database/perl/vendor/lib/Specio/Constraint/Structured.pm
vendored
Normal file
134
database/perl/vendor/lib/Specio/Constraint/Structured.pm
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
package Specio::Constraint::Structured;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use List::Util qw( all );
|
||||
use Role::Tiny::With;
|
||||
use Specio::OO;
|
||||
use Specio::TypeChecks qw( does_role );
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
$attrs->{parent}{isa} = 'Specio::Constraint::Structurable';
|
||||
$attrs->{parent}{required} = 1;
|
||||
|
||||
$attrs->{parameters} = {
|
||||
isa => 'HashRef',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub can_be_inlined {
|
||||
my $self = shift;
|
||||
return $self->_has_inline_generator;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class which represents structured constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Structured - A class which represents structured constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $tuple = t('Tuple');
|
||||
|
||||
my $tuple_of_str_int = $tuple->parameterize( of => [ t('Str'), t('Int') ] );
|
||||
|
||||
my $parent = $tuple_of_str_int->parent; # returns Tuple
|
||||
my $parameters = $arrayref_of_int->parameters; # returns { of => [ t('Str'), t('Int') ] }
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class implements the API for structured types.
|
||||
|
||||
=for Pod::Coverage can_be_inlined type_parameter
|
||||
|
||||
=head1 API
|
||||
|
||||
This class implements the same API as L<Specio::Constraint::Simple>, with a few
|
||||
additions.
|
||||
|
||||
=head2 Specio::Constraint::Structured->new(...)
|
||||
|
||||
This class's constructor accepts two additional parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * parent
|
||||
|
||||
This should be the L<Specio::Constraint::Structurable> object from which this
|
||||
object was created.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=item * parameters
|
||||
|
||||
This is the hashref of parameters for the structured type. These are the
|
||||
parameters returned by the C<Structurable> type's
|
||||
C<parameterization_args_builder>. The exact form of this hashref will vary for
|
||||
each structured type.
|
||||
|
||||
This parameter is required.
|
||||
|
||||
=back
|
||||
|
||||
=head2 $type->parameters
|
||||
|
||||
Returns the hashref that was passed to the constructor.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
198
database/perl/vendor/lib/Specio/Constraint/Union.pm
vendored
Normal file
198
database/perl/vendor/lib/Specio/Constraint/Union.pm
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
package Specio::Constraint::Union;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use List::Util qw( all any );
|
||||
use Role::Tiny::With;
|
||||
use Specio::OO;
|
||||
use Storable qw( dclone );
|
||||
|
||||
use Specio::Constraint::Role::Interface;
|
||||
with 'Specio::Constraint::Role::Interface';
|
||||
|
||||
{
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my $attrs = dclone( Specio::Constraint::Role::Interface::_attrs() );
|
||||
## use critic
|
||||
|
||||
for my $name (qw( _constraint _inline_generator )) {
|
||||
delete $attrs->{$name}{predicate};
|
||||
$attrs->{$name}{init_arg} = undef;
|
||||
$attrs->{$name}{lazy} = 1;
|
||||
$attrs->{$name}{builder}
|
||||
= $name =~ /^_/ ? '_build' . $name : '_build_' . $name;
|
||||
}
|
||||
|
||||
delete $attrs->{parent};
|
||||
|
||||
delete $attrs->{name}{predicate};
|
||||
$attrs->{name}{lazy} = 1;
|
||||
$attrs->{name}{builder} = '_build_name';
|
||||
|
||||
$attrs->{of} = {
|
||||
isa => 'ArrayRef',
|
||||
required => 1,
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub parent {undef}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _has_parent {0}
|
||||
|
||||
sub _has_name {
|
||||
my $self = shift;
|
||||
return defined $self->name;
|
||||
}
|
||||
|
||||
sub _build_name {
|
||||
my $self = shift;
|
||||
|
||||
return unless all { $_->_has_name } @{ $self->of };
|
||||
return join q{ | }, map { $_->name } @{ $self->of };
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _has_constraint {
|
||||
my $self = shift;
|
||||
|
||||
return !$self->_has_inline_generator;
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _build_constraint {
|
||||
return $_[0]->_optimized_constraint;
|
||||
}
|
||||
|
||||
sub _build_optimized_constraint {
|
||||
my $self = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my @c = map { $_->_optimized_constraint } @{ $self->of };
|
||||
return sub {
|
||||
return any { $_->( $_[0] ) } @c;
|
||||
};
|
||||
}
|
||||
|
||||
sub _has_inline_generator {
|
||||
my $self = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
return all { $_->_has_inline_generator } @{ $self->of };
|
||||
}
|
||||
|
||||
sub _build_inline_generator {
|
||||
my $self = shift;
|
||||
|
||||
return sub {
|
||||
return '(' . (
|
||||
join q{ || },
|
||||
map { sprintf( '( %s )', $_->_inline_generator->( $_, $_[1] ) ) }
|
||||
@{ $self->of }
|
||||
) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
sub _build_inline_environment {
|
||||
my $self = shift;
|
||||
|
||||
my %env;
|
||||
for my $type ( @{ $self->of } ) {
|
||||
%env = (
|
||||
%env,
|
||||
%{ $type->inline_environment },
|
||||
);
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class for union constraints
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Constraint::Union - A class for union constraints
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $type = Specio::Constraint::Untion->new(...);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a specialized type constraint class for unions, which will allow a
|
||||
value which matches any one of several distinct types.
|
||||
|
||||
=for Pod::Coverage parent
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides all of the same methods as L<Specio::Constraint::Simple>,
|
||||
with a few differences:
|
||||
|
||||
=head2 Specio::Constraint::Union->new( ... )
|
||||
|
||||
The C<parent> parameter is ignored if it passed, as it is always C<undef>
|
||||
|
||||
The C<inline_generator> and C<constraint> parameters are also ignored. This
|
||||
class provides its own default inline generator subroutine reference.
|
||||
|
||||
Finally, this class requires an additional parameter, C<of>. This must be an
|
||||
arrayref of type objects.
|
||||
|
||||
=head2 $union->of
|
||||
|
||||
Returns an array reference of the individual types which makes up this union.
|
||||
|
||||
=head1 ROLES
|
||||
|
||||
This class does the L<Specio::Constraint::Role::Interface> and
|
||||
L<Specio::Role::Inlinable> roles.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
696
database/perl/vendor/lib/Specio/Declare.pm
vendored
Normal file
696
database/perl/vendor/lib/Specio/Declare.pm
vendored
Normal file
@@ -0,0 +1,696 @@
|
||||
package Specio::Declare;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent 'Exporter';
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( croak );
|
||||
use Specio::Coercion;
|
||||
use Specio::Constraint::Simple;
|
||||
use Specio::DeclaredAt;
|
||||
use Specio::Helpers qw( install_t_sub _STRINGLIKE );
|
||||
use Specio::Registry qw( internal_types_for_package register );
|
||||
|
||||
## no critic (Modules::ProhibitAutomaticExportation)
|
||||
our @EXPORT = qw(
|
||||
anon
|
||||
any_can_type
|
||||
any_does_type
|
||||
any_isa_type
|
||||
coerce
|
||||
declare
|
||||
enum
|
||||
intersection
|
||||
object_can_type
|
||||
object_does_type
|
||||
object_isa_type
|
||||
union
|
||||
);
|
||||
## use critic
|
||||
|
||||
sub import {
|
||||
my $package = shift;
|
||||
|
||||
# What the heck is this monstrosity?
|
||||
#
|
||||
# Moose version 2.0901 included a first pass at support for Specio. This
|
||||
# was based on Specio c. 0.06 when Specio itself still used
|
||||
# Moose. Unfortunately, recent changes to Specio broke this support and
|
||||
# the Moose core needs updating.
|
||||
#
|
||||
# However, stable versions of Moose have since shipped with a test that
|
||||
# attempts to test itself with Specio 0.07+. This was fine until I wanted
|
||||
# to release a non-TRIAL Specio.
|
||||
#
|
||||
# Once that's out, anyone installing Specio will cause future attempts to
|
||||
# install Moose to fail until Moose includes updated Specio support!
|
||||
# Breaking Moose is not acceptable, thus this mess.
|
||||
#
|
||||
# Note that since Moose 2.1207 this test was renamed and the Specio tests
|
||||
# actually run (and pass). We still need to leave this in here for quite
|
||||
# some time. People should be able to install Specio and then install an
|
||||
# older Moose indefinitely (or at least for a year or two).
|
||||
if ( $ENV{HARNESS_ACTIVE}
|
||||
&& $0 =~ m{t[\\/]type_constraints[\\/]specio\.t$} ) {
|
||||
|
||||
require Test::More;
|
||||
Test::More::plan( skip_all =>
|
||||
'These tests will not pass with this version of Specio' );
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $caller = caller();
|
||||
|
||||
$package->export_to_level( 1, $package, @_ );
|
||||
|
||||
install_t_sub(
|
||||
$caller,
|
||||
internal_types_for_package($caller)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub declare {
|
||||
my $name = _STRINGLIKE(shift)
|
||||
or croak 'You must provide a name for declared types';
|
||||
my %p = @_;
|
||||
|
||||
my $tc = _make_tc( name => $name, %p );
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' );
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub anon {
|
||||
return _make_tc(@_);
|
||||
}
|
||||
|
||||
sub enum {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
require Specio::Constraint::Enum;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
values => $p{values},
|
||||
type_class => 'Specio::Constraint::Enum',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub object_can_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
# This cannot be loaded earlier, since it loads Specio::Library::Builtins,
|
||||
# which in turn wants to load Specio::Declare (the current module).
|
||||
require Specio::Constraint::ObjectCan;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
methods => $p{methods},
|
||||
type_class => 'Specio::Constraint::ObjectCan',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub object_does_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
my $caller = scalar caller();
|
||||
|
||||
# If we are being called repeatedly with a single argument, then we don't
|
||||
# want to blow up because the type has already been declared. This would
|
||||
# force the user to use t() for all calls but the first, making their code
|
||||
# pointlessly more complicated.
|
||||
unless ( keys %p ) {
|
||||
if ( my $exists = internal_types_for_package($caller)->{$name} ) {
|
||||
return $exists;
|
||||
}
|
||||
}
|
||||
|
||||
require Specio::Constraint::ObjectDoes;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
role => ( defined $p{role} ? $p{role} : $name ),
|
||||
type_class => 'Specio::Constraint::ObjectDoes',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub object_isa_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
my $caller = scalar caller();
|
||||
unless ( keys %p ) {
|
||||
if ( my $exists = internal_types_for_package($caller)->{$name} ) {
|
||||
return $exists;
|
||||
}
|
||||
}
|
||||
|
||||
require Specio::Constraint::ObjectIsa;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
class => ( defined $p{class} ? $p{class} : $name ),
|
||||
type_class => 'Specio::Constraint::ObjectIsa',
|
||||
);
|
||||
|
||||
register( $caller, $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub any_can_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
# This cannot be loaded earlier, since it loads Specio::Library::Builtins,
|
||||
# which in turn wants to load Specio::Declare (the current module).
|
||||
require Specio::Constraint::AnyCan;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
methods => $p{methods},
|
||||
type_class => 'Specio::Constraint::AnyCan',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub any_does_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
my $caller = scalar caller();
|
||||
unless ( keys %p ) {
|
||||
if ( my $exists = internal_types_for_package($caller)->{$name} ) {
|
||||
return $exists;
|
||||
}
|
||||
}
|
||||
|
||||
require Specio::Constraint::AnyDoes;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
role => ( defined $p{role} ? $p{role} : $name ),
|
||||
type_class => 'Specio::Constraint::AnyDoes',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub any_isa_type {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
my $caller = scalar caller();
|
||||
unless ( keys %p ) {
|
||||
if ( my $exists = internal_types_for_package($caller)->{$name} ) {
|
||||
return $exists;
|
||||
}
|
||||
}
|
||||
|
||||
require Specio::Constraint::AnyIsa;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
class => ( defined $p{class} ? $p{class} : $name ),
|
||||
type_class => 'Specio::Constraint::AnyIsa',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub intersection {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
require Specio::Constraint::Intersection;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
%p,
|
||||
type_class => 'Specio::Constraint::Intersection',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub union {
|
||||
my $name;
|
||||
$name = shift if @_ % 2;
|
||||
my %p = @_;
|
||||
|
||||
require Specio::Constraint::Union;
|
||||
|
||||
my $tc = _make_tc(
|
||||
( defined $name ? ( name => $name ) : () ),
|
||||
%p,
|
||||
type_class => 'Specio::Constraint::Union',
|
||||
);
|
||||
|
||||
register( scalar caller(), $name, $tc, 'exportable' )
|
||||
if defined $name;
|
||||
|
||||
return $tc;
|
||||
}
|
||||
|
||||
sub _make_tc {
|
||||
my %p = @_;
|
||||
|
||||
my $class = delete $p{type_class} || 'Specio::Constraint::Simple';
|
||||
|
||||
$p{constraint} = delete $p{where} if exists $p{where};
|
||||
$p{message_generator} = delete $p{message} if exists $p{message};
|
||||
$p{inline_generator} = delete $p{inline} if exists $p{inline};
|
||||
|
||||
return $class->new(
|
||||
%p,
|
||||
declared_at => Specio::DeclaredAt->new_from_caller(2),
|
||||
);
|
||||
}
|
||||
|
||||
sub coerce {
|
||||
my $to = shift;
|
||||
my %p = @_;
|
||||
|
||||
$p{coercion} = delete $p{using} if exists $p{using};
|
||||
$p{inline_generator} = delete $p{inline} if exists $p{inline};
|
||||
|
||||
return $to->add_coercion(
|
||||
Specio::Coercion->new(
|
||||
to => $to,
|
||||
%p,
|
||||
declared_at => Specio::DeclaredAt->new_from_caller(1),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Specio declaration subroutines
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Declare - Specio declaration subroutines
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package MyApp::Type::Library;
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins;
|
||||
|
||||
declare(
|
||||
'Foo',
|
||||
parent => t('Str'),
|
||||
where => sub { $_[0] =~ /foo/i },
|
||||
);
|
||||
|
||||
declare(
|
||||
'ArrayRefOfInt',
|
||||
parent => t( 'ArrayRef', of => t('Int') ),
|
||||
);
|
||||
|
||||
my $even = anon(
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
my $type = shift;
|
||||
my $value_var = shift;
|
||||
|
||||
return $value_var . ' % 2 == 0';
|
||||
},
|
||||
);
|
||||
|
||||
coerce(
|
||||
t('ArrayRef'),
|
||||
from => t('Foo'),
|
||||
using => sub { [ $_[0] ] },
|
||||
);
|
||||
|
||||
coerce(
|
||||
$even,
|
||||
from => t('Int'),
|
||||
using => sub { $_[0] % 2 ? $_[0] + 1 : $_[0] },
|
||||
);
|
||||
|
||||
# Specio name is DateTime
|
||||
any_isa_type('DateTime');
|
||||
|
||||
# Specio name is DateTimeObject
|
||||
object_isa_type( 'DateTimeObject', class => 'DateTime' );
|
||||
|
||||
any_can_type(
|
||||
'Duck',
|
||||
methods => [ 'duck_walk', 'quack' ],
|
||||
);
|
||||
|
||||
object_can_type(
|
||||
'DuckObject',
|
||||
methods => [ 'duck_walk', 'quack' ],
|
||||
);
|
||||
|
||||
enum(
|
||||
'Colors',
|
||||
values => [qw( blue green red )],
|
||||
);
|
||||
|
||||
intersection(
|
||||
'HashRefAndArrayRef',
|
||||
of => [ t('HashRef'), t('ArrayRef') ],
|
||||
);
|
||||
|
||||
union(
|
||||
'IntOrArrayRef',
|
||||
of => [ t('Int'), t('ArrayRef') ],
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This package exports a set of type declaration helpers. Importing this package
|
||||
also causes it to create a C<t> subroutine the caller.
|
||||
|
||||
=head1 SUBROUTINES
|
||||
|
||||
This module exports the following subroutines.
|
||||
|
||||
=head2 t('name')
|
||||
|
||||
This subroutine lets you access any types you have declared so far, as well as
|
||||
any types you imported from another type library.
|
||||
|
||||
If you pass an unknown name, it throws an exception.
|
||||
|
||||
=head2 declare(...)
|
||||
|
||||
This subroutine declares a named type. The first argument is the type name,
|
||||
followed by a set of key/value parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * parent => $type
|
||||
|
||||
The parent should be another type object. Specifically, it can be anything
|
||||
which does the L<Specio::Constraint::Role::Interface> role. The parent can be a
|
||||
named or anonymous type.
|
||||
|
||||
=item * where => sub { ... }
|
||||
|
||||
This is a subroutine which defines the type constraint. It will be passed a
|
||||
single argument, the value to check, and it should return true or false to
|
||||
indicate whether or not the value is valid for the type.
|
||||
|
||||
This parameter is mutually exclusive with the C<inline> parameter.
|
||||
|
||||
=item * inline => sub { ... }
|
||||
|
||||
This is a subroutine that is called to generate inline code to validate the
|
||||
type. Inlining can be I<much> faster than simply providing a subroutine with
|
||||
the C<where> parameter, but is often more complicated to get right.
|
||||
|
||||
The inline generator is called as a method on the type with one argument. This
|
||||
argument is a I<string> containing the variable name to use in the generated
|
||||
code. Typically this is something like C<'$_[0]'> or C<'$value'>.
|
||||
|
||||
The inline generator subroutine should return a I<string> of code representing
|
||||
a single term, and it I<should not> be terminated with a semicolon. This
|
||||
allows the inlined code to be safely included in an C<if> statement, for
|
||||
example. You can use C<do { }> blocks and ternaries to get everything into one
|
||||
term. Do not assign to the variable you are testing. This single term should
|
||||
evaluate to true or false.
|
||||
|
||||
The inline generator is expected to include code to implement both the current
|
||||
type and all its parents. Typically, the easiest way to do this is to write a
|
||||
subroutine something like this:
|
||||
|
||||
sub {
|
||||
my $self = shift;
|
||||
my $var = shift;
|
||||
|
||||
return $self->parent->inline_check($var)
|
||||
. ' and more checking code goes here';
|
||||
}
|
||||
|
||||
Or, more concisely:
|
||||
|
||||
sub { $_[0]->parent->inline_check( $_[1] ) . 'more code that checks $_[1]' }
|
||||
|
||||
The C<inline> parameter is mutually exclusive with the C<where> parameter.
|
||||
|
||||
=item * message_generator => sub { ... }
|
||||
|
||||
A subroutine to generate an error message when the type check fails. The
|
||||
default message says something like "Validation failed for type named Int
|
||||
declared in package Specio::Library::Builtins
|
||||
(.../Specio/blib/lib/Specio/Library/Builtins.pm) at line 147 in sub named (eval)
|
||||
with value 1.1".
|
||||
|
||||
You can override this to provide something more specific about the way the
|
||||
type failed.
|
||||
|
||||
The subroutine you provide will be called as a method on the type with two
|
||||
arguments. The first is the description of the type (the bit in the message
|
||||
above that starts with "type named Int ..." and ends with "... in sub named
|
||||
(eval)". This description says what the thing is and where it was defined.
|
||||
|
||||
The second argument is the value that failed the type check, after any
|
||||
coercions that might have been applied.
|
||||
|
||||
=back
|
||||
|
||||
=head2 anon(...)
|
||||
|
||||
This subroutine declares an anonymous type. It is identical to C<declare>
|
||||
except that it expects a list of key/value parameters without a type name as
|
||||
the first parameter.
|
||||
|
||||
=head2 coerce(...)
|
||||
|
||||
This declares a coercion from one type to another. The first argument should
|
||||
be an object which does the L<Specio::Constraint::Role::Interface> role. This
|
||||
can be either a named or anonymous type. This type is the type that the
|
||||
coercion is I<to>.
|
||||
|
||||
The remaining arguments are key/value parameters:
|
||||
|
||||
=over 4
|
||||
|
||||
=item * from => $type
|
||||
|
||||
This must be an object which does the L<Specio::Constraint::Role::Interface>
|
||||
role. This is type that we are coercing I<from>. Again, this can be either a
|
||||
named or anonymous type.
|
||||
|
||||
=item * using => sub { ... }
|
||||
|
||||
This is a subroutine which defines the type coercion. It will be passed a
|
||||
single argument, the value to coerce. It should return a new value of the type
|
||||
this coercion is to.
|
||||
|
||||
This parameter is mutually exclusive with the C<inline> parameter.
|
||||
|
||||
=item * inline => sub { ... }
|
||||
|
||||
This is a subroutine that is called to generate inline code to perform the
|
||||
coercion.
|
||||
|
||||
The inline generator is called as a method on the type with one argument. This
|
||||
argument is a I<string> containing the variable name to use in the generated
|
||||
code. Typically this is something like C<'$_[0]'> or C<'$value'>.
|
||||
|
||||
The inline generator subroutine should return a I<string> of code representing
|
||||
a single term, and it I<should not> be terminated with a semicolon. This
|
||||
allows the inlined code to be safely included in an C<if> statement, for
|
||||
example. You can use C<do { }> blocks and ternaries to get everything into one
|
||||
term. This single term should evaluate to the new value.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DECLARATION HELPERS
|
||||
|
||||
This module also exports some helper subs for declaring certain kinds of types:
|
||||
|
||||
=head2 any_isa_type, object_isa_type
|
||||
|
||||
The C<any_isa_type> helper creates a type which accepts a class name or
|
||||
object of the given class. The C<object_isa_type> helper creates a type
|
||||
which only accepts an object of the given class.
|
||||
|
||||
These subroutines take a type name as the first argument. The remaining
|
||||
arguments are key/value pairs. Currently this is just the C<class> key, which
|
||||
should be a class name. This is the class that the type requires.
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
You can also pass just a single argument, in which case that will be used as
|
||||
both the type's name and the class for the constraint to check.
|
||||
|
||||
=head2 any_does_type, object_does_type
|
||||
|
||||
The C<any_does_type> helper creates a type which accepts a class name or
|
||||
object which does the given role. The C<object_does_type> helper creates a
|
||||
type which only accepts an object which does the given role.
|
||||
|
||||
These subroutines take a type name as the first argument. The remaining
|
||||
arguments are key/value pairs. Currently this is just the C<role> key, which
|
||||
should be a role name. This is the class that the type requires.
|
||||
|
||||
This should just work (I hope) with roles created by L<Moose>, L<Mouse>, and
|
||||
L<Moo> (using L<Role::Tiny>).
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
You can also pass just a single argument, in which case that will be used as
|
||||
both the type's name and the role for the constraint to check.
|
||||
|
||||
=head2 any_can_type, object_can_type
|
||||
|
||||
The C<any_can_type> helper creates a type which accepts a class name or
|
||||
object with the given methods. The C<object_can_type> helper creates a type
|
||||
which only accepts an object with the given methods.
|
||||
|
||||
These subroutines take a type name as the first argument. The remaining
|
||||
arguments are key/value pairs. Currently this is just the C<methods> key,
|
||||
which can be either a string or array reference of strings. These strings are
|
||||
the required methods for the type.
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
=head2 enum
|
||||
|
||||
This creates a type which accepts a string matching a given list of acceptable
|
||||
values.
|
||||
|
||||
The first argument is the type name. The remaining arguments are key/value
|
||||
pairs. Currently this is just the C<values> key. This should an array
|
||||
reference of acceptable string values.
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
=head2 intersection
|
||||
|
||||
This creates a type which is the intersection of two or more other types. A
|
||||
union only accepts values which match all of its underlying types.
|
||||
|
||||
The first argument is the type name. The remaining arguments are key/value
|
||||
pairs. Currently this is just the C<of> key. This should an array
|
||||
reference of types.
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
=head2 union
|
||||
|
||||
This creates a type which is the union of two or more other types. A union
|
||||
accepts any of its underlying types.
|
||||
|
||||
The first argument is the type name. The remaining arguments are key/value
|
||||
pairs. Currently this is just the C<of> key. This should an array
|
||||
reference of types.
|
||||
|
||||
The type name argument can be omitted to create an anonymous type.
|
||||
|
||||
=head1 PARAMETERIZED TYPES
|
||||
|
||||
You can create a parameterized type by calling C<t> with additional
|
||||
parameters, like this:
|
||||
|
||||
my $arrayref_of_int = t( 'ArrayRef', of => t('Int') );
|
||||
|
||||
my $arrayref_of_hashref_of_int = t(
|
||||
'ArrayRef',
|
||||
of => t(
|
||||
'HashRef',
|
||||
of => t('Int'),
|
||||
),
|
||||
);
|
||||
|
||||
The C<t> subroutine assumes that if it receives more than one argument, it
|
||||
should look up the named type and call C<< $type->parameterize(...) >> with
|
||||
the additional arguments.
|
||||
|
||||
If the named type cannot be parameterized, it throws an error.
|
||||
|
||||
You can also call C<< $type->parameterize >> directly if needed. See
|
||||
L<Specio::Constraint::Parameterizable> for details.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
148
database/perl/vendor/lib/Specio/DeclaredAt.pm
vendored
Normal file
148
database/perl/vendor/lib/Specio/DeclaredAt.pm
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
package Specio::DeclaredAt;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Specio::OO;
|
||||
|
||||
{
|
||||
my $attrs = {
|
||||
package => {
|
||||
isa => 'Str',
|
||||
required => 1,
|
||||
},
|
||||
filename => {
|
||||
isa => 'Str',
|
||||
required => 1,
|
||||
},
|
||||
line => {
|
||||
isa => 'Int',
|
||||
required => 1,
|
||||
},
|
||||
subroutine => {
|
||||
isa => 'Str',
|
||||
predicate => 'has_subroutine',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub new_from_caller {
|
||||
my $class = shift;
|
||||
my $depth = shift;
|
||||
|
||||
my %p;
|
||||
@p{qw( package filename line )} = ( caller($depth) )[ 0, 1, 2 ];
|
||||
|
||||
my $sub = ( caller( $depth + 1 ) )[3];
|
||||
$p{subroutine} = $sub if defined $sub;
|
||||
|
||||
return $class->new(%p);
|
||||
}
|
||||
|
||||
sub description {
|
||||
my $self = shift;
|
||||
|
||||
my $package = $self->package;
|
||||
my $filename = $self->filename;
|
||||
my $line = $self->line;
|
||||
|
||||
my $desc = "declared in package $package ($filename) at line $line";
|
||||
if ( $self->has_subroutine ) {
|
||||
$desc .= ' in sub named ' . $self->subroutine;
|
||||
}
|
||||
|
||||
return $desc;
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A class to represent where a type or coercion was declared
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::DeclaredAt - A class to represent where a type or coercion was declared
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $declared = Specio::DeclaredAt->new_from_caller(1);
|
||||
|
||||
print $declared->description;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class provides a thin wrapper around some of the return values from
|
||||
Perl's C<caller> built-in. It's used internally to identify where types and
|
||||
coercions are being declared, which is useful when generating error messages.
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides the following methods.
|
||||
|
||||
=head2 Specio::DeclaredAt->new_from_caller($depth)
|
||||
|
||||
Given a call stack depth, this method returns a new C<Specio::DeclaredAt>
|
||||
object.
|
||||
|
||||
=head2 $declared_at->package, $declared_at->filename, $declared_at->line
|
||||
|
||||
Returns the call stack information recorded when the object was created. These
|
||||
values are always populated.
|
||||
|
||||
=head2 $declared_at->subroutine
|
||||
|
||||
Returns the subroutine from the call stack. This may be an C<udnef>
|
||||
|
||||
=head2 $declared_at->has_subroutine
|
||||
|
||||
Returns true if there is a subroutine name associated with this object.
|
||||
|
||||
=head2 $declared_at->description
|
||||
|
||||
Puts all the information together into a single string like "declared in
|
||||
package Foo::Bar (.../Foo/Bar.pm) at line 42 in sub named blah".
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
162
database/perl/vendor/lib/Specio/Exception.pm
vendored
Normal file
162
database/perl/vendor/lib/Specio/Exception.pm
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
package Specio::Exception;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use overload
|
||||
q{""} => 'as_string',
|
||||
fallback => 1;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Devel::StackTrace;
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::OO;
|
||||
|
||||
{
|
||||
my $attrs = {
|
||||
message => {
|
||||
isa => 'Str',
|
||||
required => 1,
|
||||
},
|
||||
type => {
|
||||
does => 'Specio::Constraint::Role::Interface',
|
||||
required => 1,
|
||||
},
|
||||
value => {
|
||||
required => 1,
|
||||
},
|
||||
stack_trace => {
|
||||
init_arg => undef,
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
$self->{stack_trace}
|
||||
= Devel::StackTrace->new( ignore_package => __PACKAGE__ );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub as_string {
|
||||
my $self = shift;
|
||||
|
||||
my $str = $self->message;
|
||||
$str .= "\n\n" . $self->stack_trace->as_string;
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
sub throw {
|
||||
my $self = shift;
|
||||
|
||||
die $self if blessed $self;
|
||||
|
||||
die $self->new(@_);
|
||||
}
|
||||
|
||||
__PACKAGE__->_ooify;
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: An exception class for type constraint failures
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Exception - An exception class for type constraint failures
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Try::Tiny;
|
||||
|
||||
try {
|
||||
$type->validate_or_die($value);
|
||||
}
|
||||
catch {
|
||||
if ( $_->isa('Specio::Exception') ) {
|
||||
print $_->message, "\n";
|
||||
print $_->type->name, "\n";
|
||||
print $_->value, "\n";
|
||||
}
|
||||
};
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This exception class is thrown by Specio when a type check fails. It emulates
|
||||
the L<Throwable::Error> API, but doesn't use that module to avoid adding a
|
||||
dependency on L<Moo>.
|
||||
|
||||
=for Pod::Coverage BUILD throw
|
||||
|
||||
=head1 API
|
||||
|
||||
This class provides the following methods:
|
||||
|
||||
=head2 $exception->message
|
||||
|
||||
The error message associated with the exception.
|
||||
|
||||
=head2 $exception->stack_trace
|
||||
|
||||
A L<Devel::StackTrace> object for the exception.
|
||||
|
||||
=head2 $exception->type
|
||||
|
||||
The type constraint object against which the value failed.
|
||||
|
||||
=head2 $exception->value
|
||||
|
||||
The value that failed the type check.
|
||||
|
||||
=head2 $exception->as_string
|
||||
|
||||
The exception as a string. This includes the method and the stack trace.
|
||||
|
||||
=head1 OVERLOADING
|
||||
|
||||
This class overloads stringification to call the C<as_string> method.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
166
database/perl/vendor/lib/Specio/Exporter.pm
vendored
Normal file
166
database/perl/vendor/lib/Specio/Exporter.pm
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package Specio::Exporter;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Exporter';
|
||||
|
||||
use Specio::Helpers qw( install_t_sub );
|
||||
use Specio::Registry
|
||||
qw( exportable_types_for_package internal_types_for_package register );
|
||||
|
||||
my %Exported;
|
||||
|
||||
sub import {
|
||||
my $package = shift;
|
||||
my $reexport = shift;
|
||||
|
||||
my $caller = caller();
|
||||
|
||||
return if $Exported{$caller}{$package};
|
||||
|
||||
my $exported = exportable_types_for_package($package);
|
||||
|
||||
while ( my ( $name, $type ) = each %{$exported} ) {
|
||||
register( $caller, $name, $type->clone, $reexport );
|
||||
}
|
||||
|
||||
install_t_sub(
|
||||
$caller,
|
||||
internal_types_for_package($caller),
|
||||
);
|
||||
|
||||
if ( $package->can('_also_export') ) {
|
||||
for my $sub ( $package->_also_export ) {
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
*{ $caller . '::' . $sub } = \&{ $package . '::' . $sub };
|
||||
}
|
||||
}
|
||||
|
||||
$Exported{$caller}{$package} = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Base class for type libraries
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Exporter - Base class for type libraries
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package MyApp::Type::Library;
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
|
||||
declare( ... );
|
||||
|
||||
# more types here
|
||||
|
||||
package MyApp::Foo;
|
||||
|
||||
use MyApp::Type::Library
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Inheriting from this package makes your package a type exporter. By default,
|
||||
types defined in a package are never visible outside of the package. When you
|
||||
inherit from this package, all the types you define internally become
|
||||
available via exports.
|
||||
|
||||
The exported types are available through the importing package's C<t>
|
||||
subroutine.
|
||||
|
||||
By default, types your package imports are not re-exported:
|
||||
|
||||
package MyApp::Type::Library;
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins;
|
||||
|
||||
In this case, the types provided by L<Specio::Library::Builtins> are not
|
||||
exported to packages which C<use MyApp::Type::Library>.
|
||||
|
||||
You can explicitly ask for types to be re-exported:
|
||||
|
||||
package MyApp::Type::Library;
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins -reexport;
|
||||
|
||||
In this case, packages which C<use MyApp::Type::Library> will get all the
|
||||
types from L<Specio::Library::Builtins> as well as any types defined in
|
||||
C<MyApp::Type::Library>.
|
||||
|
||||
=head1 ADDITIONAL EXPORTS
|
||||
|
||||
If you want to export some additional subroutines from a package which has
|
||||
C<Specio::Exporter> as its parent, define a sub named C<_also_export>. This
|
||||
sub should return a I<list> of subroutines defined in your package that should
|
||||
also be exported. These subs will be exported unconditionally to any package
|
||||
that uses your package.
|
||||
|
||||
=head1 COMBINING LIBRARIES WITH L<Specio::Subs>
|
||||
|
||||
You can combine loading libraries with subroutine generation using
|
||||
L<Specio::Subs> by using C<_also_export> and
|
||||
C<Specio::Subs::subs_installed_into>:
|
||||
|
||||
package My::Library;
|
||||
|
||||
use My::Library::Internal -reexport;
|
||||
use Specio::Library::Builtins -reexport;
|
||||
use Specio::Subs qw( My::Library::Internal Specio::Library::Builtins );
|
||||
|
||||
sub _also_export {
|
||||
return Specio::Subs::subs_installed_into(__PACKAGE__);
|
||||
}
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
160
database/perl/vendor/lib/Specio/Helpers.pm
vendored
Normal file
160
database/perl/vendor/lib/Specio/Helpers.pm
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
package Specio::Helpers;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw( croak );
|
||||
use Exporter 'import';
|
||||
use overload ();
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Scalar::Util qw( blessed );
|
||||
|
||||
our @EXPORT_OK = qw( install_t_sub is_class_loaded perlstring _STRINGLIKE );
|
||||
|
||||
sub install_t_sub {
|
||||
|
||||
# Specio::DeclaredAt use Specio::OO, which in turn uses
|
||||
# Specio::Helpers. If we load this with "use" we get a cirular require and
|
||||
# a big mess.
|
||||
require Specio::DeclaredAt;
|
||||
|
||||
my $caller = shift;
|
||||
my $types = shift;
|
||||
|
||||
# XXX - check to see if their t() is something else entirely?
|
||||
return if $caller->can('t');
|
||||
|
||||
my $t = sub {
|
||||
my $name = shift;
|
||||
|
||||
croak 'The t subroutine requires a single non-empty string argument'
|
||||
unless _STRINGLIKE($name);
|
||||
|
||||
croak "There is no type named $name available for the $caller package"
|
||||
unless exists $types->{$name};
|
||||
|
||||
my $found = $types->{$name};
|
||||
|
||||
return $found unless @_;
|
||||
|
||||
my %p = @_;
|
||||
|
||||
croak 'Cannot parameterize a non-parameterizable type'
|
||||
unless $found->can('parameterize');
|
||||
|
||||
return $found->parameterize(
|
||||
declared_at => Specio::DeclaredAt->new_from_caller(1),
|
||||
%p,
|
||||
);
|
||||
};
|
||||
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
no warnings 'redefine';
|
||||
*{ $caller . '::t' } = $t;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitSubroutinePrototypes, Subroutines::ProhibitExplicitReturnUndef)
|
||||
sub _STRINGLIKE ($) {
|
||||
return $_[0] if _STRING( $_[0] );
|
||||
|
||||
return $_[0]
|
||||
if blessed $_[0]
|
||||
&& overload::Method( $_[0], q{""} )
|
||||
&& length "$_[0]";
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Borrowed from Params::Util
|
||||
sub _STRING ($) {
|
||||
return defined $_[0] && !ref $_[0] && length( $_[0] ) ? $_[0] : undef;
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
if ( $] >= 5.010 && eval { require XString; 1 } ) {
|
||||
*perlstring = \&XString::perlstring;
|
||||
}
|
||||
else {
|
||||
require B;
|
||||
*perlstring = \&B::perlstring;
|
||||
}
|
||||
}
|
||||
|
||||
# Borrowed from Types::Standard
|
||||
sub is_class_loaded {
|
||||
my $stash = do {
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
\%{ $_[0] . '::' };
|
||||
};
|
||||
|
||||
return 1 if exists $stash->{ISA};
|
||||
return 1 if exists $stash->{VERSION};
|
||||
|
||||
foreach my $globref ( values %{$stash} ) {
|
||||
return 1
|
||||
if ref \$globref eq 'GLOB'
|
||||
? *{$globref}{CODE}
|
||||
: ref $globref; # const or sub ref
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Helper subs for the Specio distro
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Helpers - Helper subs for the Specio distro
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There's nothing public here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
600
database/perl/vendor/lib/Specio/Library/Builtins.pm
vendored
Normal file
600
database/perl/vendor/lib/Specio/Library/Builtins.pm
vendored
Normal file
@@ -0,0 +1,600 @@
|
||||
package Specio::Library::Builtins;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use List::Util 1.33 ();
|
||||
use overload ();
|
||||
use re ();
|
||||
use Scalar::Util ();
|
||||
use Specio::Constraint::Parameterizable;
|
||||
use Specio::Declare;
|
||||
use Specio::Helpers ();
|
||||
|
||||
BEGIN {
|
||||
local $@ = undef;
|
||||
my $has_ref_util
|
||||
= eval { require Ref::Util; Ref::Util->VERSION('0.112'); 1 };
|
||||
sub _HAS_REF_UTIL () {$has_ref_util}
|
||||
}
|
||||
|
||||
declare(
|
||||
'Item',
|
||||
inline => sub {'1'}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Undef',
|
||||
parent => t('Item'),
|
||||
inline => sub {
|
||||
'!defined(' . $_[1] . ')';
|
||||
}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Defined',
|
||||
parent => t('Item'),
|
||||
inline => sub {
|
||||
'defined(' . $_[1] . ')';
|
||||
}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Bool',
|
||||
parent => t('Item'),
|
||||
inline => sub {
|
||||
return sprintf( <<'EOF', ( $_[1] ) x 7 );
|
||||
(
|
||||
(
|
||||
!ref( %s )
|
||||
&& (
|
||||
!defined( %s )
|
||||
|| %s eq q{}
|
||||
|| %s eq '1'
|
||||
|| %s eq '0'
|
||||
)
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, 'bool' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Value',
|
||||
parent => t('Defined'),
|
||||
inline => sub {
|
||||
$_[0]->parent->inline_check( $_[1] ) . ' && !ref(' . $_[1] . ')';
|
||||
}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Ref',
|
||||
parent => t('Defined'),
|
||||
|
||||
# no need to call parent - ref also checks for definedness
|
||||
inline => sub { 'ref(' . $_[1] . ')' }
|
||||
);
|
||||
|
||||
declare(
|
||||
'Str',
|
||||
parent => t('Value'),
|
||||
inline => sub {
|
||||
return sprintf( <<'EOF', ( $_[1] ) x 6 );
|
||||
(
|
||||
(
|
||||
defined( %s )
|
||||
&& !ref( %s )
|
||||
&& (
|
||||
( ref( \%s ) eq 'SCALAR' )
|
||||
|| do { ( ref( \( my $val = %s ) ) eq 'SCALAR' ) }
|
||||
)
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, q{""} )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
|
||||
my $value_type = t('Value');
|
||||
declare(
|
||||
'Num',
|
||||
parent => t('Str'),
|
||||
inline => sub {
|
||||
return sprintf( <<'EOF', ( $_[1] ) x 5 );
|
||||
(
|
||||
(
|
||||
defined( %s )
|
||||
&& !ref( %s )
|
||||
&& (
|
||||
do {
|
||||
( my $val = %s ) =~
|
||||
/\A
|
||||
-?[0-9]+(?:\.[0-9]+)?
|
||||
(?:[Ee][\-+]?[0-9]+)?
|
||||
\z/x
|
||||
}
|
||||
)
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '0+' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
|
||||
declare(
|
||||
'Int',
|
||||
parent => t('Num'),
|
||||
inline => sub {
|
||||
return sprintf( <<'EOF', ( $_[1] ) x 6 );
|
||||
(
|
||||
(
|
||||
defined( %s )
|
||||
&& !ref( %s )
|
||||
&& (
|
||||
do { ( my $val1 = %s ) =~ /\A-?[0-9]+(?:[Ee]\+?[0-9]+)?\z/ }
|
||||
)
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '0+' )
|
||||
&& do { ( my $val2 = %s + 0 ) =~ /\A-?[0-9]+(?:[Ee]\+?[0-9]+)?\z/ }
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_coderef(%s)'
|
||||
: q{ref(%s) eq 'CODE'};
|
||||
|
||||
declare(
|
||||
'CodeRef',
|
||||
parent => t('Ref'),
|
||||
inline => sub {
|
||||
return sprintf( <<"EOF", ( $_[1] ) x 3 );
|
||||
(
|
||||
$ref_check
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '&{}' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
# This is a 5.8 back-compat shim stolen from Type::Tiny's Devel::Perl58Compat
|
||||
# module.
|
||||
unless ( exists &re::is_regexp || _HAS_REF_UTIL ) {
|
||||
require B;
|
||||
*re::is_regexp = sub {
|
||||
## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
|
||||
eval { B::svref_2object( $_[0] )->MAGIC->TYPE eq 'r' };
|
||||
};
|
||||
}
|
||||
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_regexpref(%s)'
|
||||
: 're::is_regexp(%s)';
|
||||
|
||||
declare(
|
||||
'RegexpRef',
|
||||
parent => t('Ref'),
|
||||
inline => sub {
|
||||
return sprintf( <<"EOF", ( $_[1] ) x 3 );
|
||||
(
|
||||
$ref_check
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, 'qr' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_globref(%s)'
|
||||
: q{ref( %s ) eq 'GLOB'};
|
||||
|
||||
declare(
|
||||
'GlobRef',
|
||||
parent => t('Ref'),
|
||||
inline => sub {
|
||||
return sprintf( <<"EOF", ( $_[1] ) x 3 );
|
||||
(
|
||||
$ref_check
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '*{}' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_globref(%s)'
|
||||
: q{ref( %s ) eq 'GLOB'};
|
||||
|
||||
# NOTE: scalar filehandles are GLOB refs, but a GLOB ref is not always a
|
||||
# filehandle
|
||||
declare(
|
||||
'FileHandle',
|
||||
parent => t('Ref'),
|
||||
inline => sub {
|
||||
return sprintf( <<"EOF", ( $_[1] ) x 6 );
|
||||
(
|
||||
(
|
||||
$ref_check
|
||||
&& Scalar::Util::openhandle( %s )
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&&
|
||||
(
|
||||
%s->isa('IO::Handle')
|
||||
||
|
||||
(
|
||||
defined overload::Method( %s, '*{}' )
|
||||
&& Scalar::Util::openhandle( *{ %s } )
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
EOF
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_blessed_ref(%s)'
|
||||
: 'Scalar::Util::blessed(%s)';
|
||||
|
||||
declare(
|
||||
'Object',
|
||||
parent => t('Ref'),
|
||||
inline => sub { sprintf( $ref_check, $_[1] ) },
|
||||
);
|
||||
}
|
||||
|
||||
declare(
|
||||
'ClassName',
|
||||
parent => t('Str'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf(
|
||||
<<'EOF', $_[0]->parent->inline_check( $_[1] ), ( $_[1] ) x 2 );
|
||||
(
|
||||
( %s )
|
||||
&& length "%s"
|
||||
&& Specio::Helpers::is_class_loaded( "%s" )
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_scalarref(%s) || Ref::Util::is_plain_refref(%s)'
|
||||
: q{ref( %s ) eq 'SCALAR' || ref( %s ) eq 'REF'};
|
||||
|
||||
my $base_scalarref_check = sub {
|
||||
return sprintf( <<"EOF", ( $_[0] ) x 4 );
|
||||
(
|
||||
(
|
||||
$ref_check
|
||||
)
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '\${}' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
declare(
|
||||
'ScalarRef',
|
||||
type_class => 'Specio::Constraint::Parameterizable',
|
||||
parent => t('Ref'),
|
||||
inline => sub { $base_scalarref_check->( $_[1] ) },
|
||||
parameterized_inline_generator => sub {
|
||||
my $self = shift;
|
||||
my $parameter = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf(
|
||||
'( ( %s ) && ( %s ) )',
|
||||
$base_scalarref_check->($val),
|
||||
$parameter->inline_check( '${' . $val . '}' ),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_arrayref(%s)'
|
||||
: q{ref( %s ) eq 'ARRAY'};
|
||||
|
||||
my $base_arrayref_check = sub {
|
||||
return sprintf( <<"EOF", ( $_[0] ) x 3 );
|
||||
(
|
||||
$ref_check
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '\@{}' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
declare(
|
||||
'ArrayRef',
|
||||
type_class => 'Specio::Constraint::Parameterizable',
|
||||
parent => t('Ref'),
|
||||
inline => sub { $base_arrayref_check->( $_[1] ) },
|
||||
parameterized_inline_generator => sub {
|
||||
my $self = shift;
|
||||
my $parameter = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf(
|
||||
'( ( %s ) && ( List::Util::all { %s } @{ %s } ) )',
|
||||
$base_arrayref_check->($val),
|
||||
$parameter->inline_check('$_'),
|
||||
$val,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
my $ref_check
|
||||
= _HAS_REF_UTIL
|
||||
? 'Ref::Util::is_plain_hashref(%s)'
|
||||
: q{ref( %s ) eq 'HASH'};
|
||||
|
||||
my $base_hashref_check = sub {
|
||||
return sprintf( <<"EOF", ( $_[0] ) x 3 );
|
||||
(
|
||||
$ref_check
|
||||
||
|
||||
(
|
||||
Scalar::Util::blessed( %s )
|
||||
&& defined overload::Method( %s, '%%{}' )
|
||||
)
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
declare(
|
||||
'HashRef',
|
||||
type_class => 'Specio::Constraint::Parameterizable',
|
||||
parent => t('Ref'),
|
||||
inline => sub { $base_hashref_check->( $_[1] ) },
|
||||
parameterized_inline_generator => sub {
|
||||
my $self = shift;
|
||||
my $parameter = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf(
|
||||
'( ( %s ) && ( List::Util::all { %s } values %%{ %s } ) )',
|
||||
$base_hashref_check->($val),
|
||||
$parameter->inline_check('$_'),
|
||||
$val,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
declare(
|
||||
'Maybe',
|
||||
type_class => 'Specio::Constraint::Parameterizable',
|
||||
parent => t('Item'),
|
||||
inline => sub {'1'},
|
||||
parameterized_inline_generator => sub {
|
||||
my $self = shift;
|
||||
my $parameter = shift;
|
||||
my $val = shift;
|
||||
|
||||
return sprintf( <<'EOF', $val, $parameter->inline_check($val) );
|
||||
( !defined( %s ) || ( %s ) )
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Implements type constraint objects for Perl's built-in types
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Builtins - Implements type constraint objects for Perl's built-in types
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library provides a set of types parallel to those provided by Moose.
|
||||
|
||||
The types are in the following hierarchy
|
||||
|
||||
Item
|
||||
Bool
|
||||
Maybe (of `a)
|
||||
Undef
|
||||
Defined
|
||||
Value
|
||||
Str
|
||||
Num
|
||||
Int
|
||||
ClassName
|
||||
Ref
|
||||
ScalarRef (of `a)
|
||||
ArrayRef (of `a)
|
||||
HashRef (of `a)
|
||||
CodeRef
|
||||
RegexpRef
|
||||
GlobRef
|
||||
FileHandle
|
||||
Object
|
||||
|
||||
=head2 Item
|
||||
|
||||
Accepts any value
|
||||
|
||||
=head2 Bool
|
||||
|
||||
Accepts a non-reference that is C<undef>, an empty string, C<0>, or C<1>. It
|
||||
also accepts any object which overloads boolification.
|
||||
|
||||
=head2 Maybe (of `a)
|
||||
|
||||
A parameterizable type which accepts C<undef> or the type C<`a>. If not
|
||||
parameterized this type will accept any value.
|
||||
|
||||
=head2 Undef
|
||||
|
||||
Only accepts C<undef>.
|
||||
|
||||
=head2 Value
|
||||
|
||||
Accepts any non-reference value.
|
||||
|
||||
=head2 Str
|
||||
|
||||
Accepts any non-reference value or an object which overloads stringification.
|
||||
|
||||
=head2 Num
|
||||
|
||||
Accepts nearly the same values as C<Scalar::Util::looks_like_number>, but does
|
||||
not accept numbers with leading or trailing spaces, infinities, or NaN. Also
|
||||
accepts an object which overloads numification.
|
||||
|
||||
=head2 Int
|
||||
|
||||
Accepts any integer value, or an object which overloads numification and
|
||||
numifies to an integer.
|
||||
|
||||
=head2 ClassName
|
||||
|
||||
Accepts any value which passes C<Str> where the string is a loaded package.
|
||||
|
||||
=head2 Ref
|
||||
|
||||
Accepts any reference.
|
||||
|
||||
=head2 ScalarRef (of `a)
|
||||
|
||||
Accepts a scalar reference or an object which overloads scalar
|
||||
dereferencing. If parameterized, the dereferenced value must be of type C<`a>.
|
||||
|
||||
=head2 ArrayRef (of `a)
|
||||
|
||||
Accepts a array reference or an object which overloads array dereferencing. If
|
||||
parameterized, the values in the arrayref must be of type C<`a>.
|
||||
|
||||
=head2 HashRef (of `a)
|
||||
|
||||
Accepts a hash reference or an object which overloads hash dereferencing. If
|
||||
parameterized, the values in the hashref must be of type C<`a>.
|
||||
|
||||
=head2 CodeRef
|
||||
|
||||
Accepts a code (sub) reference or an object which overloads code
|
||||
dereferencing.
|
||||
|
||||
=head2 RegexpRef
|
||||
|
||||
Accepts a regex object created by C<qr//> or an object which overloads
|
||||
regex interpolation.
|
||||
|
||||
=head2 GlobRef
|
||||
|
||||
Accepts a glob reference or an object which overloads glob dereferencing.
|
||||
|
||||
=head2 FileHandle
|
||||
|
||||
Accepts a glob reference which is an open file handle, any C<IO::Handle>
|
||||
Object or subclass, or an object which overloads glob dereferencing and
|
||||
returns a glob reference which is an open file handle.
|
||||
|
||||
=head2 Object
|
||||
|
||||
Accepts any blessed object.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
218
database/perl/vendor/lib/Specio/Library/Numeric.pm
vendored
Normal file
218
database/perl/vendor/lib/Specio/Library/Numeric.pm
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
package Specio::Library::Numeric;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins;
|
||||
|
||||
declare(
|
||||
'PositiveNum',
|
||||
parent => t('Num'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s > 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'PositiveOrZeroNum',
|
||||
parent => t('Num'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s >= 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'PositiveInt',
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s > 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'PositiveOrZeroInt',
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s >= 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'NegativeNum',
|
||||
parent => t('Num'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s < 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'NegativeOrZeroNum',
|
||||
parent => t('Num'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s <= 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'NegativeInt',
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s < 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'NegativeOrZeroInt',
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s <= 0
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'SingleDigit',
|
||||
parent => t('Int'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf(
|
||||
<<'EOF', $_[0]->parent->inline_check( $_[1] ), ( $_[1] ) x 2 );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s >= -9
|
||||
&&
|
||||
%s <= 9
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Implements type constraint objects for some common numeric types
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Numeric - Implements type constraint objects for some common numeric types
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library provides some additional string numeric for common cases.
|
||||
|
||||
=head2 PositiveNum
|
||||
|
||||
=head2 PositiveOrZeroNum
|
||||
|
||||
=head2 PositiveInt
|
||||
|
||||
=head2 PositiveOrZeroInt
|
||||
|
||||
=head2 NegativeNum
|
||||
|
||||
=head2 NegativeOrZeroNum
|
||||
|
||||
=head2 NegativeInt
|
||||
|
||||
=head2 NegativeOrZeroInt
|
||||
|
||||
=head2 SingleDigit
|
||||
|
||||
A single digit from -9 to 9.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
208
database/perl/vendor/lib/Specio/Library/Perl.pm
vendored
Normal file
208
database/perl/vendor/lib/Specio/Library/Perl.pm
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
package Specio::Library::Perl;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Library::String;
|
||||
use version 0.83 ();
|
||||
|
||||
use Specio::Declare;
|
||||
|
||||
my $package_inline = sub {
|
||||
return sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s =~ /\A[^\W\d]\w*(?:::\w+)*\z/
|
||||
)
|
||||
EOF
|
||||
};
|
||||
|
||||
declare(
|
||||
'PackageName',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => $package_inline,
|
||||
);
|
||||
|
||||
declare(
|
||||
'ModuleName',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => $package_inline,
|
||||
);
|
||||
|
||||
declare(
|
||||
'DistName',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s =~ /\A[^\W\d]\w*(?:-\w+)*\z/
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'Identifier',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s =~ /\A[^\W\d]\w*\z/
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'SafeIdentifier',
|
||||
parent => t('Identifier'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
%s !~ /\A[_ab]\z/
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'LaxVersionStr',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
version::is_lax(%s)
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'StrictVersionStr',
|
||||
parent => t('NonEmptyStr'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
version::is_strict(%s)
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Implements type constraint objects for some common Perl language things
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Perl - Implements type constraint objects for some common Perl language things
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library provides some additional string types for common cases.
|
||||
|
||||
=head2 PackageName
|
||||
|
||||
A valid package name. Unlike the C<ClassName> constraint from the
|
||||
L<Specio::Library::Builtins> library, this package does not need to be loaded.
|
||||
|
||||
This type does allow Unicode characters.
|
||||
|
||||
=head2 ModuleName
|
||||
|
||||
Same as C<PackageName>.
|
||||
|
||||
=head2 DistName
|
||||
|
||||
A valid distribution name like C<DBD-Pg> Basically this is the same as a
|
||||
package name with the double-colons replaced by dashes. Note that there are
|
||||
some historical distribution names that don't fit this pattern, like
|
||||
C<CGI.pm>.
|
||||
|
||||
This type does allow Unicode characters.
|
||||
|
||||
=head2 Identifier
|
||||
|
||||
An L<Identifier|perldata/Variable names> is something that could be used as a
|
||||
symbol name or other identifier (filehandle, directory handle, subroutine
|
||||
name, format name, or label). It's what you put after the sigil (dollar sign,
|
||||
at sign, percent sign) in a variable name. Generally, it's a bunch of
|
||||
word characters not starting with a digit.
|
||||
|
||||
This type does allow Unicode characters.
|
||||
|
||||
=head2 SafeIdentifier
|
||||
|
||||
This is just like an C<Identifier> but it excludes the single-character
|
||||
variables underscore (C<_>), C<a>< and C<b>, as these are special variables to
|
||||
the Perl interpreter.
|
||||
|
||||
=head2 LaxVersionStr and StrictVersionStr
|
||||
|
||||
Lax and strict version strings use the L<is_lax|version/is_lax> and
|
||||
L<is_strict|version/is_strict> methods from C<version> to check if the given
|
||||
string would be a valid lax or strict version. L<version::Internals> covers
|
||||
the details but basically: lax versions are everything you may do, and strict
|
||||
omit many of the usages best avoided.
|
||||
|
||||
=head2 CREDITS
|
||||
|
||||
Much of the code and docs for this library comes from MooseX::Types::Perl,
|
||||
written by Ricardo SIGNES <rjbs@cpan.org>.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
127
database/perl/vendor/lib/Specio/Library/String.pm
vendored
Normal file
127
database/perl/vendor/lib/Specio/Library/String.pm
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
package Specio::Library::String;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins;
|
||||
|
||||
declare(
|
||||
'NonEmptySimpleStr',
|
||||
parent => t('Str'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf(
|
||||
<<'EOF', $_[0]->parent->inline_check( $_[1] ), ( $_[1] ) x 3 );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
length %s > 0
|
||||
&&
|
||||
length %s <= 255
|
||||
&&
|
||||
%s !~ /[\n\r\x{2028}\x{2029}]/
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'NonEmptyStr',
|
||||
parent => t('Str'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf( <<'EOF', $_[0]->parent->inline_check( $_[1] ), $_[1] );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
length %s
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
declare(
|
||||
'SimpleStr',
|
||||
parent => t('Str'),
|
||||
inline => sub {
|
||||
return
|
||||
sprintf(
|
||||
<<'EOF', $_[0]->parent->inline_check( $_[1] ), ( $_[1] ) x 2 );
|
||||
(
|
||||
%s
|
||||
&&
|
||||
length %s <= 255
|
||||
&&
|
||||
%s !~ /[\n\r\x{2028}\x{2029}]/
|
||||
)
|
||||
EOF
|
||||
},
|
||||
);
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Implements type constraint objects for some common string types
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::String - Implements type constraint objects for some common string types
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This library provides some additional string types for common cases.
|
||||
|
||||
=head2 NonEmptyStr
|
||||
|
||||
A string which has at least one character.
|
||||
|
||||
=head2 SimpleStr
|
||||
|
||||
A string that is 255 characters or less with no vertical whitespace
|
||||
characters.
|
||||
|
||||
=head2 NonEmptySimpleStr
|
||||
|
||||
A non-empty string that is 255 characters or less with no vertical whitespace
|
||||
characters.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
250
database/perl/vendor/lib/Specio/Library/Structured.pm
vendored
Normal file
250
database/perl/vendor/lib/Specio/Library/Structured.pm
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
package Specio::Library::Structured;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use parent 'Specio::Exporter';
|
||||
|
||||
use Carp qw( confess );
|
||||
use List::Util ();
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::Constraint::Structurable;
|
||||
use Specio::Declare;
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::Library::Structured::Dict;
|
||||
use Specio::Library::Structured::Map;
|
||||
use Specio::Library::Structured::Tuple;
|
||||
use Specio::TypeChecks qw( does_role );
|
||||
|
||||
## no critic (Variables::ProtectPrivateVars)
|
||||
declare(
|
||||
'Dict',
|
||||
type_class => 'Specio::Constraint::Structurable',
|
||||
parent => Specio::Library::Structured::Dict->parent,
|
||||
inline => \&Specio::Library::Structured::Dict::_inline,
|
||||
parameterization_args_builder =>
|
||||
\&Specio::Library::Structured::Dict::_parameterization_args_builder,
|
||||
name_builder => \&Specio::Library::Structured::Dict::_name_builder,
|
||||
structured_inline_generator =>
|
||||
\&Specio::Library::Structured::Dict::_structured_inline_generator,
|
||||
);
|
||||
|
||||
declare(
|
||||
'Map',
|
||||
type_class => 'Specio::Constraint::Structurable',
|
||||
parent => Specio::Library::Structured::Map->parent,
|
||||
inline => \&Specio::Library::Structured::Map::_inline,
|
||||
parameterization_args_builder =>
|
||||
\&Specio::Library::Structured::Map::_parameterization_args_builder,
|
||||
name_builder => \&Specio::Library::Structured::Map::_name_builder,
|
||||
structured_inline_generator =>
|
||||
\&Specio::Library::Structured::Map::_structured_inline_generator,
|
||||
);
|
||||
|
||||
declare(
|
||||
'Tuple',
|
||||
type_class => 'Specio::Constraint::Structurable',
|
||||
parent => Specio::Library::Structured::Tuple->parent,
|
||||
inline => \&Specio::Library::Structured::Tuple::_inline,
|
||||
parameterization_args_builder =>
|
||||
\&Specio::Library::Structured::Tuple::_parameterization_args_builder,
|
||||
name_builder => \&Specio::Library::Structured::Tuple::_name_builder,
|
||||
structured_inline_generator =>
|
||||
\&Specio::Library::Structured::Tuple::_structured_inline_generator,
|
||||
);
|
||||
## use critic
|
||||
|
||||
sub optional {
|
||||
return { optional => shift };
|
||||
}
|
||||
|
||||
sub slurpy {
|
||||
return { slurpy => shift };
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _also_export {qw( optional slurpy )}
|
||||
## use critic
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Structured types for Specio (Dict, Map, Tuple)
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Structured - Structured types for Specio (Dict, Map, Tuple)
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::Library::String;
|
||||
use Specio::Library::Structured;
|
||||
|
||||
my $map = t(
|
||||
'Map',
|
||||
of => {
|
||||
key => t('NonEmptyStr'),
|
||||
value => t('Int'),
|
||||
},
|
||||
);
|
||||
my $tuple = t(
|
||||
'Tuple',
|
||||
of => [ t('Str'), t('Num') ],
|
||||
);
|
||||
my $dict = t(
|
||||
'Dict',
|
||||
of => {
|
||||
kv => {
|
||||
name => t('Str'),
|
||||
age => t('Int'),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<This particular library should be considered in an alpha state. The syntax
|
||||
for defining structured types may change, as well as some of the internals of
|
||||
its implementation.>
|
||||
|
||||
This library provides a set of structured types for Specio, C<Dict>, C<Map>,
|
||||
and C<Tuple>. This library also exports two helper subs used for some types,
|
||||
C<optional> and C<slurpy>.
|
||||
|
||||
All structured types are parameterized by calling C<< t( 'Type Name', of =>
|
||||
... ) >>. The arguments passed after C<of> vary for each type.
|
||||
|
||||
=head2 Dict
|
||||
|
||||
A C<Dict> is a hashref with a well-defined set of keys and types for those
|
||||
key.
|
||||
|
||||
The argument passed to C<of> should be a single hashref. That hashref must
|
||||
contain a C<kv> key defining the expected keys and the types for their
|
||||
values. This C<kv> value is itself a hashref. If a key/value pair is optional,
|
||||
use C<optional> around the I<type> for that key:
|
||||
|
||||
my $person = t(
|
||||
'Dict',
|
||||
of => {
|
||||
kv => {
|
||||
first => t('NonEmptyStr'),
|
||||
middle => optional( t('NonEmptyStr') ),
|
||||
last => t('NonEmptyStr'),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
If a key is optional, then it can be omitted entirely, but if it passed then
|
||||
it's type will be checked, so it cannot just be set to C<undef>.
|
||||
|
||||
You can also pass a C<slurpy> key. If this is passed, then the C<Dict> will
|
||||
allow other, unknown keys, as long as they match the specified type:
|
||||
|
||||
my $person = t(
|
||||
'Dict',
|
||||
of => {
|
||||
kv => {
|
||||
first => t('NonEmptyStr'),
|
||||
middle => optional( t('NonEmptyStr') ),
|
||||
last => t('NonEmptyStr'),
|
||||
},
|
||||
slurpy => t('Int'),
|
||||
},
|
||||
);
|
||||
|
||||
=head2 Map
|
||||
|
||||
A C<Map> is a hashref with specified types for its keys and values, but no
|
||||
well-defined key names.
|
||||
|
||||
The argument passed to C<of> should be a single hashref with two keys, C<key>
|
||||
and C<value>. The type for the C<key> will typically be some sort of key, but
|
||||
if you're using a tied hash or an object with hash overloading it could
|
||||
conceivably be any sort of value.
|
||||
|
||||
=head2 Tuple
|
||||
|
||||
A C<Tuple> is an arrayref with a fixed set of members in a specific order.
|
||||
|
||||
The argument passed to C<of> should be a single arrayref consisting of
|
||||
types. You can mark a slot in the C<Tuple> as optional by wrapping the type in
|
||||
a call to C<optional>:
|
||||
|
||||
my $record = t(
|
||||
'Tuple',
|
||||
of => [
|
||||
t('PositiveInt'),
|
||||
t('Str'),
|
||||
optional( t('Num') ),
|
||||
optional( t('Num') ),
|
||||
],
|
||||
);
|
||||
|
||||
You can have as many C<optional> elements as you want, but they must always
|
||||
come in sequence at the end of the tuple definition. You cannot interleave
|
||||
required and optional elements.
|
||||
|
||||
You can also make the Tuple accept an arbitrary number of values by wrapping
|
||||
the last type in a call to C<slurpy>:
|
||||
|
||||
my $record = t(
|
||||
'Tuple',
|
||||
of => [
|
||||
t('PositiveInt'),
|
||||
t('Str'),
|
||||
slurpy( t('Num') ),
|
||||
],
|
||||
);
|
||||
|
||||
In this case, the C<Tuple> will require the first two elements and then allow
|
||||
any number (including zero) of C<Num> elements.
|
||||
|
||||
You cannot mix C<optional> and C<slurpy> in a C<Tuple> definition.
|
||||
|
||||
=for Pod::Coverage optional slurpy
|
||||
|
||||
=head1 LIMITATIONS
|
||||
|
||||
Currently all structured types require that the types they are structured with
|
||||
can be inlined. This may change in the future, but inlining all your types is
|
||||
a really good idea, so you should do that anyway.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
168
database/perl/vendor/lib/Specio/Library/Structured/Dict.pm
vendored
Normal file
168
database/perl/vendor/lib/Specio/Library/Structured/Dict.pm
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package Specio::Library::Structured::Dict;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use List::Util ();
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::TypeChecks qw( does_role );
|
||||
|
||||
my $hashref = t('HashRef');
|
||||
|
||||
sub parent {$hashref}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _inline {
|
||||
$hashref->inline_check( $_[1] );
|
||||
}
|
||||
|
||||
sub _parameterization_args_builder {
|
||||
my $self = shift;
|
||||
my $args = shift;
|
||||
|
||||
for my $p ( ( $args->{slurpy} || () ), values %{ $args->{kv} } ) {
|
||||
my $type;
|
||||
if ( blessed($p) ) {
|
||||
$type = $p;
|
||||
}
|
||||
else {
|
||||
if ( ref $p eq 'HASH' && $p->{optional} ) {
|
||||
$type = $p->{optional};
|
||||
}
|
||||
else {
|
||||
confess
|
||||
'Can only pass types, optional types, and slurpy types when defining a Dict';
|
||||
}
|
||||
}
|
||||
|
||||
does_role( $type, 'Specio::Constraint::Role::Interface' )
|
||||
or confess
|
||||
'All parameters passed to ->parameterize must be objects which do the Specio::Constraint::Role::Interface role';
|
||||
|
||||
confess
|
||||
'All parameters passed to ->parameterize must be inlinable constraints'
|
||||
unless $type->can_be_inlined;
|
||||
}
|
||||
|
||||
return %{$args};
|
||||
}
|
||||
|
||||
sub _name_builder {
|
||||
my $self = shift;
|
||||
my $p = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
my @kv;
|
||||
for my $k ( sort keys %{ $p->{kv} } ) {
|
||||
my $v = $p->{kv}{$k};
|
||||
if ( blessed($v) ) {
|
||||
push @kv, "$k => " . $self->_name_or_anon($v);
|
||||
}
|
||||
elsif ( $v->{optional} ) {
|
||||
push @kv,
|
||||
"$k => " . $self->_name_or_anon( $v->{optional} ) . '?';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $p->{slurpy} ) {
|
||||
push @kv, $self->_name_or_anon( $p->{slurpy} ) . '...';
|
||||
}
|
||||
|
||||
return 'Dict{ ' . ( join ', ', @kv ) . ' }';
|
||||
}
|
||||
|
||||
sub _structured_inline_generator {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
my %args = @_;
|
||||
|
||||
my @code = sprintf( '( %s )', $hashref->_inline_check($val) );
|
||||
|
||||
for my $k ( sort keys %{ $args{kv} } ) {
|
||||
my $p = $args{kv}{$k};
|
||||
my $access = sprintf( '%s->{%s}', $val, perlstring($k) );
|
||||
|
||||
if ( !blessed($p) ) {
|
||||
my $type = $p->{optional};
|
||||
|
||||
push @code,
|
||||
sprintf(
|
||||
'( exists %s ? ( %s ) : 1 )',
|
||||
$access, $type->_inline_check($access)
|
||||
);
|
||||
}
|
||||
else {
|
||||
push @code, sprintf( '( %s )', $p->_inline_check($access) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $args{slurpy} ) {
|
||||
my $check
|
||||
= '( do { my %%_____known_____ = map { $_ => 1 } ( %s ); List::Util::all { %s } grep { ! $_____known_____{$_} } sort keys %%{ %s } } )';
|
||||
push @code,
|
||||
sprintf(
|
||||
$check,
|
||||
( join ', ', map { perlstring($_) } keys %{ $args{kv} } ),
|
||||
$args{slurpy}->_inline_check( sprintf( '%s->{$_}', $val ) ),
|
||||
$val,
|
||||
);
|
||||
}
|
||||
|
||||
return '( ' . ( join ' && ', @code ) . ' )';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Guts of Dict structured type
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Structured::Dict - Guts of Dict structured type
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There are no user facing parts here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
124
database/perl/vendor/lib/Specio/Library/Structured/Map.pm
vendored
Normal file
124
database/perl/vendor/lib/Specio/Library/Structured/Map.pm
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package Specio::Library::Structured::Map;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use List::Util ();
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::TypeChecks qw( does_role );
|
||||
|
||||
my $hashref = t('HashRef');
|
||||
|
||||
sub parent {$hashref}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _inline {
|
||||
$hashref->inline_check( $_[1] );
|
||||
}
|
||||
|
||||
sub _parameterization_args_builder {
|
||||
my $self = shift;
|
||||
my $args = shift;
|
||||
|
||||
for my $k (qw( key value )) {
|
||||
does_role(
|
||||
$args->{$k},
|
||||
'Specio::Constraint::Role::Interface'
|
||||
)
|
||||
or confess
|
||||
qq{The "$k" parameter passed to ->parameterize must be one or more objects which do the Specio::Constraint::Role::Interface role};
|
||||
|
||||
confess
|
||||
qq{The "$k" parameter passed to ->parameterize must be an inlinable constraint}
|
||||
unless $args->{$k}->can_be_inlined;
|
||||
}
|
||||
return map { $_ => $args->{$_} } qw( key value );
|
||||
}
|
||||
|
||||
sub _name_builder {
|
||||
my $self = shift;
|
||||
my $p = shift;
|
||||
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
return
|
||||
'Map{ '
|
||||
. $self->_name_or_anon( $p->{key} ) . ' => '
|
||||
. $self->_name_or_anon( $p->{value} ) . ' }';
|
||||
}
|
||||
|
||||
sub _structured_inline_generator {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
my %args = @_;
|
||||
|
||||
my $code = <<'EOF';
|
||||
(
|
||||
( %s )
|
||||
&& ( List::Util::all { %s } keys %%{ %s } )
|
||||
&& ( List::Util::all { %s } values %%{ %s } )
|
||||
)
|
||||
EOF
|
||||
|
||||
return sprintf(
|
||||
$code,
|
||||
$hashref->_inline_check($val),
|
||||
$args{key}->inline_check('$_'),
|
||||
$val,
|
||||
$args{value}->inline_check('$_'),
|
||||
$val,
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Guts of Map structured type
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Structured::Map - Guts of Map structured type
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There are no user facing parts here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
218
database/perl/vendor/lib/Specio/Library/Structured/Tuple.pm
vendored
Normal file
218
database/perl/vendor/lib/Specio/Library/Structured/Tuple.pm
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
package Specio::Library::Structured::Tuple;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess );
|
||||
use List::Util ();
|
||||
use Scalar::Util qw( blessed );
|
||||
use Specio::Library::Builtins;
|
||||
use Specio::TypeChecks qw( does_role );
|
||||
|
||||
my $arrayref = t('ArrayRef');
|
||||
|
||||
sub parent {$arrayref}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _inline {
|
||||
$arrayref->inline_check( $_[1] );
|
||||
}
|
||||
|
||||
sub _parameterization_args_builder {
|
||||
my $self = shift;
|
||||
my $args = shift;
|
||||
|
||||
my $saw_slurpy;
|
||||
my $saw_optional;
|
||||
for my $p ( @{$args} ) {
|
||||
if ($saw_slurpy) {
|
||||
confess
|
||||
'A Tuple cannot have any parameters after a slurpy parameter';
|
||||
}
|
||||
if ( $saw_optional && blessed($p) ) {
|
||||
confess
|
||||
'A Tuple cannot have a non-optional parameter after an optional parameter';
|
||||
}
|
||||
|
||||
my $type;
|
||||
if ( blessed($p) ) {
|
||||
$type = $p;
|
||||
}
|
||||
else {
|
||||
if ( ref $p eq 'HASH' ) {
|
||||
if ( $p->{optional} ) {
|
||||
$saw_optional = 1;
|
||||
$type = $p->{optional};
|
||||
}
|
||||
if ( $p->{slurpy} ) {
|
||||
$saw_slurpy = 1;
|
||||
$type = $p->{slurpy};
|
||||
}
|
||||
}
|
||||
else {
|
||||
confess
|
||||
'Can only pass types, optional types, and slurpy types when defining a Tuple';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $saw_optional && $saw_slurpy ) {
|
||||
confess
|
||||
'Cannot defined a slurpy Tuple with optional slots as well';
|
||||
}
|
||||
|
||||
does_role( $type, 'Specio::Constraint::Role::Interface' )
|
||||
or confess
|
||||
'All parameters passed to ->parameterize must be objects which do the Specio::Constraint::Role::Interface role';
|
||||
|
||||
confess
|
||||
'All parameters passed to ->parameterize must be inlinable constraints'
|
||||
unless $type->can_be_inlined;
|
||||
}
|
||||
|
||||
return ( of => $args );
|
||||
}
|
||||
|
||||
sub _name_builder {
|
||||
my $self = shift;
|
||||
my $p = shift;
|
||||
|
||||
my @names;
|
||||
for my $m ( @{ $p->{of} } ) {
|
||||
## no critic (Subroutines::ProtectPrivateSubs)
|
||||
if ( blessed($m) ) {
|
||||
push @names, $self->_name_or_anon($m);
|
||||
}
|
||||
elsif ( $m->{optional} ) {
|
||||
push @names, $self->_name_or_anon( $m->{optional} ) . '?';
|
||||
}
|
||||
elsif ( $m->{slurpy} ) {
|
||||
push @names, $self->_name_or_anon( $m->{slurpy} ) . '...';
|
||||
}
|
||||
}
|
||||
|
||||
return 'Tuple[ ' . ( join ', ', @names ) . ' ]';
|
||||
}
|
||||
|
||||
sub _structured_inline_generator {
|
||||
my $self = shift;
|
||||
my $val = shift;
|
||||
my %args = @_;
|
||||
|
||||
my @of = @{ $args{of} };
|
||||
|
||||
my $slurpy;
|
||||
$slurpy = ( pop @of )->{slurpy}
|
||||
if !blessed( $of[-1] ) && $of[-1]->{slurpy};
|
||||
|
||||
my @code = sprintf( '( %s )', $arrayref->_inline_check($val) );
|
||||
|
||||
unless ($slurpy) {
|
||||
my $min = 0;
|
||||
my $max = 0;
|
||||
for my $p (@of) {
|
||||
|
||||
# Unblessed values are optional.
|
||||
if ( blessed($p) ) {
|
||||
$min++;
|
||||
$max++;
|
||||
}
|
||||
else {
|
||||
$max++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($min) {
|
||||
push @code,
|
||||
sprintf(
|
||||
'( @{ %s } >= %d && @{ %s } <= %d )',
|
||||
$val, $min, $val, $max
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for my $i ( 0 .. $#of ) {
|
||||
my $p = $of[$i];
|
||||
my $access = sprintf( '%s->[%d]', $val, $i );
|
||||
|
||||
if ( !blessed($p) ) {
|
||||
my $type = $p->{optional};
|
||||
|
||||
push @code,
|
||||
sprintf(
|
||||
'( @{%s} >= %d ? ( %s ) : 1 )', $val, $i + 1,
|
||||
$type->_inline_check($access)
|
||||
);
|
||||
}
|
||||
else {
|
||||
push @code,
|
||||
sprintf( '( %s )', $p->_inline_check($access) );
|
||||
}
|
||||
}
|
||||
|
||||
if ($slurpy) {
|
||||
my $non_slurpy = scalar @of;
|
||||
my $check
|
||||
= '( @{%s} > %d ? ( List::Util::all { %s } @{%s}[%d .. $#{%s}] ) : 1 )';
|
||||
push @code,
|
||||
sprintf(
|
||||
$check,
|
||||
$val, $non_slurpy, $slurpy->_inline_check('$_'),
|
||||
$val, $non_slurpy, $val,
|
||||
);
|
||||
}
|
||||
|
||||
return '( ' . ( join ' && ', @code ) . ' )';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Guts of Tuple structured type
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Library::Structured::Tuple - Guts of Tuple structured type
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There are no user facing parts here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
412
database/perl/vendor/lib/Specio/OO.pm
vendored
Normal file
412
database/perl/vendor/lib/Specio/OO.pm
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
package Specio::OO;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw( confess );
|
||||
use List::Util qw( all );
|
||||
use MRO::Compat;
|
||||
use Role::Tiny;
|
||||
use Scalar::Util qw( weaken );
|
||||
use Specio::Helpers qw( perlstring );
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
use Specio::TypeChecks;
|
||||
use Storable qw( dclone );
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Exporter qw( import );
|
||||
|
||||
## no critic (Modules::ProhibitAutomaticExportation)
|
||||
our @EXPORT = qw(
|
||||
clone
|
||||
_ooify
|
||||
);
|
||||
## use critic
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _ooify {
|
||||
my $class = shift;
|
||||
|
||||
my $attrs = $class->_attrs;
|
||||
for my $name ( sort keys %{$attrs} ) {
|
||||
my $attr = $attrs->{$name};
|
||||
|
||||
_inline_reader( $class, $name, $attr );
|
||||
_inline_predicate( $class, $name, $attr );
|
||||
}
|
||||
|
||||
_inline_constructor($class);
|
||||
}
|
||||
## use critic
|
||||
|
||||
sub _inline_reader {
|
||||
my $class = shift;
|
||||
my $name = shift;
|
||||
my $attr = shift;
|
||||
|
||||
my $reader;
|
||||
if ( $attr->{lazy} && ( my $builder = $attr->{builder} ) ) {
|
||||
my $source = <<'EOF';
|
||||
sub {
|
||||
unless ( exists $_[0]->{%s} ) {
|
||||
$_[0]->{%s} = $_[0]->%s;
|
||||
Scalar::Util::weaken( $_[0]->{%s} ) if %s && ref $_[0]->{%s};
|
||||
}
|
||||
$_[0]->{%s};
|
||||
}
|
||||
EOF
|
||||
$reader = sprintf(
|
||||
$source,
|
||||
$name,
|
||||
$name,
|
||||
$builder,
|
||||
$name,
|
||||
( $attr->{weak_ref} ? 1 : 0 ),
|
||||
$name,
|
||||
$name,
|
||||
);
|
||||
}
|
||||
else {
|
||||
$reader = sprintf( 'sub { $_[0]->{%s} }', $name );
|
||||
}
|
||||
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
*{ $class . '::' . $name } = _eval_or_die(
|
||||
$reader, $class . '->' . $name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub _inline_predicate {
|
||||
my $class = shift;
|
||||
my $name = shift;
|
||||
my $attr = shift;
|
||||
|
||||
return unless $attr->{predicate};
|
||||
|
||||
my $predicate = "sub { exists \$_[0]->{$name} }";
|
||||
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
*{ $class . '::' . $attr->{predicate} } = _eval_or_die(
|
||||
$predicate, $class . '->' . $attr->{predicate},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
my @RolesWithBUILD = qw( Specio::Constraint::Role::Interface );
|
||||
|
||||
# This is an optimization to avoid calling this many times over:
|
||||
#
|
||||
# Specio::TypeChecks->can( 'is_' . $attr->{isa} )
|
||||
my %TypeChecks;
|
||||
|
||||
BEGIN {
|
||||
for my $sub (@Specio::TypeChecks::EXPORT_OK) {
|
||||
my ($type) = $sub =~ /^is_(.+)$/
|
||||
or next;
|
||||
$TypeChecks{$type} = Specio::TypeChecks->can($sub);
|
||||
}
|
||||
}
|
||||
|
||||
sub _inline_constructor {
|
||||
my $class = shift;
|
||||
|
||||
my @build_subs;
|
||||
for my $parent ( @{ mro::get_linear_isa($class) } ) {
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
push @build_subs, $parent . '::BUILD'
|
||||
if defined &{ $parent . '::BUILD' };
|
||||
}
|
||||
}
|
||||
|
||||
# This is all a hack to avoid needing Class::Method::Modifiers to add a
|
||||
# BUILD from a role. We can't just call the method in the role "BUILD" or
|
||||
# it will be shadowed by a class's BUILD. So we give it a wacky unique
|
||||
# name. We need to explicitly know which roles have a _X_BUILD method
|
||||
# because Role::Tiny doesn't provide a way to list all the roles applied
|
||||
# to a class.
|
||||
for my $role (@RolesWithBUILD) {
|
||||
if ( Role::Tiny::does_role( $class, $role ) ) {
|
||||
( my $build_name = $role ) =~ s/::/_/g;
|
||||
$build_name = q{_} . $build_name . '_BUILD';
|
||||
push @build_subs, $role . '::' . $build_name;
|
||||
}
|
||||
}
|
||||
|
||||
my $constructor = <<'EOF';
|
||||
sub {
|
||||
my $class = shift;
|
||||
|
||||
my %p = do {
|
||||
if ( @_ == 1 ) {
|
||||
if ( ref $_[0] eq 'HASH' ) {
|
||||
%{ shift() };
|
||||
}
|
||||
else {
|
||||
Specio::OO::_constructor_confess(
|
||||
Specio::OO::_bad_args_message( $class, @_ ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
Specio::OO::_constructor_confess(
|
||||
Specio::OO::_bad_args_message( $class, @_ ) )
|
||||
if @_ % 2;
|
||||
@_;
|
||||
}
|
||||
};
|
||||
|
||||
my $self = bless {}, $class;
|
||||
|
||||
EOF
|
||||
|
||||
my $attrs = $class->_attrs;
|
||||
for my $name ( sort keys %{$attrs} ) {
|
||||
my $attr = $attrs->{$name};
|
||||
my $key_name = defined $attr->{init_arg} ? $attr->{init_arg} : $name;
|
||||
|
||||
if ( $attr->{required} ) {
|
||||
$constructor .= <<"EOF";
|
||||
Specio::OO::_constructor_confess(
|
||||
"$class->new requires a $key_name argument.")
|
||||
unless exists \$p{$key_name};
|
||||
EOF
|
||||
}
|
||||
|
||||
if ( $attr->{builder} && !$attr->{lazy} ) {
|
||||
my $builder = $attr->{builder};
|
||||
$constructor .= <<"EOF";
|
||||
\$p{$key_name} = $class->$builder unless exists \$p{$key_name};
|
||||
EOF
|
||||
}
|
||||
|
||||
if ( $attr->{isa} ) {
|
||||
my $validator;
|
||||
if ( $TypeChecks{ $attr->{isa} } ) {
|
||||
$validator
|
||||
= 'Specio::TypeChecks::is_'
|
||||
. $attr->{isa}
|
||||
. "( \$p{$key_name} )";
|
||||
}
|
||||
else {
|
||||
my $quoted_class = perlstring( $attr->{isa} );
|
||||
$validator
|
||||
= "Specio::TypeChecks::isa_class( \$p{$key_name}, $quoted_class )";
|
||||
}
|
||||
|
||||
$constructor .= <<"EOF";
|
||||
if ( exists \$p{$key_name} && !$validator ) {
|
||||
Carp::confess(
|
||||
Specio::OO::_bad_value_message(
|
||||
"The value you provided to $class->new for $key_name is not a valid $attr->{isa}.",
|
||||
\$p{$key_name},
|
||||
)
|
||||
);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
if ( $attr->{does} ) {
|
||||
my $quoted_role = perlstring( $attr->{does} );
|
||||
$constructor .= <<"EOF";
|
||||
if ( exists \$p{$key_name} && !Specio::TypeChecks::does_role( \$p{$key_name}, $quoted_role ) ) {
|
||||
Carp::confess(
|
||||
Specio::OO::_bad_value_message(
|
||||
"The value you provided to $class->new for $key_name does not do the $attr->{does} role.",
|
||||
\$p{$key_name},
|
||||
)
|
||||
);
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
if ( $attr->{weak_ref} ) {
|
||||
$constructor .= " Scalar::Util::weaken( \$p{$key_name} );\n";
|
||||
}
|
||||
|
||||
$constructor
|
||||
.= " \$self->{$name} = \$p{$key_name} if exists \$p{$key_name};\n";
|
||||
|
||||
$constructor .= "\n";
|
||||
}
|
||||
|
||||
$constructor .= ' $self->' . $_ . "(\\%p);\n" for @build_subs;
|
||||
$constructor .= <<'EOF';
|
||||
|
||||
return $self;
|
||||
}
|
||||
EOF
|
||||
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
*{ $class . '::new' } = _eval_or_die(
|
||||
$constructor, $class . '->new',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# This used to be done with Eval::Closure but that added a lot of unneeded
|
||||
# overhead. We're never actually eval'ing a closure, just plain source, so
|
||||
# doing it by hand is a worthwhile optimization.
|
||||
sub _eval_or_die {
|
||||
local $@ = undef;
|
||||
## no critic (Variables::RequireInitializationForLocalVars)
|
||||
# $SIG{__DIE__} = undef causes warnings with 5.8.x
|
||||
local $SIG{__DIE__};
|
||||
## no critic (BuiltinFunctions::ProhibitStringyEval)
|
||||
my $sub = eval <<"EOF";
|
||||
#line 1 "$_[1]"
|
||||
$_[0];
|
||||
EOF
|
||||
my $e = $@;
|
||||
die $e if $e;
|
||||
return $sub;
|
||||
}
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _constructor_confess {
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
confess shift;
|
||||
}
|
||||
|
||||
sub _bad_args_message {
|
||||
my $class = shift;
|
||||
|
||||
return
|
||||
"$class->new requires either a hashref or hash as arguments. You passed "
|
||||
. partial_dump(@_);
|
||||
}
|
||||
|
||||
sub _bad_value_message {
|
||||
my $message = shift;
|
||||
my $value = shift;
|
||||
|
||||
return $message . ' You passed ' . partial_dump($value);
|
||||
}
|
||||
## use critic
|
||||
|
||||
my %BuiltinTypes = map { $_ => 1 } qw(
|
||||
SCALAR
|
||||
ARRAY
|
||||
HASH
|
||||
CODE
|
||||
REF
|
||||
GLOB
|
||||
LVALUE
|
||||
FORMAT
|
||||
IO
|
||||
VSTRING
|
||||
Regexp
|
||||
);
|
||||
|
||||
sub clone {
|
||||
my $self = shift;
|
||||
|
||||
# Attributes which provide a clone method are cloned by calling that
|
||||
# method on the _clone_ (not the original). This is primarily to allow us
|
||||
# to clone the coercions contained by a type in a way that doesn't lead to
|
||||
# circular clone (type clones coercions which in turn need to clone their
|
||||
# to/from types which in turn ...).
|
||||
my $attrs = $self->_attrs;
|
||||
my %special = map { $_ => $attrs->{$_}{clone} }
|
||||
grep { $attrs->{$_}{clone} } keys %{$attrs};
|
||||
|
||||
my $new;
|
||||
for my $key ( keys %{$self} ) {
|
||||
my $value = $self->{$key};
|
||||
|
||||
if ( $special{$key} ) {
|
||||
$new->{$key} = $value;
|
||||
next;
|
||||
}
|
||||
|
||||
# We need to special case arrays of Specio objects, as they may
|
||||
# contain code refs which cannot be cloned with dclone. Not using
|
||||
# blessed is a small optimization.
|
||||
if ( ( ref $value eq 'ARRAY' )
|
||||
&& all { ( ref($_) || q{} ) =~ /Specio/ } @{$value} ) {
|
||||
|
||||
$new->{$key} = [ map { $_->clone } @{$value} ];
|
||||
next;
|
||||
}
|
||||
|
||||
# This is a weird hacky way of trying to avoid calling
|
||||
# Scalar::Util::blessed, which showed up as a hotspot in profiling of
|
||||
# loading DateTime. That's because we call ->clone a _lot_ (it's
|
||||
# called every time a type is exported).
|
||||
my $ref = ref $value;
|
||||
$new->{$key}
|
||||
= !$ref ? $value
|
||||
: $ref eq 'CODE' ? $value
|
||||
: $BuiltinTypes{$ref} ? dclone($value)
|
||||
: $value->clone;
|
||||
}
|
||||
|
||||
bless $new, ( ref $self );
|
||||
|
||||
for my $key ( keys %special ) {
|
||||
my $method = $special{$key};
|
||||
$new->{$key} = $new->$method;
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A painfully poor reimplementation of Moo(se)
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::OO - A painfully poor reimplementation of Moo(se)
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Specio can't depend on Moo or Moose, so this module provides a terrible
|
||||
reimplementation of a small slice of their features.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
261
database/perl/vendor/lib/Specio/PartialDump.pm
vendored
Normal file
261
database/perl/vendor/lib/Specio/PartialDump.pm
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
package Specio::PartialDump;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Scalar::Util qw( looks_like_number reftype blessed );
|
||||
|
||||
use Exporter qw( import );
|
||||
|
||||
our @EXPORT_OK = qw( partial_dump );
|
||||
|
||||
my $MaxLength = 100;
|
||||
my $MaxElements = 6;
|
||||
my $MaxDepth = 2;
|
||||
|
||||
sub partial_dump {
|
||||
my (@args) = @_;
|
||||
|
||||
my $dump
|
||||
= _should_dump_as_pairs(@args)
|
||||
? _dump_as_pairs( 1, @args )
|
||||
: _dump_as_list( 1, @args );
|
||||
|
||||
if ( length($dump) > $MaxLength ) {
|
||||
my $max_length = $MaxLength - 3;
|
||||
$max_length = 0 if $max_length < 0;
|
||||
substr( $dump, $max_length, length($dump) - $max_length ) = '...';
|
||||
}
|
||||
|
||||
return $dump;
|
||||
}
|
||||
|
||||
sub _should_dump_as_pairs {
|
||||
my (@what) = @_;
|
||||
|
||||
return if @what % 2 != 0; # must be an even list
|
||||
|
||||
for ( my $i = 0; $i < @what; $i += 2 ) {
|
||||
return if ref $what[$i]; # plain strings are keys
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub _dump_as_pairs {
|
||||
my ( $depth, @what ) = @_;
|
||||
|
||||
my $truncated;
|
||||
if ( defined $MaxElements and ( @what / 2 ) > $MaxElements ) {
|
||||
$truncated = 1;
|
||||
@what = splice( @what, 0, $MaxElements * 2 );
|
||||
}
|
||||
|
||||
return join(
|
||||
', ', _dump_as_pairs_recursive( $depth, @what ),
|
||||
( $truncated ? "..." : () )
|
||||
);
|
||||
}
|
||||
|
||||
sub _dump_as_pairs_recursive {
|
||||
my ( $depth, @what ) = @_;
|
||||
|
||||
return unless @what;
|
||||
|
||||
my ( $key, $value, @rest ) = @what;
|
||||
|
||||
return (
|
||||
( _format_key( $depth, $key ) . ': ' . _format( $depth, $value ) ),
|
||||
_dump_as_pairs_recursive( $depth, @rest ),
|
||||
);
|
||||
}
|
||||
|
||||
sub _dump_as_list {
|
||||
my ( $depth, @what ) = @_;
|
||||
|
||||
my $truncated;
|
||||
if ( @what > $MaxElements ) {
|
||||
$truncated = 1;
|
||||
@what = splice( @what, 0, $MaxElements );
|
||||
}
|
||||
|
||||
return join(
|
||||
', ', ( map { _format( $depth, $_ ) } @what ),
|
||||
( $truncated ? "..." : () )
|
||||
);
|
||||
}
|
||||
|
||||
sub _format {
|
||||
my ( $depth, $value ) = @_;
|
||||
|
||||
defined($value)
|
||||
? (
|
||||
ref($value)
|
||||
? (
|
||||
blessed($value)
|
||||
? _format_object( $depth, $value )
|
||||
: _format_ref( $depth, $value )
|
||||
)
|
||||
: (
|
||||
looks_like_number($value)
|
||||
? _format_number( $depth, $value )
|
||||
: _format_string( $depth, $value )
|
||||
)
|
||||
)
|
||||
: _format_undef( $depth, $value ),
|
||||
}
|
||||
|
||||
sub _format_key {
|
||||
my ( undef, $key ) = @_;
|
||||
return $key;
|
||||
}
|
||||
|
||||
sub _format_ref {
|
||||
my ( $depth, $ref ) = @_;
|
||||
|
||||
if ( $depth > $MaxDepth ) {
|
||||
return overload::StrVal($ref);
|
||||
}
|
||||
else {
|
||||
my $reftype = reftype($ref);
|
||||
$reftype = 'SCALAR'
|
||||
if $reftype eq 'REF' || $reftype eq 'LVALUE';
|
||||
my $method = "_format_" . lc $reftype;
|
||||
|
||||
if ( my $sub = __PACKAGE__->can($method) ) {
|
||||
return $sub->( $depth, $ref );
|
||||
}
|
||||
else {
|
||||
return overload::StrVal($ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _format_array {
|
||||
my ( $depth, $array ) = @_;
|
||||
|
||||
my $class = blessed($array) || '';
|
||||
$class .= "=" if $class;
|
||||
|
||||
return $class . "[ " . _dump_as_list( $depth + 1, @$array ) . " ]";
|
||||
}
|
||||
|
||||
sub _format_hash {
|
||||
my ( $depth, $hash ) = @_;
|
||||
|
||||
my $class = blessed($hash) || '';
|
||||
$class .= "=" if $class;
|
||||
|
||||
return $class . "{ " . _dump_as_pairs(
|
||||
$depth + 1,
|
||||
map { $_ => $hash->{$_} } sort keys %$hash
|
||||
) . " }";
|
||||
}
|
||||
|
||||
sub _format_scalar {
|
||||
my ( $depth, $scalar ) = @_;
|
||||
|
||||
my $class = blessed($scalar) || '';
|
||||
$class .= "=" if $class;
|
||||
|
||||
return $class . "\\" . _format( $depth + 1, $$scalar );
|
||||
}
|
||||
|
||||
sub _format_object {
|
||||
my ( $depth, $object ) = @_;
|
||||
|
||||
return _format_ref( $depth, $object );
|
||||
}
|
||||
|
||||
sub _format_string {
|
||||
my ( undef, $str ) = @_;
|
||||
|
||||
# FIXME use String::Escape ?
|
||||
|
||||
# remove vertical whitespace
|
||||
$str =~ s/\n/\\n/g;
|
||||
$str =~ s/\r/\\r/g;
|
||||
|
||||
# reformat nonprintables
|
||||
$str =~ s/(\P{IsPrint})/"\\x{" . sprintf("%x", ord($1)) . "}"/ge;
|
||||
|
||||
_quote($str);
|
||||
}
|
||||
|
||||
sub _quote {
|
||||
my ($str) = @_;
|
||||
|
||||
qq{"$str"};
|
||||
}
|
||||
|
||||
sub _format_undef {"undef"}
|
||||
|
||||
sub _format_number {
|
||||
my ( undef, $value ) = @_;
|
||||
return "$value";
|
||||
}
|
||||
|
||||
# ABSTRACT: A partially rear-ended copy of Devel::PartialDump without prereqs
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::PartialDump - A partially rear-ended copy of Devel::PartialDump without prereqs
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Specio::PartialDump qw( partial_dump );
|
||||
|
||||
partial_dump( { foo => 42 } );
|
||||
partial_dump(qw( a b c d e f g ));
|
||||
partial_dump( foo => 42, bar => [ 1, 2, 3 ], );
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a copy of Devel::PartialDump with all the OO bits and prereqs
|
||||
removed. You may want to use this module in your own code to generate nicely
|
||||
formatted messages when a type constraint fails.
|
||||
|
||||
This module optionally exports one sub, C<partial_dump>. This sub accepts any
|
||||
number of arguments. If given more than one, it will assume that it's either
|
||||
been given a list of key/value pairs (to build a hash) or a list of values (to
|
||||
build an array) and dump them appropriately. Objects and references are
|
||||
stringified in a sane way.
|
||||
|
||||
=for Pod::Coverage partial_dump
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2008 by יובל קוג'מן (Yuval Kogman).
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
103
database/perl/vendor/lib/Specio/Registry.pm
vendored
Normal file
103
database/perl/vendor/lib/Specio/Registry.pm
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package Specio::Registry;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent 'Exporter';
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( confess croak );
|
||||
|
||||
our @EXPORT_OK
|
||||
= qw( exportable_types_for_package internal_types_for_package register );
|
||||
|
||||
my %Registry;
|
||||
|
||||
sub register {
|
||||
confess
|
||||
'register requires three or four arguments (package, name, type, [exportable])'
|
||||
unless @_ == 3 || @_ == 4;
|
||||
|
||||
my $package = shift;
|
||||
my $name = shift;
|
||||
my $type = shift;
|
||||
my $exportable = shift;
|
||||
|
||||
croak "The $package package already has a type named $name"
|
||||
if $Registry{$package}{internal}{$name};
|
||||
|
||||
# This is structured so that we can always return a _reference_ for
|
||||
# *_types_for_package. This means that the generated t sub sees any
|
||||
# changes to the registry as they happen. This is important inside a
|
||||
# package that is declaring new types. It needs to be able to see types it
|
||||
# has declared.
|
||||
$Registry{$package}{internal}{$name} = $type;
|
||||
$Registry{$package}{exportable}{$name} = $type
|
||||
if $exportable;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub exportable_types_for_package {
|
||||
my $package = shift;
|
||||
|
||||
return $Registry{$package}{exportable} ||= {};
|
||||
}
|
||||
|
||||
sub internal_types_for_package {
|
||||
my $package = shift;
|
||||
|
||||
return $Registry{$package}{internal} ||= {};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Implements the per-package type registry
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Registry - Implements the per-package type registry
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There's nothing public here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
137
database/perl/vendor/lib/Specio/Role/Inlinable.pm
vendored
Normal file
137
database/perl/vendor/lib/Specio/Role/Inlinable.pm
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
package Specio::Role::Inlinable;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Eval::Closure qw( eval_closure );
|
||||
|
||||
use Role::Tiny;
|
||||
|
||||
requires '_build_description';
|
||||
|
||||
{
|
||||
my $attrs = {
|
||||
_inline_generator => {
|
||||
is => 'ro',
|
||||
isa => 'CodeRef',
|
||||
predicate => '_has_inline_generator',
|
||||
init_arg => 'inline_generator',
|
||||
},
|
||||
inline_environment => {
|
||||
is => 'ro',
|
||||
isa => 'HashRef',
|
||||
lazy => 1,
|
||||
init_arg => 'inline_environment',
|
||||
builder => '_build_inline_environment',
|
||||
},
|
||||
_generated_inline_sub => {
|
||||
is => 'ro',
|
||||
isa => 'CodeRef',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_generated_inline_sub',
|
||||
},
|
||||
declared_at => {
|
||||
is => 'ro',
|
||||
isa => 'Specio::DeclaredAt',
|
||||
required => 1,
|
||||
},
|
||||
description => {
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
init_arg => undef,
|
||||
lazy => 1,
|
||||
builder => '_build_description',
|
||||
},
|
||||
};
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _attrs {
|
||||
return $attrs;
|
||||
}
|
||||
}
|
||||
|
||||
# These are here for backwards compatibility. Some other packages that I wrote
|
||||
# may call the private methods.
|
||||
|
||||
## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
|
||||
sub _description { $_[0]->description }
|
||||
sub _inline_environment { $_[0]->inline_environment }
|
||||
## use critic
|
||||
|
||||
sub can_be_inlined {
|
||||
my $self = shift;
|
||||
|
||||
return $self->_has_inline_generator;
|
||||
}
|
||||
|
||||
sub _build_generated_inline_sub {
|
||||
my $self = shift;
|
||||
|
||||
my $source
|
||||
= 'sub { ' . $self->_inline_generator->( $self, '$_[0]' ) . '}';
|
||||
|
||||
return eval_closure(
|
||||
source => $source,
|
||||
environment => $self->inline_environment,
|
||||
description => 'inlined sub for ' . $self->description,
|
||||
);
|
||||
}
|
||||
|
||||
sub _build_inline_environment {
|
||||
return {};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: A role for things which can be inlined (type constraints and coercions)
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Role::Inlinable - A role for things which can be inlined (type constraints and coercions)
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This role implements a common API for inlinable things, type constraints and
|
||||
coercions. It is fully documented in the relevant classes.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
282
database/perl/vendor/lib/Specio/Subs.pm
vendored
Normal file
282
database/perl/vendor/lib/Specio/Subs.pm
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
package Specio::Subs;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Carp qw( croak );
|
||||
use Eval::Closure qw( eval_closure );
|
||||
use Module::Runtime qw( use_package_optimistically );
|
||||
use Specio::Library::Perl;
|
||||
use Specio::Registry qw( exportable_types_for_package );
|
||||
|
||||
my $counter = 0;
|
||||
|
||||
sub import {
|
||||
shift;
|
||||
my @libs = @_;
|
||||
|
||||
my $caller = caller();
|
||||
|
||||
my $ident = t('Identifier');
|
||||
|
||||
use_package_optimistically($_) for @libs;
|
||||
|
||||
for my $types ( map { exportable_types_for_package($_) } @libs ) {
|
||||
for my $name ( keys %{$types} ) {
|
||||
croak
|
||||
qq{Cannot use '$name' type to create a check sub. It results in an invalid Perl subroutine name}
|
||||
unless $ident->check( 'is_' . $name );
|
||||
|
||||
_export_subs( $name, $types->{$name}, $caller );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _export_subs {
|
||||
my $name = shift;
|
||||
my $type = shift;
|
||||
my $caller = shift;
|
||||
|
||||
_export_validation_subs( $name, $type, $caller );
|
||||
|
||||
return unless $type->has_coercions;
|
||||
|
||||
_export_coercion_subs( $name, $type, $caller );
|
||||
}
|
||||
|
||||
sub _export_validation_subs {
|
||||
my $name = shift;
|
||||
my $type = shift;
|
||||
my $caller = shift;
|
||||
|
||||
my $is_name = 'is_' . $name;
|
||||
my $assert_name = 'assert_' . $name;
|
||||
if ( $type->can_be_inlined ) {
|
||||
_make_sub(
|
||||
$caller, $is_name,
|
||||
$type->inline_check('$_[0]')
|
||||
);
|
||||
_make_sub(
|
||||
$caller, $assert_name,
|
||||
$type->inline_assert('$_[0]')
|
||||
);
|
||||
}
|
||||
else {
|
||||
_install_sub(
|
||||
$caller, $is_name,
|
||||
sub { $type->value_is_valid( $_[0] ) }
|
||||
);
|
||||
_install_sub(
|
||||
$caller, $assert_name,
|
||||
sub { $type->validate_or_die( $_[0] ) }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub _export_coercion_subs {
|
||||
my $name = shift;
|
||||
my $type = shift;
|
||||
my $caller = shift;
|
||||
|
||||
my $to_name = 'to_' . $name;
|
||||
if ( $type->can_inline_coercion ) {
|
||||
_make_sub(
|
||||
$caller, $to_name,
|
||||
$type->inline_coercion('$_[0]')
|
||||
);
|
||||
}
|
||||
else {
|
||||
_install_sub(
|
||||
$caller, $to_name,
|
||||
sub { $type->coerce_value( $_[0] ) }
|
||||
);
|
||||
}
|
||||
|
||||
my $force_name = 'force_' . $name;
|
||||
if ( $type->can_inline_coercion_and_check ) {
|
||||
_make_sub(
|
||||
$caller, $force_name,
|
||||
$type->inline_coercion_and_check('$_[0]')
|
||||
);
|
||||
}
|
||||
else {
|
||||
_install_sub(
|
||||
$caller, $force_name,
|
||||
sub {
|
||||
my $val = $type->coerce_value( $_[0] );
|
||||
$type->validate_or_die($val);
|
||||
return $val;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub _make_sub {
|
||||
my $caller = shift;
|
||||
my $sub_name = shift;
|
||||
my $source = shift;
|
||||
my $env = shift;
|
||||
|
||||
my $sub = eval_closure(
|
||||
source => 'sub { ' . $source . ' }',
|
||||
environment => $env,
|
||||
description => $caller . '::'
|
||||
. $sub_name
|
||||
. ' generated by '
|
||||
. __PACKAGE__,
|
||||
);
|
||||
|
||||
_install_sub( $caller, $sub_name, $sub );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
my $sub_namer = do {
|
||||
eval {
|
||||
require Sub::Util;
|
||||
Sub::Util->VERSION(1.40);
|
||||
Sub::Util->can('set_subname');
|
||||
} or eval {
|
||||
require Sub::Name;
|
||||
Sub::Name->can('subname');
|
||||
}
|
||||
or sub { return $_[1] };
|
||||
};
|
||||
|
||||
my %Installed;
|
||||
|
||||
sub _install_sub {
|
||||
my $caller = shift;
|
||||
my $sub_name = shift;
|
||||
my $sub = shift;
|
||||
|
||||
my $fq_name = $caller . '::' . $sub_name;
|
||||
|
||||
{
|
||||
## no critic (TestingAndDebugging::ProhibitNoStrict)
|
||||
no strict 'refs';
|
||||
*{$fq_name} = $sub_namer->( $fq_name, $sub );
|
||||
}
|
||||
|
||||
$Installed{$caller} ||= [];
|
||||
push @{ $Installed{$caller} }, $sub_name;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub subs_installed_into {
|
||||
my $package = shift;
|
||||
|
||||
return @{ $Installed{$package} || [] };
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Make validation and coercion subs from Specio types
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::Subs - Make validation and coercion subs from Specio types
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Specio::Subs qw( Specio::Library::Builtins Specio::Library::Perl My::Lib );
|
||||
|
||||
if ( is_PackageName($var) ) { ... }
|
||||
|
||||
assert_Str($var);
|
||||
|
||||
my $person1 = to_Person($var);
|
||||
my $person2 = force_Person($var);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module generates a set of helpful validation and coercion subroutines for
|
||||
all of the types defined in one or more libraries.
|
||||
|
||||
To use it, simply import C<Specio::Subs> passing a list of one or more library
|
||||
names. This module will load those libraries as needed.
|
||||
|
||||
If any of the types in any libraries have names that do not work as part of a
|
||||
Perl subroutine name, this module will throw an exception.
|
||||
|
||||
If you have L<Sub::Util> or L<Sub::Name> installed, one of those will be used
|
||||
to name the generated subroutines.
|
||||
|
||||
=head1 "EXPORTS"
|
||||
|
||||
The following subs are created in the importing package:
|
||||
|
||||
=head2 is_$type($value)
|
||||
|
||||
This subroutine returns a boolean indicating whether or not the C<$value> is
|
||||
valid for the type.
|
||||
|
||||
=head2 assert_$type($value)
|
||||
|
||||
This subroutine dies if the C<$value> is not valid for the type.
|
||||
|
||||
=head2 to_$type($value)
|
||||
|
||||
This subroutine attempts to coerce C<$value> into the given type. If it cannot
|
||||
be coerced it returns the original C<$value>.
|
||||
|
||||
This is only created if the type has coercions.
|
||||
|
||||
=head2 force_$type($value)
|
||||
|
||||
This subroutine attempts to coerce C<$value> into the given type, and dies if
|
||||
it cannot do so.
|
||||
|
||||
This is only created if the type has coercions.
|
||||
|
||||
=head1 ADDITIONAL API
|
||||
|
||||
=for Pod::Coverage subs_installed_into
|
||||
|
||||
This module has a subroutine named C<subs_installed_into>. It is not exported
|
||||
but it can be called by its fully qualified name. It accepts a single
|
||||
argument, a package name. It returns a list of subs that it generated and
|
||||
installed in the given package, if any.
|
||||
|
||||
This exists to make it easy to write a type library that combines other
|
||||
library and generates helper subs for export all at once.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
107
database/perl/vendor/lib/Specio/TypeChecks.pm
vendored
Normal file
107
database/perl/vendor/lib/Specio/TypeChecks.pm
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
package Specio::TypeChecks;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.46';
|
||||
|
||||
use Exporter qw( import );
|
||||
use Specio::Helpers qw( is_class_loaded );
|
||||
use Scalar::Util qw( blessed );
|
||||
|
||||
our @EXPORT_OK = qw(
|
||||
does_role
|
||||
is_ArrayRef
|
||||
is_ClassName
|
||||
is_CodeRef
|
||||
is_HashRef
|
||||
is_Int
|
||||
is_Str
|
||||
isa_class
|
||||
);
|
||||
|
||||
sub is_ArrayRef {
|
||||
return ref $_[0] eq 'ARRAY';
|
||||
}
|
||||
|
||||
sub is_CodeRef {
|
||||
return ref $_[0] eq 'CODE';
|
||||
}
|
||||
|
||||
sub is_HashRef {
|
||||
return ref $_[0] eq 'HASH';
|
||||
}
|
||||
|
||||
sub is_Str {
|
||||
defined( $_[0] ) && !ref( $_[0] ) && ref( \$_[0] ) eq 'SCALAR'
|
||||
|| ref( \( my $val = $_[0] ) eq 'SCALAR' );
|
||||
}
|
||||
|
||||
sub is_Int {
|
||||
( defined( $_[0] ) && !ref( $_[0] ) && ref( \$_[0] ) eq 'SCALAR'
|
||||
|| ref( \( my $val = $_[0] ) eq 'SCALAR' ) )
|
||||
&& $_[0] =~ /^[0-9]+$/;
|
||||
}
|
||||
|
||||
sub is_ClassName {
|
||||
is_class_loaded( $_[0] );
|
||||
}
|
||||
|
||||
sub isa_class {
|
||||
blessed( $_[0] ) && $_[0]->isa( $_[1] );
|
||||
}
|
||||
|
||||
sub does_role {
|
||||
blessed( $_[0] ) && $_[0]->can('does') && $_[0]->does( $_[1] );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
# ABSTRACT: Type checks used internally for Specio classes (it's not self-bootstrapping (yet?))
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Specio::TypeChecks - Type checks used internally for Specio classes (it's not self-bootstrapping (yet?))
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 0.46
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
There's nothing public here.
|
||||
|
||||
=for Pod::Coverage .*
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
Bugs may be submitted at L<https://github.com/houseabsolute/Specio/issues>.
|
||||
|
||||
I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Specio can be found at L<https://github.com/houseabsolute/Specio>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is Copyright (c) 2012 - 2020 by Dave Rolsky.
|
||||
|
||||
This is free software, licensed under:
|
||||
|
||||
The Artistic License 2.0 (GPL Compatible)
|
||||
|
||||
The full text of the license can be found in the
|
||||
F<LICENSE> file included with this distribution.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user