File Coverage

blib/lib/List/Objects/Types.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


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