File Coverage

blib/lib/Type/Tie.pm
Criterion Covered Total %
statement 100 121 82.6
branch 19 32 59.3
condition 7 17 41.1
subroutine 27 30 90.0
pod 1 1 100.0
total 154 201 76.6


line stmt bran cond sub pod time code
1 4     4   1822 use 5.008005;
  4         16  
2 4     4   21 use strict;
  4         8  
  4         81  
3 4     4   19 use warnings;
  4         7  
  4         92  
4              
5 4     4   18 use Carp ();
  4         6  
  4         89  
6 4     4   973 use Exporter::Tiny ();
  4         6501  
  4         74  
7 4     4   1930 use Tie::Array ();
  4         4726  
  4         121  
8 4     4   1992 use Tie::Hash ();
  4         3796  
  4         126  
9 4     4   1957 use Tie::Scalar ();
  4         2234  
  4         750  
10              
11             ++$Carp::CarpInternal{"Type::Tie::$_"} for qw( BASE SCALAR ARRAY HASH );
12              
13             BEGIN
14 0         0 {
15             package Type::Tie;
16 4     4   16 our $AUTHORITY = 'cpan:TOBYINK';
17 4         8 our $VERSION = '0.014';
18 4         69 our @ISA = qw( Exporter::Tiny );
19 4         461 our @EXPORT = qw( ttie );
20            
21             sub ttie (\[$@%]@)#>&%*/&<%\$[]^!@;@)
22             {
23 10     10 1 4296 my ($ref, $type, @vals) = @_;
24            
25 10 100       49 if (ref($ref) eq "HASH")
    100          
26             {
27 3         24 tie(%$ref, "Type::Tie::HASH", $type);
28 3 50       31 %$ref = @vals if @vals;
29             }
30             elsif (ref($ref) eq "ARRAY")
31             {
32 3         23 tie(@$ref, "Type::Tie::ARRAY", $type);
33 3 50       37 @$ref = @vals if @vals;
34             }
35             else
36             {
37 4         38 tie($$ref, "Type::Tie::SCALAR", $type);
38 4 50       37 $$ref = $vals[-1] if @vals;
39             }
40 10         95 return $ref;
41             }
42             };
43              
44             BEGIN
45 0         0 {
46             package Type::Tie::BASE;
47 4     4   21 our $AUTHORITY = 'cpan:TOBYINK';
48 4         14 our $VERSION = '0.014';
49            
50             BEGIN {
51 4     4   13 my $impl;
52 4   33     35 $impl ||= eval { require Hash::FieldHash; 'Hash::FieldHash' };
  4         1865  
  4         6161  
53 4   33     15 $impl ||= do { require Hash::Util::FieldHash; 'Hash::Util::FieldHash' };
  0         0  
  0         0  
54 4         2389 $impl->import('fieldhash');
55             };
56            
57 4         33 fieldhash(my %TYPE);
58 4         15 fieldhash(my %COERCE);
59 4         1164 fieldhash(my %CHECK);
60            
61             sub _set_type
62             {
63 10     10   25 my $self = shift;
64 10         16 my $type = $_[0];
65            
66 10         60 $TYPE{$self} = $type;
67            
68 10 100       61 if ($type->isa('Type::Tiny'))
69             {
70 4         62 $CHECK{$self} = $type->compiled_check;
71 4         29 $COERCE{$self} = undef;
72 4 100       14 $COERCE{$self} = $type->coercion->compiled_coercion
73             if $type->has_coercion;
74             }
75             else
76             {
77             $CHECK{$self} = $type->can('compiled_check')
78             ? $type->compiled_check
79 6 50   45   53 : sub { $type->check($_[0]) };
  45         99  
80 6         18 $COERCE{$self} = undef;
81 20     20   95 $COERCE{$self} = sub { $type->coerce($_[0]) }
82 6 50 66     54 if $type->can("has_coercion")
      66        
83             && $type->can("coerce")
84             && $type->has_coercion;
85             }
86             }
87            
88             sub type
89             {
90 0     0   0 my $self = shift;
91 0         0 $TYPE{$self};
92             }
93            
94             sub _dd
95             {
96 0 0   0   0 my $value = @_ ? $_[0] : $_;
97             !defined $value ? 'Undef' :
98             !ref $value ? sprintf('Value %s', B::perlstring($value)) :
99 0 0       0 do {
    0          
100 0         0 require Data::Dumper;
101 0         0 local $Data::Dumper::Indent = 0;
102 0         0 local $Data::Dumper::Useqq = 1;
103 0         0 local $Data::Dumper::Terse = 1;
104 0         0 local $Data::Dumper::Sortkeys = 1;
105 0         0 local $Data::Dumper::Maxdepth = 2;
106 0         0 Data::Dumper::Dumper($value)
107             }
108             }
109            
110             sub coerce_and_check_value
111             {
112 51     51   77 my $self = shift;
113 51         98 my $check = $CHECK{$self};
114 51         81 my $coerce = $COERCE{$self};
115            
116             my @vals = map {
117 51 100       124 my $val = $coerce ? $coerce->($_) : $_;
  69         185  
118 69 100       402 if (not $check->($val)) {
119 15         63 my $type = $TYPE{$self};
120 15 50 33     81 Carp::croak(
      0        
121             $type && $type->can('get_message')
122             ? $type->get_message($val)
123             : sprintf("%s does not meet type constraint %s", _dd($_), $type||'Unknown')
124             );
125             }
126 54         310 $val;
127             } (my @cp = @_); # need to copy @_ for Perl < 5.14
128            
129 36 50       228 wantarray ? @vals : $vals[0];
130             }
131             };
132              
133             BEGIN
134 0         0 {
135             package Type::Tie::ARRAY;
136 4     4   15 our $AUTHORITY = 'cpan:TOBYINK';
137 4         8 our $VERSION = '0.014';
138 4         727 our @ISA = qw( Tie::StdArray Type::Tie::BASE );
139            
140             sub TIEARRAY
141             {
142 3     3   9 my $class = shift;
143 3         48 my $self = $class->SUPER::TIEARRAY;
144 3         53 $self->_set_type($_[0]);
145 3         663 return $self;
146             }
147            
148             sub STORE
149             {
150 15     15   153 my $self = shift;
151 15         36 $self->SUPER::STORE($_[0], $self->coerce_and_check_value($_[1]));
152             }
153            
154             sub PUSH
155             {
156 6     6   63 my $self = shift;
157 6         16 $self->SUPER::PUSH( $self->coerce_and_check_value(@_) );
158             }
159            
160             sub UNSHIFT
161             {
162 6     6   30 my $self = shift;
163 6         15 $self->SUPER::UNSHIFT( $self->coerce_and_check_value(@_) );
164             }
165              
166             sub SPLICE
167             {
168 0     0   0 my $self = shift;
169 0         0 my ($start, $len, @rest) = @_;
170 0         0 $self->SUPER::SPLICE($start, $len, $self->coerce_and_check_value(@rest) );
171             }
172             };
173              
174             BEGIN
175 0         0 {
176             package Type::Tie::HASH;
177 4     4   16 our $AUTHORITY = 'cpan:TOBYINK';
178 4         32 our $VERSION = '0.014';
179 4         695 our @ISA = qw( Tie::StdHash Type::Tie::BASE );
180            
181             sub TIEHASH
182             {
183 3     3   9 my $class = shift;
184 3         36 my $self = $class->SUPER::TIEHASH;
185 3         31 $self->_set_type($_[0]);
186 3         20 return $self;
187             }
188            
189             sub STORE
190             {
191 9     9   66 my $self = shift;
192 9         33 $self->SUPER::STORE($_[0], $self->coerce_and_check_value($_[1]));
193             }
194             };
195              
196             BEGIN
197 0         0 {
198             package Type::Tie::SCALAR;
199 4     4   16 our $AUTHORITY = 'cpan:TOBYINK';
200 4         8 our $VERSION = '0.014';
201 4         181 our @ISA = qw( Tie::StdScalar Type::Tie::BASE );
202            
203             sub TIESCALAR
204             {
205 4     4   11 my $class = shift;
206 4         45 my $self = $class->SUPER::TIESCALAR;
207 4         69 $self->_set_type($_[0]);
208 4         956 return $self;
209             }
210            
211             sub STORE
212             {
213 15     15   3842 my $self = shift;
214 15         61 $self->SUPER::STORE( $self->coerce_and_check_value($_[0]) );
215             }
216             };
217              
218             1;
219              
220             __END__