File Coverage

blib/lib/Types/Const.pm
Criterion Covered Total %
statement 56 67 83.5
branch 12 20 60.0
condition 6 9 66.6
subroutine 19 20 95.0
pod n/a
total 93 116 80.1


line stmt bran cond sub pod time code
1             package Types::Const;
2              
3 3     3   404628 use v5.14;
  3         27  
4 3     3   17 use warnings;
  3         18  
  3         130  
5              
6             # ABSTRACT: Types that coerce references to read-only
7              
8             use Type::Library
9 3         28 -base,
10 3     3   1534 -declare => qw/ Const /;
  3         66183  
11              
12 3     3   3396 use Const::Fast ();
  3         1062  
  3         65  
13 3     3   16 use List::Util 1.33 ();
  3         50  
  3         61  
14 3     3   1758 use Storable 3.06 (); # Regexp support
  3         11564  
  3         82  
15 3     3   1505 use Type::Coercion;
  3         12238  
  3         100  
16 3     3   25 use Type::Tiny 1.002001;
  3         46  
  3         82  
17 3     3   1569 use Type::Utils -all;
  3         15100  
  3         26  
18 3     3   11563 use Types::Standard qw/ -types is_ArrayRef is_HashRef is_ScalarRef /;
  3         127559  
  3         30  
19 3     3   15077 use Types::TypeTiny ();
  3         9  
  3         82  
20              
21             # RECOMMEND PREREQ: Ref::Util::XS 0.100
22             # RECOMMEND PREREQ: Type::Tiny::XS
23              
24 3     3   1422 use namespace::autoclean 0.28;
  3         45570  
  3         18  
25              
26             our $VERSION = 'v0.5.0';
27              
28              
29             declare Const,
30             as Ref,
31             where \&__is_readonly,
32             message {
33             return "$_ is not readonly";
34             },
35             constraint_generator => \&__constraint_generator,
36             coercion_generator => \&__coercion_generator;
37              
38             coerce Const,
39             from Ref,
40             via \&__coerce_constant;
41              
42             sub __coerce_constant {
43 8 50   8   98 my $value = @_ ? $_[0] : $_;
44 8         36 Const::Fast::_make_readonly( $value => 0 );
45 8         1080 return $value;
46             }
47              
48             sub __is_readonly {
49 297 100   297   116964 if ( is_ArrayRef( $_[0] ) ) {
    100          
    100          
50             return Internals::SvREADONLY( @{ $_[0] } )
51 57   66 104   93 && List::Util::all { __is_readonly($_) } @{ $_[0] };
  104         199  
52             }
53             elsif ( is_HashRef( $_[0] ) ) {
54 45         117 &Internals::hv_clear_placeholders( $_[0] );
55             return Internals::SvREADONLY( %{ $_[0] } )
56 45   66 82   54 && List::Util::all { __is_readonly($_) } values %{ $_[0] };
  82         152  
57             }
58             elsif ( is_ScalarRef( $_[0] ) ) {
59 6         12 return Internals::SvREADONLY( ${ $_[0] } );
  6         33  
60             }
61              
62 189         669 return Internals::SvREADONLY( $_[0] );
63             }
64              
65             sub __constraint_generator {
66 6 100   6   52831 return Const unless @_;
67              
68 5         14 my $param = shift;
69 5 50       20 Types::TypeTiny::TypeTiny->check($param)
70             or _croak("Parameter to Const[`a] expected to be a type constraint; got $param");
71              
72 5 50       117 _croak("Only one parameter to Const[`a] expected; got @{[ 1 + @_ ]}.")
  0         0  
73             if @_;
74              
75 5         27 my $psub = $param->constraint;
76              
77             return sub {
78 37   66 37   248 return $psub->($_) && __is_readonly($_);
79 5         51 };
80             }
81              
82             sub __coercion_generator {
83 5     5   1027 my ( $parent, $child, $param ) = @_;
84              
85 5 50       18 return $parent->coercion unless $param->has_coercion;
86              
87 0           my $coercion = Type::Coercion->new( type_constraint => $child );
88              
89 0           my $coercable_item = $param->coercion->_source_type_union;
90              
91             $coercion->add_type_coercions(
92             $parent => sub {
93 0 0   0     my $value = @_ ? $_[0] : $_;
94 0           my @new;
95 0           for my $item (@$value) {
96 0 0         return $value unless $coercable_item->check($item);
97 0           push @new, $param->coerce($item);
98             }
99 0           return __coerce_constant(\@new);
100             },
101 0           );
102              
103 0           return $coercion;
104             }
105              
106             __PACKAGE__->meta->make_immutable;
107              
108             __END__