File Coverage

blib/lib/Type/TinyX/Facets.pm
Criterion Covered Total %
statement 59 59 100.0
branch 6 10 60.0
condition 5 8 62.5
subroutine 14 14 100.0
pod 2 2 100.0
total 86 93 92.4


line stmt bran cond sub pod time code
1             package Type::TinyX::Facets;
2              
3             # ABSTRACT: Easily create a facet parameterized Type::Tiny type
4              
5 1     1   309761 use strict;
  1         11  
  1         32  
6 1     1   6 use warnings;
  1         2  
  1         43  
7              
8             our $VERSION = '0.03';
9              
10 1     1   6 use B qw(perlstring);
  1         1  
  1         53  
11 1     1   7 use base 'Exporter::Tiny';
  1         3  
  1         102  
12 1     1   6 use Exporter::Tiny qw(mkopt);
  1         2  
  1         5  
13 1     1   214 use Carp;
  1         2  
  1         87  
14 1     1   440 use Safe::Isa;
  1         482  
  1         645  
15              
16             our @EXPORT = qw'facet facetize';
17              
18             my %FACET;
19              
20              
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46              
47             sub facet {
48              
49 3     3 1 912 my ( $name, $coderef ) = @_;
50              
51 3         8 my $caller = caller;
52              
53 3   100     27 $FACET{$caller} ||= {};
54 3         9 $FACET{$caller}{$name} = $coderef;
55             }
56              
57              
58              
59              
60              
61              
62              
63              
64              
65              
66              
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77              
78              
79              
80              
81              
82              
83              
84             sub facetize {
85              
86             # type may be first or last parameter
87 3 50   3 1 2047 my $self
88             = $_[-1]->$_isa( 'Type::Tiny' )
89             ? pop
90             : croak( "type object must be last parameter\n" );
91              
92 3         69 my $FACET = $FACET{ caller() };
93              
94             my @facets = map {
95 6         74 my ( $facet, $sub ) = @{$_};
  6         12  
96 6   33     33 $sub ||= $FACET->{$facet} || croak( "unknown facet: $facet" );
      66        
97 6         17 [ $facet, $sub ];
98 3         6 } @{ mkopt( \@_ ) };
  3         9  
99              
100              
101 3         13 my $name = "$self";
102              
103             my $inline_generator = sub {
104 15     15   156 my %p_not_destroyed = @_;
105             return sub {
106 15         1181 my %p = %p_not_destroyed; # copy;
107 15         31 my $var = $_[1];
108             my $r = sprintf(
109             '(%s)',
110             join( ' and ',
111             $self->inline_check( $var ),
112 15         46 map { $_->[1]->( \%p, $var, $_->[0] ) } @facets ),
  24         1905  
113             );
114              
115 12 50       608 croak sprintf(
    100          
116             'Attempt to parameterize type "%s" with unrecognised parameter%s %s',
117             $name,
118             scalar( keys %p ) == 1 ? '' : 's',
119             join( ", ", map( qq["$_"], sort keys %p ) ),
120             ) if keys %p;
121 10         34 return $r;
122 15         85 };
123 3         36 };
124              
125 3         9 $self->{inline_generator} = $inline_generator;
126             $self->{constraint_generator} = sub {
127 10     10   19051 my $sub = sprintf( 'sub { %s }',
128             $inline_generator->( @_ )->( $self, '$_[0]' ),
129             );
130             ## no critic( ProhibitStringyEval )
131 5 50       613 eval( $sub ) or croak "could not build sub: $@\n\nCODE: $sub\n";
132 3         12 };
133             $self->{name_generator} = sub {
134 5     5   138 my ( $s, %a ) = @_;
135             sprintf( '%s[%s]',
136             $s, join q[,],
137 5         72 map sprintf( "%s=>%s", $_, perlstring $a{$_} ),
138             sort keys %a );
139 3         11 };
140              
141 3 50       10 return if $self->is_anon;
142              
143             ## no critic( ProhibitNoStrict )
144 1     1   9 no strict qw( refs );
  1         2  
  1         51  
145 1     1   7 no warnings qw( redefine prototype );
  1         2  
  1         113  
146 3         37 *{ $self->library . '::' . $self->name } = $self->library->_mksub( $self );
  3         929  
147             }
148              
149              
150              
151             1;
152              
153             #
154             # This file is part of Type-TinyX-Facets
155             #
156             # This software is copyright (c) 2017 by Smithsonian Astrophysical Observatory.
157             #
158             # This is free software; you can redistribute it and/or modify it under
159             # the same terms as the Perl 5 programming language system itself.
160             #
161              
162             __END__