File Coverage

blib/lib/MooseX/Types/Moose/MutualCoercion.pm
Criterion Covered Total %
statement 27 27 100.0
branch 1 2 50.0
condition n/a
subroutine 9 9 100.0
pod n/a
total 37 38 97.3


line stmt bran cond sub pod time code
1             package MooseX::Types::Moose::MutualCoercion;
2              
3              
4             # ****************************************************************
5             # perl dependency
6             # ****************************************************************
7              
8 1     1   599853 use 5.008_001;
  1         5  
  1         46  
9              
10              
11             # ****************************************************************
12             # pragma(ta)
13             # ****************************************************************
14              
15             # Moose turns strict/warnings pragmata on,
16             # however, kwalitee scorer cannot detect such mechanism.
17             # (Perl::Critic can it, with equivalent_modules parameter)
18 1     1   6 use strict;
  1         2  
  1         35  
19 1     1   6 use warnings;
  1         6  
  1         54  
20              
21              
22             # ****************************************************************
23             # MOP dependency(-ies)
24             # ****************************************************************
25              
26 1         10 use MooseX::Types -declare => [qw(
27             NumToInt
28             ScalarRefToStr ArrayRefToLines
29             StrToClassName
30             StrToScalarRef
31             StrToArrayRef LinesToArrayRef
32             HashRefToArrayRef HashKeysToArrayRef HashValuesToArrayRef
33             OddArrayRef EvenArrayRef
34             ArrayRefToHashRef ArrayRefToHashKeys
35             ArrayRefToRegexpRef
36 1     1   1021 )];
  1         48364  
37 1         13 use MooseX::Types::Common::String qw(
38             NonEmptyStr
39 1     1   13133 );
  1         119142  
40 1         7 use MooseX::Types::Moose qw(
41             Str
42             Num
43             Int
44             ClassName
45             RoleName
46             Ref
47             ScalarRef
48             ArrayRef
49             HashRef
50             RegexpRef
51 1     1   3573 );
  1         3  
52              
53              
54             # ****************************************************************
55             # general dependency(-ies)
56             # ****************************************************************
57              
58 1         121 use Class::Load qw(
59             load_class
60             is_class_loaded
61 1     1   7272 );
  1         3  
62              
63              
64             # ****************************************************************
65             # public class variable(s)
66             # ****************************************************************
67              
68             our $VERSION = "0.04";
69              
70              
71             # ****************************************************************
72             # namespace cleaner
73             # ****************************************************************
74              
75 1     1   47 use namespace::clean;
  1         3  
  1         13  
76              
77              
78             # ****************************************************************
79             # subtype(s) and coercion(s)
80             # ****************************************************************
81              
82             # ================================================================
83             # to Int
84             # ================================================================
85              
86             subtype NumToInt,
87             as Int;
88              
89             coerce NumToInt,
90             from Num,
91             via {
92             int $_;
93             };
94              
95             # ================================================================
96             # to Str
97             # ================================================================
98              
99             foreach my $type (
100             ScalarRefToStr, ArrayRefToLines,
101             ) {
102             subtype $type,
103             as Str;
104             }
105              
106             coerce ScalarRefToStr,
107             from ScalarRef[Str],
108             via {
109             $$_;
110             };
111              
112             coerce ArrayRefToLines,
113             from ArrayRef[Str],
114             via {
115             ( join $/, @$_ ) . $/;
116             };
117              
118             # ================================================================
119             # to ClassName
120             # ================================================================
121              
122             subtype StrToClassName,
123             as ClassName;
124              
125             coerce StrToClassName,
126             from NonEmptyStr,
127             via {
128             _ensure_class_loaded($_);
129             };
130              
131             # ================================================================
132             # to ScalarRef
133             # ================================================================
134              
135             subtype StrToScalarRef,
136             as ScalarRef[Str];
137              
138             coerce StrToScalarRef,
139             from Str,
140             via {
141             \do{ $_ };
142             };
143              
144             # ================================================================
145             # to ArrayRef
146             # ================================================================
147              
148             foreach my $type (
149             StrToArrayRef, LinesToArrayRef,
150             HashRefToArrayRef, HashKeysToArrayRef, HashValuesToArrayRef,
151             ) {
152             subtype $type,
153             as ArrayRef;
154             }
155              
156             coerce StrToArrayRef,
157             from Str,
158             via {
159             [ $_ ];
160             };
161              
162             coerce LinesToArrayRef,
163             from Str,
164             via {
165             ( my $new_line = $/ ) =~ s{(.)}{[$1]}xmsg;
166             [ split m{ (?<= $new_line ) }xms, $_ ];
167             };
168              
169             coerce HashRefToArrayRef,
170             from HashRef,
171             via {
172             my $hashref = $_;
173             [
174             map {
175             $_, $hashref->{$_};
176             } sort keys %$hashref
177             ];
178             };
179              
180             coerce HashKeysToArrayRef,
181             from HashRef,
182             via {
183             [ sort keys %$_ ];
184             };
185              
186             coerce HashValuesToArrayRef,
187             from HashRef,
188             via {
189             my $hashref = $_;
190             [
191             map {
192             $hashref->{$_};
193             } sort keys %$hashref
194             ];
195             };
196              
197             subtype OddArrayRef,
198             as ArrayRef,
199             where {
200             scalar @$_ % 2;
201             };
202              
203             subtype EvenArrayRef,
204             as ArrayRef,
205             where {
206             ! scalar @$_ % 2;
207             };
208              
209             foreach my $type (OddArrayRef, EvenArrayRef) {
210             coerce $type,
211             from ArrayRef,
212             via {
213             push @$_, undef;
214             $_;
215             };
216             }
217              
218             # ================================================================
219             # to HashRef
220             # ================================================================
221              
222             foreach my $type (
223             ArrayRefToHashRef, ArrayRefToHashKeys,
224             ) {
225             subtype $type,
226             as HashRef;
227             }
228              
229             coerce ArrayRefToHashRef,
230             from EvenArrayRef,
231             via {
232             my %hash = @$_; # Note: "{ @$_ }" is invalid (need "return").
233             \%hash;
234             };
235              
236             coerce ArrayRefToHashKeys,
237             from ArrayRef,
238             via {
239             my %hash;
240             @hash{@$_} = ();
241             \%hash;
242             };
243              
244             # ================================================================
245             # to RegexpRef
246             # ================================================================
247              
248             subtype ArrayRefToRegexpRef,
249             as RegexpRef;
250              
251             coerce ArrayRefToRegexpRef,
252             from ArrayRef,
253             via {
254             eval {
255             require Regexp::Assemble;
256             };
257             if ($@) {
258             my $pattern_string = join '|', @$_;
259             qr{$pattern_string};
260             }
261             else {
262             my $regexp = Regexp::Assemble->new;
263             foreach my $pattern (@$_) {
264             $regexp->add($pattern);
265             }
266             $regexp->re;
267             }
268             };
269              
270              
271             # ****************************************************************
272             # subroutine(s)
273             # ****************************************************************
274              
275             sub _ensure_class_loaded {
276 1     1   3 my $class = shift;
277              
278 1 50       14 load_class($class)
279             unless is_class_loaded($class);
280              
281 1         12629 return $class;
282             }
283              
284              
285             # ****************************************************************
286             # return true
287             # ****************************************************************
288              
289             1;
290             __END__
291              
292              
293             # ****************************************************************
294             # POD
295             # ****************************************************************
296              
297             =pod
298              
299             =head1 NAME
300              
301             MooseX::Types::Moose::MutualCoercion - Mutual coercions for common type constraints of Moose
302              
303             =head1 VERSION
304              
305             This document describes
306             L<MooseX::Types::Moose::MutualCoercion|MooseX::Types::Moose::MutualCoercion>
307             version C<0.04>.
308              
309             =head1 SYNOPSIS
310              
311             {
312             package Foo;
313             use Moose;
314             use MooseX::Types::Moose::MutualCoercion
315             qw(StrToArrayRef ArrayRefToHashKeys);
316             has 'thingies' =>
317             (is => 'rw', isa => StrToArrayRef, coerce => 1);
318             has 'lookup_table' =>
319             (is => 'rw', isa => ArrayRefToHashKeys, coerce => 1);
320             1;
321             }
322              
323             my $foo = Foo->new( thingies => 'bar' );
324             print $foo->thingies->[0]; # 'bar'
325              
326             $foo->lookup_table( [qw(baz qux)] );
327             print 'eureka!' # 'eureka!'
328             if grep {
329             exists $foo->lookup_table->{$_};
330             } qw(foo bar baz);
331              
332             =head1 TRANSLATIONS
333              
334             Much of the
335             L<MooseX::Types::Moose::MutualCoercion|MooseX::Types::Moose::MutualCoercion>
336             documentation has been translated into other language(s).
337              
338             =over 4
339              
340             =item en: English
341              
342             L<MooseX::Types::Moose::MutualCoercion|MooseX::Types::Moose::MutualCoercion>
343             (This document)
344              
345             =item ja: Japanese
346              
347             L<MooseX::Types::Moose::MutualCoercion::JA|MooseX::Types::Moose::MutualCoercion::JA>
348              
349             =back
350              
351             =head1 DESCRIPTION
352              
353             This module packages several
354             L<Moose::Util::TypeConstraints|Moose::Util::TypeConstraints> with coercions,
355             designed to mutually coerce with the built-in and common types known to
356             L<Moose|Moose>.
357              
358             =head1 CONSTRAINTS AND COERCIONS
359              
360             B<NOTE>: These constraints are not exported by default
361             but you can request them in an import list like this:
362              
363             use MooseX::Types::Moose::MutualCoercion qw(NumToInt ScalarRefToStr);
364              
365             =head2 To C<< Int >>
366              
367             =over 4
368              
369             =item C<< NumToInt >>
370              
371             A subtype of C<< Int >>.
372             If you turned C<< coerce >> on, C<< Num >> will become integer.
373             For example, C<< 3.14 >> will be converted into C<< 3 >>.
374              
375             =back
376              
377             =head2 To C<< Str >>
378              
379             =over 4
380              
381             =item C<< ScalarRefToStr >>
382              
383             A subtype of C<< Str >>.
384             If you turned C<< coerce >> on,
385             C<< ScalarRef[Str] >> will become dereferenced string.
386             For example, C<< \do{'foo'} >> will be converted into C<< foo >>.
387              
388             =item C<< ArrayRefToLines >>
389              
390             A subtype of C<< Str >>.
391             If you turned C<< coerce >> on,
392             all elements of C<< ArrayRef[Str] >> will be joined by C<< $/ >>.
393             For example, C<< [qw(foo bar baz)] >>
394             will be converted into C<< foo\nbar\nbaz\n >>.
395              
396             B<NOTE>: Also adds C<< $/ >> to the last element.
397              
398             =back
399              
400             =head2 To C<< ClassName >>
401              
402             =over 4
403              
404             =item C<< StrToClassName >>
405              
406             B<CAVEAT>: This type constraint and coercion is B<DEPRECATED>.
407             Please use L<MooseX::Types::LoadableClass's LodableClass
408             |MooseX::Types::LoadableClass/LodableClass> instead of it.
409             In addition, L<MooseX::Types::LoadableClass|MooseX::Types::LoadableClass>
410             also has L<LodableRole|MooseX::Types::LoadableClass/LoadableRole>.
411              
412             A subtype of C<< ClassName >>.
413             If you turned C<< coerce >> on, C<< NonEmptyStr >>, provided by
414             L<MooseX::Types::Common::String|MooseX::Types::Common::String>,
415             will be treated as a class name.
416             When it is not already loaded, it will be loaded by
417             L<< Class::Load::load_class()|Class::Load >>.
418              
419             =back
420              
421             =head2 To C<< ScalarRef >>
422              
423             =over 4
424              
425             =item C<< StrToScalarRef >>
426              
427             A subtype of C<< ScalarRef[Str] >>.
428             If you turned C<< coerce >> on, C<< Str >> will be referenced.
429             For example, C<< foo >> will be converted into C<< \do{'foo'} >>.
430              
431             =back
432              
433             =head2 To C<< ArrayRef >>
434              
435             =over 4
436              
437             =item C<< StrToArrayRef >>
438              
439             A subtype of C<< ArrayRef >>.
440             If you turned C<< coerce >> on,
441             C<< Str >> will be assigned for the first element of an array reference.
442             For example, C<< foo >> will be converted into C<< [qw(foo)] >>.
443              
444             =item C<< LinesToArrayRef >>
445              
446             A subtype of C<< ArrayRef >>.
447             If you turned C<< coerce >> on, C<< Str >> will be split by C<< $/ >>
448             and will be assigned for each element of an array reference.
449             For example, C<< foo\nbar\nbaz\n >>
450             will be converted into C<< ["foo\n", "bar\n", "baz\n"] >>.
451              
452             B<NOTE>: C<< $/ >> was not removed.
453              
454             =item C<< HashRefToArrayRef >>
455              
456             A subtype of C<< ArrayRef >>.
457             If you turned C<< coerce >> on,
458             C<< HashRef >> will be flattened as an array reference.
459             For example, C<< {foo => 0, bar => 1} >>
460             will be converted into C<< [qw(bar 1 foo 0)] >>.
461              
462             B<NOTE>: Order of keys/values is the same as lexically sorted keys.
463              
464             =item C<< HashKeysToArrayRef >>
465              
466             A subtype of C<< ArrayRef >>.
467             If you turned C<< coerce >> on,
468             list of lexically sorted keys of C<< HashRef >> will become an array reference.
469             For example, C<< {foo => 0, bar => 1} >>
470             will be converted into C<< [qw(bar foo)] >>.
471              
472             =item C<< HashValuesToArrayRef >>
473              
474             A subtype of C<< ArrayRef >>.
475             If you turned C<< coerce >> on,
476             list of values of C<< HashRef >> will become an array reference.
477             For example, C<< {foo => 0, bar => 1} >>
478             will be converted into C<< [qw(1 0)] >>.
479              
480             B<NOTE>: Order of values is the same as lexically sorted keys.
481              
482             =item C<< OddArrayRef >>
483              
484             A subtype of C<< ArrayRef >>, that must have odd elements.
485             If you turned C<< coerce >> on, C<< ArrayRef >>, that has even elements,
486             will be pushed C<< undef >> as the last element.
487             For example, C<< [qw(foo bar)] >>
488             will be converted into C<< [qw(foo bar), undef] >>.
489              
490             =item C<< EvenArrayRef >>
491              
492             A subtype of C<< ArrayRef >>, that must have even elements.
493             If you turned C<< coerce >> on, C<< ArrayRef >>, that has odd elements,
494             will be pushed C<< undef >> as the last element.
495             For example, C<< [qw(foo)] >>
496             will be converted into C<< [qw(foo), undef] >>.
497              
498             =back
499              
500             =head2 To C<< HashRef >>
501              
502             =over 4
503              
504             =item C<< ArrayRefToHashRef >>
505              
506             A subtype of C<< HashRef >>.
507             If you turned C<< coerce >> on,
508             all elements of C<< EvenArrayRef >> will be substituted for a hash reference.
509             For example, C<< [qw(foo 0 bar 1)] >>
510             will be converted into C<< {foo => 0, bar => 1} >>.
511              
512             =item C<< ArrayRefToHashKeys >>
513              
514             A subtype of C<< HashRef >>.
515             If you turned C<< coerce >> on,
516             all elements of C<< ArrayRef >> will be substituted
517             for keys of a hash reference.
518             For example, C<< [qw(foo bar baz)] >>
519             will be converted into C<< {foo => undef, bar => undef, baz => undef} >>.
520              
521             =back
522              
523             =head2 To C<< RegexpRef >>
524              
525             =over 4
526              
527             =item C<< ArrayRefToRegexpRef >>
528              
529             A subtype of C<< RegexpRef >>.
530             If you turned C<< coerce >> on, all elements of C<< ArrayRef >>
531             will be joined with C<< | >> (the meta character for alternation)
532             and will become a regular expression reference.
533             For example, C<< [qw(foo bar baz)] >>
534             will be converted into C<< qr{foo|bar|baz} >>.
535              
536             B<NOTE>: If L<Regexp::Assemble|Regexp::Assemble> can be loaded dynamically,
537             namely at runtime, a regular expression reference
538             will be built with this module.
539             For example, C<< [qw(foo bar baz)] >>
540             will be converted into C<< qr{(?:ba[rz]|foo)} >>.
541              
542             =back
543              
544             =head1 SEE ALSO
545              
546             =over 4
547              
548             =item *
549              
550             L<Moose::Manual::Types|Moose::Manual::Types>
551              
552             =item *
553              
554             L<MooseX::Types|MooseX::Types>
555              
556             =item *
557              
558             L<MooseX::Types::Moose|MooseX::Types::Moose>
559              
560             =item *
561              
562             L<MooseX::Types::LoadableClass|MooseX::Types::LoadableClass>
563              
564             =item *
565              
566             L<MooseX::Types::Common|MooseX::Types::Common>
567              
568             =item *
569              
570             About special variable C<< $/ >> (C<< $RS >>, C<< $INPUT_RECORD_SEPARATOR >>).
571              
572             L<perlvar|perlvar>
573              
574             =back
575              
576             =head1 INCOMPATIBILITIES
577              
578             None reported.
579              
580             =head1 BUGS AND LIMITATIONS
581              
582             No bugs have been reported.
583              
584             =head2 Making suggestions and reporting bugs
585              
586             Please report any found bugs, feature requests, and ideas for improvements
587             to C<< <bug-moosex-types-moose-mutualcoercion at rt.cpan.org> >>,
588             or through the web interface
589             at L<http://rt.cpan.org/Public/Bug/Report.html?Queue=MooseX-Types-Moose-MutualCoercion>.
590             I will be notified, and then you'll automatically be notified of progress
591             on your bugs/requests as I make changes.
592              
593             When reporting bugs, if possible,
594             please add as small a sample as you can make of the code
595             that produces the bug.
596             And of course, suggestions and patches are welcome.
597              
598             =head1 SUPPORT
599              
600             You can find documentation for this module with the C<perldoc> command.
601              
602             % perldoc MooseX::Types::Moose::MutualCoercion
603              
604             You can also find the Japanese edition of documentation for this module
605             with the C<perldocjp> command from L<Pod::PerldocJp|Pod::PerldocJp>.
606              
607             % perldocjp MooseX::Types::Moose::MutualCoercion::JA
608              
609             You can also look for information at:
610              
611             =over 4
612              
613             =item RT: CPAN's request tracker
614              
615             L<http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Types-Moose-MutualCoercion>
616              
617             =item AnnoCPAN: Annotated CPAN documentation
618              
619             L<http://annocpan.org/dist/MooseX-Types-Moose-MutualCoercion>
620              
621             =item Search CPAN
622              
623             L<http://search.cpan.org/dist/MooseX-Types-Moose-MutualCoercion>
624              
625             =item CPAN Ratings
626              
627             L<http://cpanratings.perl.org/dist/MooseX-Types-Moose-MutualCoercion>
628              
629             =back
630              
631             =head1 VERSION CONTROL
632              
633             This module is maintained using I<Git>.
634             You can get the latest version from
635             L<git://github.com/gardejo/p5-moosex-types-moose-mutualcoercion.git>.
636              
637             =head1 TO DO
638              
639             =over 4
640              
641             =item *
642              
643             More tests
644              
645             =back
646              
647             =head1 AUTHOR
648              
649             =over 4
650              
651             =item MORIYA Masaki, alias Gardejo
652              
653             C<< <moriya at cpan dot org> >>,
654             L<http://gardejo.org/>
655              
656             =back
657              
658             =head1 COPYRIGHT AND LICENSE
659              
660             Copyright (c) 2010 MORIYA Masaki, alias Gardejo
661              
662             This library is free software;
663             you can redistribute it and/or modify it under the same terms as Perl itself.
664             See L<perlgpl|perlgpl> and L<perlartistic|perlartistic>.
665              
666             The full text of the license can be found in the F<LICENSE> file
667             included with this distribution.
668              
669             =cut