File Coverage

blib/lib/MooseX/Types/FakeHash.pm
Criterion Covered Total %
statement 72 75 96.0
branch 17 22 77.2
condition 0 6 0.0
subroutine 23 26 88.4
pod 1 1 100.0
total 113 130 86.9


line stmt bran cond sub pod time code
1 12     12   11102293 use strict;
  12         32  
  12         697  
2 12     12   65 use warnings;
  12         22  
  12         752  
3              
4             package MooseX::Types::FakeHash;
5             BEGIN {
6 12     12   426 $MooseX::Types::FakeHash::AUTHORITY = 'cpan:KENTNL';
7             }
8             {
9             $MooseX::Types::FakeHash::VERSION = '0.1.2';
10             }
11              
12             # ABSTRACT: Types for emulating Hash-like behaviours with ArrayRefs.
13              
14 12     12   14771 use MooseX::Types;
  12         8396878  
  12         92  
15 12     12   46430 use Moose::Util::TypeConstraints ();
  12         26  
  12         231  
16 12     12   80 use Moose::Meta::TypeConstraint::Parameterizable;
  12         25  
  12         433  
17 12     12   70 use Moose::Meta::TypeConstraint::Parameterized;
  12         25  
  12         25476  
18              
19              
20             ## no critic ( RequireArgUnpacking Capitalization )
21             sub _constraint_KeyWith {
22 68 50   68   1266012 return unless ref($_) eq 'ARRAY'; # its an array
23 68 100       104 return unless @{$_} == 2; # and it has exactly 2 keys.
  68         344  
24 56         142 return 1;
25             }
26              
27             sub _constraint_FakeHash {
28 32 50   32   7488961 return unless ref($_) eq 'ARRAY'; # its an array
29 32 100       62 return if scalar @{$_} & 1; # and it has a multiple of 2 keys ( bitwise checks for even, 0 == true )
  32         136  
30 24         65 return 1;
31             }
32              
33             sub _constraint_OrderedFakeHash {
34 28 50   28   13261401 return unless ref($_) eq 'ARRAY'; # its an array
35 28         68 return 1;
36             }
37              
38 0   0 0   0 sub _optimised_constraint_KeyWith { return ref( $_[0] ) eq 'ARRAY' && scalar @{ $_[0] } == 2 }
39 0   0 0   0 sub _optimised_constraint_FakeHash { return ref( $_[0] ) eq 'ARRAY' && !( scalar @{ $_[0] } & 1 ) }
40 0     0   0 sub _optimised_constraint_OrderedFakeHash { return ref( $_[0] ) eq 'ARRAY' }
41              
42             my $STR_check = Moose::Util::TypeConstraints::find_type_constraint('Str')->_compiled_type_constraint;
43              
44             sub _constraint_generator_KeyWith {
45 8     8   4745550 my $type_parameter = shift;
46 8         240 my $check = $type_parameter->_compiled_type_constraint;
47             return sub {
48 56 100   56   1631 $STR_check->( $_->[0] ) || return;
49 52 100       1902 $check->( $_->[1] ) || return;
50 48         626 1;
51 8         2403 };
52             }
53              
54             sub _constraint_generator_FakeHash {
55 4     4   42858 my $type_parameter = shift;
56 4         120 my $check = $type_parameter->_compiled_type_constraint;
57             return sub {
58 24     24   118 my @items = @{$_};
  24         74  
59 24         44 my $i = 0;
60 24         90 while ( $i <= $#items ) {
61 30 50       856 $STR_check->( $items[$i] ) || return;
62 30 100       1042 $check->( $items[ $i + 1 ] ) || return;
63             }
64             continue {
65 22         428 $i += 2;
66             }
67              
68 16         60 1;
69 4         1123 };
70             }
71              
72             sub _constraint_generator_OrderedFakeHash {
73 4     4   6817331 my $type_parameter = shift;
74 4         95 my $subtype = Moose::Meta::TypeConstraint::Parameterized->new(
75             name => 'OrderedFakeHash::KeyWith[' . $type_parameter->name . ']',
76             parent => _type_KeyWith(),
77             type_parameter => $type_parameter,
78             );
79             return sub {
80 28     28   131 for my $pair ( @{$_} ) {
  28         71  
81 48 50       436 $subtype->assert_valid($pair) || return;
82             }
83 22         238 1;
84 4         3833 };
85             }
86              
87             my $type_cache = {};
88              
89             sub _mk_type {
90 40     40   117 my (%args) = @_;
91 40         65 my $name = $args{name};
92 40 100       607 return $type_cache->{$name} if exists $type_cache->{$name};
93              
94 36         110 my $type = $type_cache->{$name} = Moose::Meta::TypeConstraint::Parameterizable->new(
95             package_defined_in => __PACKAGE__,
96             parent => Moose::Util::TypeConstraints::find_type_constraint('Ref'),
97             constraint => __PACKAGE__->can( '_constraint_' . $name ),
98             optimised_constraint => __PACKAGE__->can( '_optimised_constraint_' . $name ),
99             constraint_generator => __PACKAGE__->can( '_constraint_generator_' . $name ),
100             %args,
101             );
102 36         44415 Moose::Util::TypeConstraints::register_type_constraint($type);
103 36         5413 Moose::Util::TypeConstraints::add_parameterizable_type($type);
104 36         354 return $type;
105             }
106              
107 16     16   1280 sub _type_KeyWith { return _mk_type( name => 'KeyWith', ) }
108 12     12   34 sub _type_FakeHash { return _mk_type( name => 'FakeHash', ) }
109 12     12   41 sub _type_OrderedFakeHash { return _mk_type( name => 'OrderedFakeHash' ) }
110              
111             sub _setup {
112 12     12   149 _type_KeyWith;
113 12         32 _type_FakeHash;
114 12         37 _type_OrderedFakeHash;
115 12         22 return 1;
116             }
117              
118              
119              
120              
121             _setup();
122              
123             sub type_storage {
124 84     84 1 5814 return { map { ($_) x 2 } qw( KeyWith FakeHash OrderedFakeHash ) };
  252         1002  
125             }
126              
127 12     12   105 no Moose::Util::TypeConstraints;
  12         26  
  12         92  
128              
129             1;
130              
131             __END__
132              
133             =pod
134              
135             =head1 NAME
136              
137             MooseX::Types::FakeHash - Types for emulating Hash-like behaviours with ArrayRefs.
138              
139             =head1 VERSION
140              
141             version 0.1.2
142              
143             =head1 SYNOPSIS
144              
145             =head2 Standard Non-MooseX-Types style invocation
146              
147             package #
148             Foo;
149              
150             use Moose;
151             use MooseX::Types::FakeHash;
152              
153             has foo => (
154             isa => 'KeyWith[ ArrayRef ]'
155             is => 'rw',
156             required => 1,
157             );
158              
159             has bar => (
160             isa => 'ArrayRef[ KeyWith[ Str ] ]',
161             is => 'rw',
162             required => 1,
163             );
164              
165             ....
166              
167              
168             Foo->new(
169             foo => [ Hello => [] ]
170             bar => [
171             [ "Content-Type" => "text/plain" ],
172             [ "X-Zombies" => "0" ],
173             ],
174             );
175              
176             =head2 MooseX-Types style invocation
177              
178             package #
179             Foo;
180              
181             use Moose;
182             use MooseX::Types::FakeHash qw( :all );
183             use MooseX::Types::Moose qw( :all );
184              
185             has foo => (
186             isa => KeyWith[ ArrayRef ]
187             is => 'rw',
188             required => 1,
189             );
190              
191             has bar => (
192             isa => ArrayRef[ KeyWith[ Str ] ],
193             is => 'rw',
194             required => 1,
195             );
196              
197             ....
198              
199              
200             Foo->new(
201             foo => [ Hello => [] ]
202             bar => [
203             [ "Content-Type" => "text/plain" ],
204             [ "X-Zombies" => "0" ],
205             ],
206             );
207              
208             =head1 TYPES
209              
210             =head2 KeyWith
211              
212             =head2 KeyWith[ X ]
213              
214             A parameterizable type intended to simulate a singular key/value pair stored in an array.
215              
216             The keys is required to be of type C<Str>, while the value is the parameterized type.
217              
218             has bar ( isa => KeyWith[ Foo ] , ... );
219              
220             ...
221              
222             ->new(
223             bar => [ "Key" => $fooitem ] # [ Str, Foo ]
224             );
225              
226             =head2 FakeHash
227              
228             =head2 FakeHash[ X ]
229              
230             A parameterizable type intended to simulate the values of a HashRef, but stored in an ArrayRef instead
231             as an even number of key/values.
232              
233             The keys are required to be of type C<Str>, while the value is the parameterized type.
234              
235             has bar ( isa => FakeHash[ Foo ] , ... );
236              
237             ...
238              
239             ->new(
240             bar => [
241             "Key" => $fooitem,
242             "AnotherKey" => $baritem,
243             "YetAnotherKey" => $quuxitem,
244             ] # [ Str, Foo, Str, Foo, Str, Foo ]
245             );
246              
247             =head2 OrderedFakeHash
248              
249             =head2 OrderedFakeHash[ X ]
250              
251             A parameterizable type intended to simulate the values of a HashRef, but stored in an ArrayRef instead
252             as an array of L</KeyWith> items. This is much like a L</FakeHash>, but slightly different, in that the paring of the Key/Value is stricter,
253             and numerical-offset based lookup is simpler.
254              
255             [
256             [ "Key" => $value ],
257             [ "Key" => $value ],
258             ]
259              
260             In essence, OrderedFakeHash[ x ] is ShortHand for ArrayRef[ KeyWith[ x ] ].
261              
262             This makes it harder to convert to a native Perl 5 Hash, but somewhat easier to iterate pairwise.
263              
264             my $data = $object->orderedfakehashthing();
265             for my $pair ( @($data) ){
266             my ( $key, $value ) = @{ $pair };
267             ....
268             }
269              
270             The keys are required to be of type C<Str>, while the value is the parameterized type.
271              
272             has bar ( isa => OrderedFakeHash[ Foo ] , ... );
273              
274             ...
275              
276             ->new(
277             bar => [
278             [ "Key" => $fooitem ],
279             [ "AnotherKey" => $baritem ],
280             [ "YetAnotherKey" => $quuxitem ],
281             ] # [ [ Str, Foo ],[ Str, Foo ],[ Str, Foo ] ]
282             );
283              
284             =head1 AUTHOR
285              
286             Kent Fredric <kentnl@cpan.org>
287              
288             =head1 COPYRIGHT AND LICENSE
289              
290             This software is copyright (c) 2013 by Kent Fredric <kentnl@cpan.org>.
291              
292             This is free software; you can redistribute it and/or modify it under
293             the same terms as the Perl 5 programming language system itself.
294              
295             =cut