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   1736 use 5.008005;
  4         12  
2 4     4   22 use strict;
  4         6  
  4         80  
3 4     4   17 use warnings;
  4         6  
  4         88  
4              
5 4     4   19 use Carp ();
  4         7  
  4         73  
6 4     4   911 use Exporter::Tiny ();
  4         6308  
  4         75  
7 4     4   1764 use Tie::Array ();
  4         4621  
  4         113  
8 4     4   1863 use Tie::Hash ();
  4         3818  
  4         98  
9 4     4   1826 use Tie::Scalar ();
  4         2150  
  4         728  
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   14 our $AUTHORITY = 'cpan:TOBYINK';
17 4         7 our $VERSION = '0.013';
18 4         68 our @ISA = qw( Exporter::Tiny );
19 4         452 our @EXPORT = qw( ttie );
20            
21             sub ttie (\[$@%]@)#>&%*/&<%\$[]^!@;@)
22             {
23 10     10 1 4101 my ($ref, $type, @vals) = @_;
24            
25 10 100       44 if (ref($ref) eq "HASH")
    100          
26             {
27 3         19 tie(%$ref, "Type::Tie::HASH", $type);
28 3 50       23 %$ref = @vals if @vals;
29             }
30             elsif (ref($ref) eq "ARRAY")
31             {
32 3         18 tie(@$ref, "Type::Tie::ARRAY", $type);
33 3 50       91 @$ref = @vals if @vals;
34             }
35             else
36             {
37 4         28 tie($$ref, "Type::Tie::SCALAR", $type);
38 4 50       27 $$ref = $vals[-1] if @vals;
39             }
40 10         84 return $ref;
41             }
42             };
43              
44             BEGIN
45 0         0 {
46             package Type::Tie::BASE;
47 4     4   17 our $AUTHORITY = 'cpan:TOBYINK';
48 4         7 our $VERSION = '0.013';
49            
50             BEGIN {
51 4     4   13 my $impl;
52 4   33     26 $impl ||= eval { require Hash::FieldHash; 'Hash::FieldHash' };
  4         1755  
  4         4942  
53 4   33     13 $impl ||= do { require Hash::Util::FieldHash; 'Hash::Util::FieldHash' };
  0         0  
  0         0  
54 4         2202 $impl->import('fieldhash');
55             };
56            
57 4         25 fieldhash(my %TYPE);
58 4         12 fieldhash(my %COERCE);
59 4         1133 fieldhash(my %CHECK);
60            
61             sub _set_type
62             {
63 10     10   21 my $self = shift;
64 10         17 my $type = $_[0];
65            
66 10         51 $TYPE{$self} = $type;
67            
68 10 100       59 if ($type->isa('Type::Tiny'))
69             {
70 4         44 $CHECK{$self} = $type->compiled_check;
71 4         25 $COERCE{$self} = undef;
72 4 100       10 $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   50 : sub { $type->check($_[0]) };
  45         93  
80 6         27 $COERCE{$self} = undef;
81 20     20   38 $COERCE{$self} = sub { $type->coerce($_[0]) }
82 6 50 66     42 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   71 my $self = shift;
113 51         96 my $check = $CHECK{$self};
114 51         76 my $coerce = $COERCE{$self};
115            
116             my @vals = map {
117 51 100       116 my $val = $coerce ? $coerce->($_) : $_;
  69         142  
118 69 100       388 if (not $check->($val)) {
119 15         60 my $type = $TYPE{$self};
120 15 50 33     75 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         307 $val;
127             } (my @cp = @_); # need to copy @_ for Perl < 5.14
128            
129 36 50       177 wantarray ? @vals : $vals[0];
130             }
131             };
132              
133             BEGIN
134 0         0 {
135             package Type::Tie::ARRAY;
136 4     4   16 our $AUTHORITY = 'cpan:TOBYINK';
137 4         8 our $VERSION = '0.013';
138 4         677 our @ISA = qw( Tie::StdArray Type::Tie::BASE );
139            
140             sub TIEARRAY
141             {
142 3     3   9 my $class = shift;
143 3         42 my $self = $class->SUPER::TIEARRAY;
144 3         45 $self->_set_type($_[0]);
145 3         614 return $self;
146             }
147            
148             sub STORE
149             {
150 15     15   140 my $self = shift;
151 15         39 $self->SUPER::STORE($_[0], $self->coerce_and_check_value($_[1]));
152             }
153            
154             sub PUSH
155             {
156 6     6   60 my $self = shift;
157 6         15 $self->SUPER::PUSH( $self->coerce_and_check_value(@_) );
158             }
159            
160             sub UNSHIFT
161             {
162 6     6   24 my $self = shift;
163 6         17 $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   14 our $AUTHORITY = 'cpan:TOBYINK';
178 4         23 our $VERSION = '0.013';
179 4         656 our @ISA = qw( Tie::StdHash Type::Tie::BASE );
180            
181             sub TIEHASH
182             {
183 3     3   7 my $class = shift;
184 3         28 my $self = $class->SUPER::TIEHASH;
185 3         29 $self->_set_type($_[0]);
186 3         20 return $self;
187             }
188            
189             sub STORE
190             {
191 9     9   62 my $self = shift;
192 9         32 $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   14 our $AUTHORITY = 'cpan:TOBYINK';
200 4         8 our $VERSION = '0.013';
201 4         174 our @ISA = qw( Tie::StdScalar Type::Tie::BASE );
202            
203             sub TIESCALAR
204             {
205 4     4   11 my $class = shift;
206 4         32 my $self = $class->SUPER::TIESCALAR;
207 4         64 $self->_set_type($_[0]);
208 4         872 return $self;
209             }
210            
211             sub STORE
212             {
213 15     15   3455 my $self = shift;
214 15         49 $self->SUPER::STORE( $self->coerce_and_check_value($_[0]) );
215             }
216             };
217              
218             1;
219              
220             __END__