File Coverage

blib/lib/Salvation/TC/Meta/Type/Union.pm
Criterion Covered Total %
statement 55 59 93.2
branch 13 18 72.2
condition 4 12 33.3
subroutine 11 11 100.0
pod 4 4 100.0
total 87 104 83.6


line stmt bran cond sub pod time code
1             package Salvation::TC::Meta::Type::Union;
2              
3             =head1 NAME
4              
5             Salvation::TC::Meta::Type::Union - Класс для объединённых типов
6              
7             =cut
8              
9 4     4   12 use strict;
  4         15  
  4         117  
10 4     4   14 use warnings;
  4         6  
  4         73  
11 4     4   13 use boolean;
  4         14  
  4         16  
12              
13 4     4   201 use base 'Salvation::TC::Meta::Type';
  4         4  
  4         262  
14              
15 4     4   21 use Scalar::Util 'blessed';
  4         4  
  4         153  
16 4     4   1376 use Salvation::TC::Exception::WrongType::TC ();
  4         8  
  4         1518  
17              
18             =head1 METHODS
19              
20             =cut
21              
22             =head2 new()
23              
24             =cut
25              
26             sub new {
27              
28 9     9 1 19 my ( $proto, %args ) = @_;
29              
30 9 50       22 die( 'Type union metaclass must have types list' ) unless( defined $args{ 'types' } );
31 9 50       25 die( 'Types list must be an ArrayRef' ) if( ref( $args{ 'types' } ) ne 'ARRAY' );
32              
33 9         9 foreach ( @{ $args{ 'types' } } ) {
  9         21  
34              
35 19 50 33     148 unless( defined $_ && blessed $_ && $_ -> isa( 'Salvation::TC::Meta::Type' ) ) {
      33        
36              
37 0         0 die( 'Types list must be an ArrayRef[Salvation::TC::Meta::Type]' );
38             }
39             }
40              
41 9         28 $args{ 'validator' } = $proto -> build_validator( @args{ 'name', 'types' } );
42              
43 9         45 return $proto -> SUPER::new( %args );
44             }
45              
46             =head2 types()
47              
48             =cut
49              
50             sub types {
51              
52 3     3 1 4 my ( $self ) = @_;
53              
54 3         7 return $self -> { 'types' };
55             }
56              
57             =head2 build_validator( Str $name, ArrayRef[Salvation::TC::Meta::Type] $types )
58              
59             =cut
60              
61             sub build_validator {
62              
63 9     9 1 15 my ( $self, $name, $types ) = @_;
64              
65             return sub {
66              
67 9     9   10 my ( $value ) = @_;
68              
69 9         11 my @errors = ();
70              
71 9         14 foreach my $type ( @$types ) {
72              
73 17         75 my $check_passed = true;
74              
75 17         43 eval { $type -> check( $value ) };
  17         52  
76              
77 17 100       59 if( $@ ) {
78              
79 11 50 33     65 if( blessed( $@ ) && $@ -> isa( 'Salvation::TC::Exception::WrongType' ) ) {
80              
81 11 100       26 push( @errors, Salvation::TC::Exception::WrongType::TC -> new(
82             type => $type -> name(), value => $value,
83             ( $@ -> isa( 'Salvation::TC::Exception::WrongType::TC' ) ? (
84             prev => $@,
85             ) : () )
86             ) );
87              
88 11         23 $check_passed = false;
89              
90             } else {
91              
92 0         0 die( $@ );
93             }
94             }
95              
96 17 100       59 return true if( $check_passed );
97             }
98              
99             Salvation::TC::Exception::WrongType::TC -> throw(
100 3         24 type => $name, value => $value, prev => \@errors,
101             );
102 9         45 };
103             }
104              
105             =head2 coerce( Any $value )
106              
107             =cut
108              
109             sub coerce {
110              
111 3     3 1 6 my ( $self, $value ) = @_;
112              
113 3         3 foreach my $type ( @{ $self -> types() } ) {
  3         5  
114              
115             {
116 6         6 local $SIG{ '__DIE__' } = 'DEFAULT';
  6         15  
117              
118 6         7 eval {
119 6         13 my $new_value = $type -> coerce( $value );
120              
121 6         11 $type -> check( $new_value ); # true или die
122              
123 3         15 $value = $new_value;
124             };
125             }
126              
127 6 100       14 if( $@ ) {
128              
129 3 50 33     16 if( blessed( $@ ) && $@ -> isa( 'Salvation::TC::Exception::WrongType' ) ) {
130              
131 3         3 next;
132              
133             } else {
134              
135 0         0 die( $@ );
136             }
137             }
138              
139 3         19 return $value; # Moose возвращает либо старое, либо приведённое значение
140             }
141              
142 0           return $value; # Moose возвращает либо старое, либо приведённое значение
143             }
144              
145              
146             1;
147              
148             __END__