Filename | /Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Type/Tiny/Enum.pm |
Statements | Executed 2380 statements in 5.25ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
118 | 2 | 1 | 888µs | 909µs | _regexp (recurses: max depth 12, inclusive time 4.33ms) | Type::Tiny::Enum::_Trie::
37 | 4 | 3 | 513µs | 714µs | inline_check | Type::Tiny::Enum::
18 | 1 | 1 | 172µs | 172µs | add | Type::Tiny::Enum::_Trie::
44 | 1 | 1 | 133µs | 181µs | parent | Type::Tiny::Enum::
4 | 1 | 1 | 106µs | 314µs | new | Type::Tiny::Enum::
4 | 1 | 1 | 97µs | 1.18ms | handle | Type::Tiny::Enum::_Trie::
41 | 2 | 1 | 95µs | 95µs | _xs_encoding | Type::Tiny::Enum::
41 | 2 | 1 | 83µs | 1.27ms | _regexp | Type::Tiny::Enum::
41 | 2 | 1 | 56µs | 56µs | unique_values | Type::Tiny::Enum::
4 | 1 | 1 | 54µs | 2.30ms | _build_compiled_check | Type::Tiny::Enum::
21 | 6 | 3 | 52µs | 52µs | can_be_inlined | Type::Tiny::Enum::
1 | 1 | 1 | 32µs | 32µs | BEGIN@3 | Type::Tiny::Enum::
22 | 1 | 1 | 26µs | 26µs | has_parent | Type::Tiny::Enum::
100 | 1 | 1 | 21µs | 21µs | CORE:sort (opcode) | Type::Tiny::Enum::_Trie::
1 | 1 | 1 | 16µs | 25µs | BEGIN@4 | Type::Tiny::Enum::
1 | 1 | 1 | 13µs | 22µs | BEGIN@16 | Type::Tiny::Enum::
4 | 1 | 1 | 12µs | 12µs | CORE:sort (opcode) | Type::Tiny::Enum::
1 | 1 | 1 | 8µs | 39µs | BEGIN@5 | Type::Tiny::Enum::
1 | 1 | 1 | 8µs | 25µs | BEGIN@54 | Type::Tiny::Enum::
4 | 1 | 1 | 8µs | 8µs | _is_null_constraint | Type::Tiny::Enum::
4 | 1 | 1 | 6µs | 6µs | new | Type::Tiny::Enum::_Trie::
1 | 1 | 1 | 3µs | 3µs | BEGIN@17 | Type::Tiny::Enum::
1 | 1 | 1 | 2µs | 2µs | BEGIN@7 | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:185] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:21] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:315] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:316] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:396] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:79] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | __ANON__[:81] | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _build_constraint | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _build_display_name | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _croak | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _enum_order_hash | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _exporter_fail | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | _instantiate_moose_type | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | as_regexp | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | closest_match | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | constraint | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | exportables | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | has_sorter | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | is_word_safe | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | new_intersection | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | new_union | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | sorter | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | validate_explain | Type::Tiny::Enum::
0 | 0 | 0 | 0s | 0s | values | Type::Tiny::Enum::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Type::Tiny::Enum; | ||||
2 | |||||
3 | 2 | 117µs | 1 | 32µs | # spent 32µs within Type::Tiny::Enum::BEGIN@3 which was called:
# once (32µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 3 # spent 32µs making 1 call to Type::Tiny::Enum::BEGIN@3 |
4 | 2 | 46µs | 2 | 34µs | # spent 25µs (16+9) within Type::Tiny::Enum::BEGIN@4 which was called:
# once (16µs+9µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 4 # spent 25µs making 1 call to Type::Tiny::Enum::BEGIN@4
# spent 9µs making 1 call to strict::import |
5 | 2 | 41µs | 2 | 70µs | # spent 39µs (8+31) within Type::Tiny::Enum::BEGIN@5 which was called:
# once (8µs+31µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 5 # spent 39µs making 1 call to Type::Tiny::Enum::BEGIN@5
# spent 31µs making 1 call to warnings::import |
6 | |||||
7 | # spent 2µs within Type::Tiny::Enum::BEGIN@7 which was called:
# once (2µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 10 | ||||
8 | 1 | 0s | $Type::Tiny::Enum::AUTHORITY = 'cpan:TOBYINK'; | ||
9 | 1 | 3µs | $Type::Tiny::Enum::VERSION = '2.000001'; | ||
10 | 1 | 65µs | 1 | 2µs | } # spent 2µs making 1 call to Type::Tiny::Enum::BEGIN@7 |
11 | |||||
12 | 1 | 1µs | $Type::Tiny::Enum::VERSION =~ tr/_//d; | ||
13 | |||||
14 | sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak } | ||||
15 | |||||
16 | 3 | 35µs | 2 | 31µs | # spent 22µs (13+9) within Type::Tiny::Enum::BEGIN@16 which was called:
# once (13µs+9µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 16 # spent 22µs making 1 call to Type::Tiny::Enum::BEGIN@16
# spent 9µs making 1 call to UNIVERSAL::VERSION |
17 | 2 | 223µs | 1 | 3µs | # spent 3µs within Type::Tiny::Enum::BEGIN@17 which was called:
# once (3µs+0s) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 17 # spent 3µs making 1 call to Type::Tiny::Enum::BEGIN@17 |
18 | 1 | 12µs | our @ISA = qw( Type::Tiny Exporter::Tiny ); | ||
19 | |||||
20 | __PACKAGE__->_install_overloads( | ||||
21 | q[@{}] => sub { shift->values }, | ||||
22 | 1 | 7µs | 1 | 21µs | ); # spent 21µs making 1 call to Type::Tiny::_install_overloads |
23 | |||||
24 | sub _exporter_fail { | ||||
25 | my ( $class, $type_name, $values, $globals ) = @_; | ||||
26 | my $caller = $globals->{into}; | ||||
27 | my $type = $class->new( | ||||
28 | name => $type_name, | ||||
29 | values => [ @$values ], | ||||
30 | coercion => 1, | ||||
31 | ); | ||||
32 | $INC{'Type/Registry.pm'} | ||||
33 | ? 'Type::Registry'->for_class( $caller )->add_type( $type, $type_name ) | ||||
34 | : ( $Type::Registry::DELAYED{$caller}{$type_name} = $type ) | ||||
35 | unless( ref($caller) or $caller eq '-lexical' or $globals->{'lexical'} ); | ||||
36 | return map +( $_->{name} => $_->{code} ), @{ $type->exportables }; | ||||
37 | } | ||||
38 | |||||
39 | # spent 314µs (106+208) within Type::Tiny::Enum::new which was called 4 times, avg 78µs/call:
# 4 times (106µs+208µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 1054 of Types/Standard.pm, avg 78µs/call | ||||
40 | 4 | 1µs | my $proto = shift; | ||
41 | |||||
42 | 4 | 8µs | my %opts = ( @_ == 1 ) ? %{ $_[0] } : @_; | ||
43 | _croak | ||||
44 | "Enum type constraints cannot have a parent constraint passed to the constructor" | ||||
45 | 4 | 2µs | if exists $opts{parent}; | ||
46 | _croak | ||||
47 | "Enum type constraints cannot have a constraint coderef passed to the constructor" | ||||
48 | 4 | 2µs | if exists $opts{constraint}; | ||
49 | _croak | ||||
50 | "Enum type constraints cannot have a inlining coderef passed to the constructor" | ||||
51 | 4 | 0s | if exists $opts{inlined}; | ||
52 | 4 | 1µs | _croak "Need to supply list of values" unless exists $opts{values}; | ||
53 | |||||
54 | 2 | 2.23ms | 2 | 42µs | # spent 25µs (8+17) within Type::Tiny::Enum::BEGIN@54 which was called:
# once (8µs+17µs) by Types::Standard::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard.pm:1059] at line 54 # spent 25µs making 1 call to Type::Tiny::Enum::BEGIN@54
# spent 17µs making 1 call to warnings::unimport |
55 | $opts{values} = [ | ||||
56 | map "$_", | ||||
57 | 4 | 18µs | @{ ref $opts{values} eq 'ARRAY' ? $opts{values} : [ $opts{values} ] } | ||
58 | ]; | ||||
59 | |||||
60 | 4 | 1µs | my %tmp; | ||
61 | 4 | 15µs | undef $tmp{$_} for @{ $opts{values} }; | ||
62 | 4 | 30µs | 4 | 12µs | $opts{unique_values} = [ sort keys %tmp ]; # spent 12µs making 4 calls to Type::Tiny::Enum::CORE:sort, avg 3µs/call |
63 | |||||
64 | 4 | 7µs | 4 | 4µs | my $xs_encoding = _xs_encoding( $opts{unique_values} ); # spent 4µs making 4 calls to Type::Tiny::Enum::_xs_encoding, avg 1µs/call |
65 | 4 | 2µs | if ( defined $xs_encoding ) { | ||
66 | my $xsub = Type::Tiny::XS::get_coderef_for( $xs_encoding ); | ||||
67 | $opts{compiled_type_constraint} = $xsub if $xsub; | ||||
68 | } | ||||
69 | |||||
70 | 4 | 1µs | if ( defined $opts{coercion} and !ref $opts{coercion} and 1 eq $opts{coercion} ) | ||
71 | { | ||||
72 | delete $opts{coercion}; | ||||
73 | $opts{_build_coercion} = sub { | ||||
74 | require Types::Standard; | ||||
75 | my $c = shift; | ||||
76 | my $t = $c->type_constraint; | ||||
77 | $c->add_type_coercions( | ||||
78 | Types::Standard::Str(), | ||||
79 | sub { $t->closest_match( @_ ? $_[0] : $_ ) } | ||||
80 | ); | ||||
81 | }; | ||||
82 | } #/ if ( defined $opts{coercion...}) | ||||
83 | |||||
84 | 4 | 24µs | 4 | 192µs | return $proto->SUPER::new( %opts ); # spent 192µs making 4 calls to Type::Tiny::new, avg 48µs/call |
85 | } #/ sub new | ||||
86 | |||||
87 | sub new_union { | ||||
88 | my $proto = shift; | ||||
89 | my %opts = ( @_ == 1 ) ? %{ $_[0] } : @_; | ||||
90 | my @types = @{ delete $opts{type_constraints} }; | ||||
91 | my @values = map @$_, @types; | ||||
92 | $proto->new( %opts, values => \@values ); | ||||
93 | } | ||||
94 | |||||
95 | sub new_intersection { | ||||
96 | my $proto = shift; | ||||
97 | my %opts = ( @_ == 1 ) ? %{ $_[0] } : @_; | ||||
98 | my @types = @{ delete $opts{type_constraints} }; | ||||
99 | my %values; ++$values{$_} for map @$_, @types; | ||||
100 | my @values = sort grep $values{$_}==@types, keys %values; | ||||
101 | $proto->new( %opts, values => \@values ); | ||||
102 | } | ||||
103 | |||||
104 | sub values { $_[0]{values} } | ||||
105 | 41 | 163µs | sub unique_values { $_[0]{unique_values} } | ||
106 | sub constraint { $_[0]{constraint} ||= $_[0]->_build_constraint } | ||||
107 | |||||
108 | 4 | 7µs | # spent 8µs within Type::Tiny::Enum::_is_null_constraint which was called 4 times, avg 2µs/call:
# 4 times (8µs+0s) by Type::Tiny::_build_compiled_check at line 532 of Type/Tiny.pm, avg 2µs/call | ||
109 | |||||
110 | sub _build_display_name { | ||||
111 | my $self = shift; | ||||
112 | sprintf( "Enum[%s]", join q[,], @{ $self->unique_values } ); | ||||
113 | } | ||||
114 | |||||
115 | sub is_word_safe { | ||||
116 | my $self = shift; | ||||
117 | return not grep /\W/, @{ $self->unique_values }; | ||||
118 | } | ||||
119 | |||||
120 | sub exportables { | ||||
121 | my ( $self, $base_name ) = @_; | ||||
122 | if ( not $self->is_anon ) { | ||||
123 | $base_name ||= $self->name; | ||||
124 | } | ||||
125 | |||||
126 | my $exportables = $self->SUPER::exportables( $base_name ); | ||||
127 | |||||
128 | if ( $self->is_word_safe ) { | ||||
129 | require Eval::TypeTiny; | ||||
130 | require B; | ||||
131 | for my $value ( @{ $self->unique_values } ) { | ||||
132 | push @$exportables, { | ||||
133 | name => uc( sprintf '%s_%s', $base_name, $value ), | ||||
134 | tags => [ 'constants' ], | ||||
135 | code => Eval::TypeTiny::eval_closure( | ||||
136 | source => sprintf( 'sub () { %s }', B::perlstring($value) ), | ||||
137 | environment => {}, | ||||
138 | ), | ||||
139 | }; | ||||
140 | } | ||||
141 | } | ||||
142 | |||||
143 | return $exportables; | ||||
144 | } | ||||
145 | |||||
146 | { | ||||
147 | 1 | 0s | my $new_xs; | ||
148 | |||||
149 | # | ||||
150 | # Note the fallback code for older Type::Tiny::XS cannot be tested as | ||||
151 | # part of the coverage tests because they use the latest Type::Tiny::XS. | ||||
152 | # | ||||
153 | |||||
154 | sub _xs_encoding { | ||||
155 | 41 | 24µs | my $unique_values = shift; | ||
156 | |||||
157 | 41 | 101µs | return undef unless Type::Tiny::_USE_XS; | ||
158 | |||||
159 | return undef if @$unique_values > 50; # RT 121957 | ||||
160 | |||||
161 | $new_xs = eval { Type::Tiny::XS->VERSION( "0.020" ); 1 } ? 1 : 0 | ||||
162 | unless defined $new_xs; | ||||
163 | if ( $new_xs ) { | ||||
164 | require B; | ||||
165 | return sprintf( | ||||
166 | "Enum[%s]", | ||||
167 | join( ",", map B::perlstring( $_ ), @$unique_values ) | ||||
168 | ); | ||||
169 | } | ||||
170 | else { # uncoverable statement | ||||
171 | return undef if grep /\W/, @$unique_values; # uncoverable statement | ||||
172 | return sprintf( "Enum[%s]", join( ",", @$unique_values ) ); # uncoverable statement | ||||
173 | } # uncoverable statement | ||||
174 | } #/ sub _xs_encoding | ||||
175 | } | ||||
176 | |||||
177 | { | ||||
178 | 2 | 0s | my %cached; | ||
179 | |||||
180 | sub _build_constraint { | ||||
181 | my $self = shift; | ||||
182 | |||||
183 | my $regexp = $self->_regexp; | ||||
184 | return $cached{$regexp} if $cached{$regexp}; | ||||
185 | my $coderef = ( $cached{$regexp} = sub { defined and m{\A(?:$regexp)\z} } ); | ||||
186 | Scalar::Util::weaken( $cached{$regexp} ); | ||||
187 | return $coderef; | ||||
188 | } | ||||
189 | } | ||||
190 | |||||
191 | { | ||||
192 | 2 | 1µs | my %cached; | ||
193 | |||||
194 | # spent 2.30ms (54µs+2.25) within Type::Tiny::Enum::_build_compiled_check which was called 4 times, avg 576µs/call:
# 4 times (54µs+2.25ms) by Type::Tiny::compiled_check at line 437 of Type/Tiny.pm, avg 576µs/call | ||||
195 | 4 | 1µs | my $self = shift; | ||
196 | 4 | 5µs | 4 | 1.21ms | my $regexp = $self->_regexp; # spent 1.21ms making 4 calls to Type::Tiny::Enum::_regexp, avg 303µs/call |
197 | 4 | 4µs | return $cached{$regexp} if $cached{$regexp}; | ||
198 | 4 | 17µs | 4 | 1.03ms | my $coderef = ( $cached{$regexp} = $self->SUPER::_build_compiled_check( @_ ) ); # spent 1.03ms making 4 calls to Type::Tiny::_build_compiled_check, avg 258µs/call |
199 | 4 | 15µs | 4 | 5µs | Scalar::Util::weaken( $cached{$regexp} ); # spent 5µs making 4 calls to Scalar::Util::weaken, avg 1µs/call |
200 | 4 | 9µs | return $coderef; | ||
201 | } | ||||
202 | } | ||||
203 | |||||
204 | 1 | 0s | sub _regexp { | ||
205 | 41 | 13µs | my $self = shift; | ||
206 | 41 | 107µs | 8 | 1.19ms | $self->{_regexp} ||= 'Type::Tiny::Enum::_Trie'->handle( $self->unique_values ); # spent 1.18ms making 4 calls to Type::Tiny::Enum::_Trie::handle, avg 296µs/call
# spent 3µs making 4 calls to Type::Tiny::Enum::unique_values, avg 750ns/call |
207 | } | ||||
208 | |||||
209 | sub as_regexp { | ||||
210 | my $self = shift; | ||||
211 | |||||
212 | my $flags = @_ ? $_[0] : ''; | ||||
213 | unless ( defined $flags and $flags =~ /^[i]*$/ ) { | ||||
214 | _croak( | ||||
215 | "Unknown regexp flags: '$flags'; only 'i' currently accepted; stopped" ); | ||||
216 | } | ||||
217 | |||||
218 | my $regexp = $self->_regexp; | ||||
219 | $flags ? qr/\A(?:$regexp)\z/i : qr/\A(?:$regexp)\z/; | ||||
220 | } #/ sub as_regexp | ||||
221 | |||||
222 | # spent 52µs within Type::Tiny::Enum::can_be_inlined which was called 21 times, avg 2µs/call:
# 9 times (41µs+0s) by Type::Tiny::inline_assert at line 915 of Type/Tiny.pm, avg 5µs/call
# 4 times (5µs+0s) by Type::Tiny::_build_compiled_check at line 537 of Type/Tiny.pm, avg 1µs/call
# 3 times (1µs+0s) by Type::Tiny::_overload_coderef at line 203 of Type/Tiny.pm, avg 333ns/call
# 2 times (3µs+0s) by Types::Standard::Dict::__inline_generator at line 117 of Types/Standard/Dict.pm, avg 2µs/call
# 2 times (1µs+0s) by Types::Standard::Tuple::__inline_generator at line 103 of Types/Standard/Tuple.pm, avg 500ns/call
# once (1µs+0s) by Types::Standard::Dict::__coercion_generator at line 256 of Types/Standard/Dict.pm | ||||
223 | 21 | 53µs | !!1; | ||
224 | } | ||||
225 | |||||
226 | # spent 714µs (513+201) within Type::Tiny::Enum::inline_check which was called 37 times, avg 19µs/call:
# 16 times (217µs+89µs) by Types::Standard::Dict::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard/Dict.pm:161] at line 156 of Types/Standard/Dict.pm, avg 19µs/call
# 9 times (126µs+58µs) by Type::Tiny::inline_assert at line 915 of Type/Tiny.pm, avg 20µs/call
# 8 times (124µs+34µs) by Types::Standard::Tuple::__ANON__[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Types/Standard/Tuple.pm:164] at line 157 of Types/Standard/Tuple.pm, avg 20µs/call
# 4 times (46µs+20µs) by Type::Tiny::_build_compiled_check at line 537 of Type/Tiny.pm, avg 16µs/call | ||||
227 | 37 | 8µs | my $self = shift; | ||
228 | |||||
229 | 37 | 10µs | my $xsub; | ||
230 | 37 | 143µs | 74 | 144µs | if ( my $xs_encoding = _xs_encoding( $self->unique_values ) ) { # spent 91µs making 37 calls to Type::Tiny::Enum::_xs_encoding, avg 2µs/call
# spent 53µs making 37 calls to Type::Tiny::Enum::unique_values, avg 1µs/call |
231 | $xsub = Type::Tiny::XS::get_subname_for( $xs_encoding ); | ||||
232 | return "$xsub\($_[0]\)" if $xsub && !$Type::Tiny::AvoidCallbacks; | ||||
233 | } | ||||
234 | |||||
235 | 37 | 68µs | 37 | 57µs | my $regexp = $self->_regexp; # spent 57µs making 37 calls to Type::Tiny::Enum::_regexp, avg 2µs/call |
236 | 37 | 56µs | my $code = | ||
237 | $_[0] eq '$_' | ||||
238 | ? "(defined and !ref and m{\\A(?:$regexp)\\z})" | ||||
239 | : "(defined($_[0]) and !ref($_[0]) and $_[0] =~ m{\\A(?:$regexp)\\z})"; | ||||
240 | |||||
241 | 37 | 12µs | return "do { $Type::Tiny::SafePackage $code }" | ||
242 | if $Type::Tiny::AvoidCallbacks; | ||||
243 | 37 | 146µs | return $code; | ||
244 | } #/ sub inline_check | ||||
245 | |||||
246 | sub _instantiate_moose_type { | ||||
247 | my $self = shift; | ||||
248 | my %opts = @_; | ||||
249 | delete $opts{parent}; | ||||
250 | delete $opts{constraint}; | ||||
251 | delete $opts{inlined}; | ||||
252 | require Moose::Meta::TypeConstraint::Enum; | ||||
253 | return "Moose::Meta::TypeConstraint::Enum" | ||||
254 | ->new( %opts, values => $self->values ); | ||||
255 | } #/ sub _instantiate_moose_type | ||||
256 | |||||
257 | # spent 26µs within Type::Tiny::Enum::has_parent which was called 22 times, avg 1µs/call:
# 22 times (26µs+0s) by Type::Tiny::is_strictly_subtype_of at line 697 of Type/Tiny.pm, avg 1µs/call | ||||
258 | 22 | 50µs | !!1; | ||
259 | } | ||||
260 | |||||
261 | # spent 181µs (133+48) within Type::Tiny::Enum::parent which was called 44 times, avg 4µs/call:
# 44 times (133µs+48µs) by Type::Tiny::is_strictly_subtype_of at line 698 of Type/Tiny.pm, avg 4µs/call | ||||
262 | 44 | 35µs | require Types::Standard; | ||
263 | 44 | 112µs | 44 | 48µs | Types::Standard::Str(); # spent 48µs making 44 calls to Types::Standard::Str, avg 1µs/call |
264 | } | ||||
265 | |||||
266 | sub validate_explain { | ||||
267 | my $self = shift; | ||||
268 | my ( $value, $varname ) = @_; | ||||
269 | $varname = '$_' unless defined $varname; | ||||
270 | |||||
271 | return undef if $self->check( $value ); | ||||
272 | |||||
273 | require Type::Utils; | ||||
274 | !defined( $value ) | ||||
275 | ? [ | ||||
276 | sprintf( | ||||
277 | '"%s" requires that the value is defined', | ||||
278 | $self, | ||||
279 | ), | ||||
280 | ] | ||||
281 | : @$self < 13 ? [ | ||||
282 | sprintf( | ||||
283 | '"%s" requires that the value is equal to %s', | ||||
284 | $self, | ||||
285 | Type::Utils::english_list( \"or", map B::perlstring( $_ ), @$self ), | ||||
286 | ), | ||||
287 | ] | ||||
288 | : [ | ||||
289 | sprintf( | ||||
290 | '"%s" requires that the value is one of an enumerated list of strings', | ||||
291 | $self, | ||||
292 | ), | ||||
293 | ]; | ||||
294 | } #/ sub validate_explain | ||||
295 | |||||
296 | sub has_sorter { | ||||
297 | !!1; | ||||
298 | } | ||||
299 | |||||
300 | sub _enum_order_hash { | ||||
301 | my $self = shift; | ||||
302 | my %hash; | ||||
303 | my $i = 0; | ||||
304 | for my $value ( @{ $self->values } ) { | ||||
305 | next if exists $hash{$value}; | ||||
306 | $hash{$value} = $i++; | ||||
307 | } | ||||
308 | return %hash; | ||||
309 | } #/ sub _enum_order_hash | ||||
310 | |||||
311 | sub sorter { | ||||
312 | my $self = shift; | ||||
313 | my %hash = $self->_enum_order_hash; | ||||
314 | return [ | ||||
315 | sub { $_[0] <=> $_[1] }, | ||||
316 | sub { exists( $hash{ $_[0] } ) ? $hash{ $_[0] } : 2_100_000_000 }, | ||||
317 | ]; | ||||
318 | } | ||||
319 | |||||
320 | 1 | 0s | my $canon; | ||
321 | |||||
322 | sub closest_match { | ||||
323 | require Types::Standard; | ||||
324 | |||||
325 | my ( $self, $given ) = ( shift, @_ ); | ||||
326 | |||||
327 | return unless Types::Standard::is_Str $given; | ||||
328 | |||||
329 | return $given if $self->check( $given ); | ||||
330 | |||||
331 | $canon ||= eval( | ||||
332 | $] lt '5.016' | ||||
333 | ? q< sub { ( my $var = lc($_[0]) ) =~ s/(^\s+)|(\s+$)//g; $var } > | ||||
334 | : q< sub { CORE::fc($_[0]) =~ s/(^\s+)|(\s+$)//gr; } > | ||||
335 | ); | ||||
336 | |||||
337 | $self->{_lookups} ||= do { | ||||
338 | my %lookups; | ||||
339 | for ( @{ $self->values } ) { | ||||
340 | my $key = $canon->( $_ ); | ||||
341 | next if exists $lookups{$key}; | ||||
342 | $lookups{$key} = $_; | ||||
343 | } | ||||
344 | \%lookups; | ||||
345 | }; | ||||
346 | |||||
347 | my $cgiven = $canon->( $given ); | ||||
348 | return $self->{_lookups}{$cgiven} | ||||
349 | if $self->{_lookups}{$cgiven}; | ||||
350 | |||||
351 | my $best; | ||||
352 | VALUE: for my $possible ( @{ $self->values } ) { | ||||
353 | my $stem = substr( $possible, 0, length $cgiven ); | ||||
354 | if ( $cgiven eq $canon->( $stem ) ) { | ||||
355 | if ( defined( $best ) and length( $best ) >= length( $possible ) ) { | ||||
356 | next VALUE; | ||||
357 | } | ||||
358 | $best = $possible; | ||||
359 | } | ||||
360 | } | ||||
361 | |||||
362 | return $best if defined $best; | ||||
363 | |||||
364 | return $self->values->[$given] | ||||
365 | if Types::Standard::is_Int $given; | ||||
366 | |||||
367 | return $given; | ||||
368 | } #/ sub closest_match | ||||
369 | |||||
370 | push @Type::Tiny::CMP, sub { | ||||
371 | my $A = shift->find_constraining_type; | ||||
372 | my $B = shift->find_constraining_type; | ||||
373 | return Type::Tiny::CMP_UNKNOWN | ||||
374 | unless $A->isa( __PACKAGE__ ) && $B->isa( __PACKAGE__ ); | ||||
375 | |||||
376 | my %seen; | ||||
377 | for my $word ( @{ $A->unique_values } ) { | ||||
378 | $seen{$word} += 1; | ||||
379 | } | ||||
380 | for my $word ( @{ $B->unique_values } ) { | ||||
381 | $seen{$word} += 2; | ||||
382 | } | ||||
383 | |||||
384 | my $values = join( '', CORE::values %seen ); | ||||
385 | if ( $values =~ /^3*$/ ) { | ||||
386 | return Type::Tiny::CMP_EQUIVALENT; | ||||
387 | } | ||||
388 | elsif ( $values !~ /2/ ) { | ||||
389 | return Type::Tiny::CMP_SUPERTYPE; | ||||
390 | } | ||||
391 | elsif ( $values !~ /1/ ) { | ||||
392 | return Type::Tiny::CMP_SUBTYPE; | ||||
393 | } | ||||
394 | |||||
395 | return Type::Tiny::CMP_UNKNOWN; | ||||
396 | 1 | 2µs | }; | ||
397 | |||||
398 | package # stolen from Regexp::Trie | ||||
399 | Type::Tiny::Enum::_Trie; | ||||
400 | 4 | 11µs | # spent 6µs within Type::Tiny::Enum::_Trie::new which was called 4 times, avg 2µs/call:
# 4 times (6µs+0s) by Type::Tiny::Enum::_Trie::handle at line 444, avg 2µs/call | ||
401 | |||||
402 | # spent 172µs within Type::Tiny::Enum::_Trie::add which was called 18 times, avg 10µs/call:
# 18 times (172µs+0s) by Type::Tiny::Enum::_Trie::handle at line 445, avg 10µs/call | ||||
403 | 18 | 4µs | my $self = shift; | ||
404 | 18 | 3µs | my $str = shift; | ||
405 | 18 | 4µs | my $ref = $self; | ||
406 | 18 | 45µs | for my $char ( split //, $str ) { | ||
407 | 128 | 65µs | $ref->{$char} ||= {}; | ||
408 | 128 | 35µs | $ref = $ref->{$char}; | ||
409 | } | ||||
410 | 18 | 8µs | $ref->{''} = 1; # { '' => 1 } as terminator | ||
411 | 18 | 26µs | $self; | ||
412 | } #/ sub add | ||||
413 | |||||
414 | sub _regexp { | ||||
415 | 118 | 12µs | my $self = shift; | ||
416 | 118 | 61µs | return if $self->{''} and scalar keys %$self == 1; # terminator | ||
417 | 100 | 10µs | my ( @alt, @cc ); | ||
418 | 100 | 14µs | my $q = 0; | ||
419 | 100 | 257µs | 100 | 21µs | for my $char ( sort keys %$self ) { # spent 21µs making 100 calls to Type::Tiny::Enum::_Trie::CORE:sort, avg 210ns/call |
420 | 114 | 22µs | my $qchar = quotemeta $char; | ||
421 | 114 | 216µs | 114 | 0s | if ( ref $self->{$char} ) { # spent 4.33ms making 114 calls to Type::Tiny::Enum::_Trie::_regexp, avg 38µs/call, recursion: max depth 12, sum of overlapping time 4.33ms |
422 | if ( defined( my $recurse = _regexp( $self->{$char} ) ) ) { | ||||
423 | push @alt, $qchar . $recurse; | ||||
424 | } | ||||
425 | else { | ||||
426 | 18 | 9µs | push @cc, $qchar; | ||
427 | } | ||||
428 | } | ||||
429 | else { | ||||
430 | $q = 1; | ||||
431 | } | ||||
432 | } #/ for my $char ( sort keys...) | ||||
433 | 100 | 20µs | my $cconly = !@alt; | ||
434 | 100 | 16µs | @cc and push @alt, @cc == 1 ? $cc[0] : '[' . join( '', @cc ) . ']'; | ||
435 | 100 | 71µs | my $result = @alt == 1 ? $alt[0] : '(?:' . join( '|', @alt ) . ')'; | ||
436 | 100 | 13µs | $q and $result = $cconly ? "$result?" : "(?:$result)?"; | ||
437 | 100 | 192µs | return $result; | ||
438 | } #/ sub _regexp | ||||
439 | |||||
440 | # spent 1.18ms (97µs+1.09) within Type::Tiny::Enum::_Trie::handle which was called 4 times, avg 296µs/call:
# 4 times (97µs+1.09ms) by Type::Tiny::Enum::_regexp at line 206, avg 296µs/call | ||||
441 | 4 | 1µs | my $class = shift; | ||
442 | 4 | 2µs | my ( $vals ) = @_; | ||
443 | 4 | 0s | return '(?!)' unless @$vals; | ||
444 | 4 | 4µs | 4 | 6µs | my $self = $class->new; # spent 6µs making 4 calls to Type::Tiny::Enum::_Trie::new, avg 2µs/call |
445 | 4 | 17µs | 18 | 172µs | $self->add( $_ ) for @$vals; # spent 172µs making 18 calls to Type::Tiny::Enum::_Trie::add, avg 10µs/call |
446 | 4 | 51µs | 4 | 909µs | $self->_regexp; # spent 909µs making 4 calls to Type::Tiny::Enum::_Trie::_regexp, avg 227µs/call |
447 | } | ||||
448 | |||||
449 | 1 | 7µs | 1; | ||
450 | |||||
451 | __END__ | ||||
# spent 12µs within Type::Tiny::Enum::CORE:sort which was called 4 times, avg 3µs/call:
# 4 times (12µs+0s) by Type::Tiny::Enum::new at line 62, avg 3µs/call | |||||
# spent 21µs within Type::Tiny::Enum::_Trie::CORE:sort which was called 100 times, avg 210ns/call:
# 100 times (21µs+0s) by Type::Tiny::Enum::_Trie::_regexp at line 419, avg 210ns/call |