File Coverage

blib/lib/List/Objects/Types.pm
Criterion Covered Total %
statement 24 24 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 32 32 100.0


line stmt bran cond sub pod time code
1             package List::Objects::Types;
2             $List::Objects::Types::VERSION = '1.003002';
3 2     2   268859 use strict; use warnings;
  2     2   6  
  2         58  
  2         10  
  2         5  
  2         69  
4              
5 2     2   11 use List::Util ();
  2         3  
  2         43  
6              
7 2     2   9 use Type::Library -base;
  2         4  
  2         16  
8 2     2   2370 use Type::Utils -all;
  2         9585  
  2         20  
9 2     2   6269 use Types::Standard -types;
  2         5  
  2         12  
10 2     2   8239 use Types::TypeTiny ();
  2         4  
  2         37  
11              
12 2     2   1880 use List::Objects::WithUtils;
  2         6815  
  2         15  
13              
14              
15             declare ArrayObj =>
16             as ConsumerOf[ 'List::Objects::WithUtils::Role::Array' ];
17              
18             coerce ArrayObj =>
19             from ArrayRef() => via { array(@$_) };
20              
21              
22             declare ImmutableArray =>
23             as ArrayObj(),
24             where { $_->does('List::Objects::WithUtils::Role::Array::Immutable') },
25             inline_as {
26             (undef, qq[$_->does('List::Objects::WithUtils::Role::Array::Immutable')])
27             };
28              
29             coerce ImmutableArray =>
30             from ArrayRef() => via { immarray(@$_) },
31             from ArrayObj() => via { immarray($_->all) };
32              
33              
34             declare TypedArray =>
35             as ConsumerOf[ 'List::Objects::WithUtils::Role::Array::Typed' ],
36             constraint_generator => sub {
37             my $param = Types::TypeTiny::to_TypeTiny(shift);
38             sub { $_->type->is_a_type_of($param) }
39             },
40             coercion_generator => sub {
41             my ($parent, $child, $param) = @_;
42             my $c = Type::Coercion->new(type_constraint => $child);
43             if ($param->has_coercion) {
44             my $inner = $param->coercion;
45             $c->add_type_coercions(
46             ArrayRef() => sub { array_of($param, map {; $inner->coerce($_) } @$_) },
47             ArrayObj() => sub { array_of($param, map {; $inner->coerce($_) } $_->all) },
48             );
49             } else {
50             $c->add_type_coercions(
51             ArrayRef() => sub { array_of($param, @$_) },
52             ArrayObj() => sub { array_of($param, $_->all) },
53             );
54             }
55              
56             $c->freeze
57             };
58              
59             declare ImmutableTypedArray =>
60             as InstanceOf[ 'List::Objects::WithUtils::Array::Immutable::Typed' ],
61             constraint_generator => sub {
62             my $param = Types::TypeTiny::to_TypeTiny(shift);
63             sub { $_->type->is_a_type_of($param) }
64             },
65             coercion_generator => sub {
66             my ($parent, $child, $param) = @_;
67             my $c = Type::Coercion->new( type_constraint => $child );
68             if ($param->has_coercion) {
69             my $inner = $param->coercion;
70             $c->add_type_coercions(
71             ArrayRef() => sub {
72             immarray_of($param, map {; $inner->coerce($_) } @$_)
73             },
74             ArrayObj() => sub {
75             immarray_of($param, map {; $inner->coerce($_) } $_->all)
76             },
77             );
78             } else {
79             $c->add_type_coercions(
80             ArrayRef() => sub { immarray_of($param, @$_) },
81             ArrayObj() => sub { immarray_of($param, $_->all) },
82             );
83             }
84             };
85              
86             declare HashObj =>
87             as ConsumerOf[ 'List::Objects::WithUtils::Role::Hash' ];
88              
89             coerce HashObj =>
90             from HashRef() => via { hash(%$_) };
91              
92              
93             declare ImmutableHash =>
94             as HashObj(),
95             where { $_->does('List::Objects::WithUtils::Role::Hash::Immutable') },
96             inline_as {
97             (undef, qq[$_->does('List::Objects::WithUtils::Role::Hash::Immutable')])
98             };
99              
100             coerce ImmutableHash =>
101             from HashRef() => via { immhash(%$_) },
102             from HashObj() => via { immhash($_->export) };
103              
104              
105             declare InflatedHash =>
106             as InstanceOf['List::Objects::WithUtils::Hash::Inflated'],
107             constraint_generator => sub {
108             my @params = @_;
109             sub {
110             Scalar::Util::blessed $_
111             and not List::Util::first { !$_[0]->can($_) } @params
112             }
113             };
114              
115             coerce InflatedHash =>
116             from HashRef() => via { hash(%$_)->inflate },
117             from HashObj() => via { $_->inflate };
118              
119              
120             declare TypedHash =>
121             as ConsumerOf[ 'List::Objects::WithUtils::Role::Hash::Typed' ],
122             constraint_generator => sub {
123             my $param = Types::TypeTiny::to_TypeTiny(shift);
124             sub { $_->type->is_a_type_of($param) }
125             },
126             coercion_generator => sub {
127             my ($parent, $child, $param) = @_;
128             my $c = Type::Coercion->new(type_constraint => $child);
129             if ($param->has_coercion) {
130             my $inner = $param->coercion;
131             $c->add_type_coercions(
132             HashRef() => sub {
133             my %old = %$_; my %new;
134             @new{keys %old} = map {; $inner->coerce($_) } values %old;
135             hash_of($param, %new)
136             },
137             HashObj() => sub {
138             my %old = $_->export; my %new;
139             @new{keys %old} = map {; $inner->coerce($_) } values %old;
140             hash_of($param, %new)
141             },
142             );
143             } else {
144             $c->add_type_coercions(
145             HashRef() => sub { hash_of($param, %$_) },
146             HashObj() => sub { hash_of($param, $_->export) },
147             );
148             }
149              
150            
151             $c->freeze
152             };
153              
154              
155             declare ImmutableTypedHash =>
156             as InstanceOf[ 'List::Objects::WithUtils::Hash::Immutable::Typed' ],
157             constraint_generator => sub {
158             my $param = Types::TypeTiny::to_TypeTiny(shift);
159             sub { $_->type->is_a_type_of($param) }
160             },
161             coercion_generator => sub {
162             my ($parent, $child, $param) = @_;
163             my $c = Type::Coercion->new(type_constraint => $child);
164             if ($param->has_coercion) {
165             my $inner = $param->coercion;
166             $c->add_type_coercions(
167             HashRef() => sub {
168             my %old = %$_; my %new;
169             @new{keys %old} = map {; $inner->coerce($_) } values %old;
170             immhash_of($param, %new)
171             },
172             HashObj() => sub {
173             my %old = $_->export; my %new;
174             @new{keys %old} = map {; $inner->coerce($_) } values %old;
175             immhash_of($param, %new)
176             },
177             );
178             } else {
179             $c->add_type_coercions(
180             HashRef() => sub { immhash_of($param, %$_) },
181             HashObj() => sub { immhash_of($param, $_->export) },
182             );
183             }
184              
185            
186             $c->freeze
187             };
188              
189             1;
190              
191              
192             =pod
193              
194             =head1 NAME
195              
196             List::Objects::Types - Type::Tiny-based types for List::Objects::WithUtils
197              
198             =head1 SYNOPSIS
199              
200             package Foo;
201              
202             use List::Objects::Types -all;
203             use List::Objects::WithUtils;
204             use Moo 2; # version 2+ for better Type::Tiny support
205              
206             has my_array => (
207             is => 'ro',
208             isa => ArrayObj,
209             default => sub { array }
210             );
211              
212             has static_array => (
213             is => 'ro',
214             isa => ImmutableArray,
215             coerce => 1,
216             default => sub { [qw/ foo bar /] }
217             );
218              
219             has my_hash => (
220             is => 'ro',
221             isa => HashObj,
222             coerce => 1,
223             # Coercible from a plain HASH:
224             default => sub { +{} }
225             );
226              
227             use Types::Standard 'Int', 'Num';
228             has my_ints => (
229             is => 'ro',
230             # Nums added to this array_of(Int) are coerced to Ints:
231             isa => TypedArray[ Int->plus_coercions(Num, 'int($_)') ],
232             coerce => 1,
233             default => sub { [1, 2, 3.14] }
234             );
235              
236             =head1 DESCRIPTION
237              
238             A set of L-based types & coercions matching the list objects found
239             in L.
240              
241             =head3 ArrayObj
242              
243             An object that consumes L.
244              
245             Can be coerced from a plain ARRAY; a shallow copy is performed.
246              
247             =head3 HashObj
248              
249             An object that consumes L.
250              
251             Can be coerced from a plain HASH; a shallow copy is performed.
252              
253             =head3 ImmutableArray
254              
255             An object that consumes L.
256              
257             Can be coerced from a plain ARRAY or an L; a shallow copy is performed.
258              
259             =head3 TypedArray
260              
261             An object that consumes L.
262              
263             Not coercible.
264              
265             =head3 TypedArray[`a]
266              
267             TypedArray can be parameterized with another type constraint. For
268             example, the type constraint C<< TypedArray[Num] >> will accept
269             C<< array_of(Num, 1, 2, 3.14159) >>, and will also accept
270             C<< array_of(Int, 1, 2, 3) >> because C is a subtype of C.
271              
272             Can be coerced from a plain ARRAY or an L; a shallow copy is
273             performed. If the parameter also has a coercion, this will be applied
274             to each item in the new array.
275              
276             (The C directory that comes with this distribution contains some
277             examples of parameterized & coercible TypedArrays.)
278              
279             =head3 ImmutableTypedArray
280              
281             An object that isa L.
282              
283             Not coercible.
284              
285             =head3 ImmutableTypedArray[`a]
286              
287             ImmutableTypedArray can be parameterized with another type constraint, like
288             L.
289              
290             Can be coerced from a plain ARRAY or an L.
291              
292             =head3 TypedHash
293              
294             An object that consumes L.
295              
296             Not coercible.
297              
298             =head3 TypedHash[`a]
299              
300             TypedHash can be parameterized with another type constraint, like
301             L.
302              
303             Can be coerced from a plain HASH or a L. If the parameter also has a
304             coercion, this will be applied to each value in the new hash.
305              
306             =head3 ImmutableTypedHash
307              
308             An object that isa L.
309              
310             Not coercible.
311              
312             =head3 ImmutableTypedHash[`a]
313              
314             ImmutableTypedHash can be parameterized with another type constraint, like
315             L.
316              
317             Can be coerced from a plain HASH or an L.
318              
319             =head3 InflatedHash
320              
321             An object that isa L.
322              
323             Can be coerced from a plain HASH or an L.
324              
325             (Available from v1.2.1)
326              
327             =head3 InflatedHash[`a]
328              
329             InflatedHash can be parameterized with a list of methods expected to be
330             available.
331              
332             (Available from v1.3.1)
333              
334             =head2 SEE ALSO
335              
336             L for integration with L class-building sugar.
337              
338             L for more on the relevant list objects.
339              
340             L for more on type methods & overloads.
341              
342             L for a set of useful base types.
343              
344             L for details on importing types.
345              
346             =head1 AUTHOR
347              
348             Jon Portnoy with significant contributions from Toby
349             Inkster (CPAN: TOBYINK)
350              
351             =cut