File Coverage

blib/lib/Venus/Assert.pm
Criterion Covered Total %
statement 368 418 88.0
branch 154 230 66.9
condition 42 67 62.6
subroutine 119 136 87.5
pod 51 55 92.7
total 734 906 81.0


line stmt bran cond sub pod time code
1             package Venus::Assert;
2              
3 12     12   305 use 5.018;
  12         61  
4              
5 12     12   73 use strict;
  12         44  
  12         293  
6 12     12   57 use warnings;
  12         29  
  12         444  
7              
8 12     12   76 use Venus::Class 'attr', 'base', 'with';
  12         26  
  12         114  
9              
10 12     12   7609 use Venus::Match;
  12         41  
  12         104  
11 12     12   92 use Venus::Type;
  12         38  
  12         166  
12              
13             base 'Venus::Kind::Utility';
14              
15             with 'Venus::Role::Buildable';
16              
17             use overload (
18 0     0   0 '&{}' => sub{$_[0]->validator},
19 12         129 fallback => 1,
20 12     12   81 );
  12         30  
21              
22             # ATTRIBUTES
23              
24             attr 'expects';
25             attr 'message';
26             attr 'name';
27              
28             # BUILDERS
29              
30             sub build_arg {
31 301     301 0 734 my ($self, $name) = @_;
32              
33             return {
34 301         1209 name => $name,
35             };
36             }
37              
38             sub build_self {
39 368     368 0 776 my ($self, $data) = @_;
40              
41 368 100       1218 if (!$self->name) {
42 67         175 $self->name('Unknown')
43             }
44              
45 368 50       1148 if (!$self->message) {
46 368         885 $self->message('Type assertion (%s) failed: received (%s), expected (%s)');
47             }
48              
49 368 50       1294 if (!$self->expects) {
50 368         995 $self->expects([])
51             }
52              
53 368         1511 $self->conditions;
54              
55 368         658 return $self;
56             }
57              
58             # METHODS
59              
60             sub any {
61 101     101 1 188 my ($self) = @_;
62              
63 101     10   221 $self->constraints->when(sub{true})->then(sub{true});
  10         30  
  10         23  
64              
65 101         334 return $self;
66             }
67              
68             sub accept {
69 631     631 1 1237 my ($self, $name, @args) = @_;
70              
71 631 50       1150 if (!$name) {
72 0         0 return $self;
73             }
74 631 100       2180 if ($self->can($name)) {
75 627         1569 return $self->$name(@args);
76             }
77             else {
78 4         21 return $self->identity($name, @args);
79             }
80             }
81              
82             sub array {
83 7     7 1 17 my ($self, @code) = @_;
84              
85 7 50   5   52 $self->constraint('array', @code ? @code : sub{true});
  5         20  
86              
87 7         33 return $self;
88             }
89              
90             sub arrayref {
91 1     1 1 5 my ($self, @code) = @_;
92              
93 1         6 return $self->array(@code);
94             }
95              
96             sub attributes {
97 3     3 1 12 my ($self, @pairs) = @_;
98              
99             $self->object(sub{
100 6     6   13 my $check = 0;
101 6         15 my $value = $_->value;
102 6 50       19 return false if @pairs % 2;
103 6         28 for (my $i = 0; $i < @pairs;) {
104 8         38 my ($key, $data) = (map $pairs[$_], $i++, $i++);
105 8 50       26 my ($match, @args) = (ref $data) ? (@{$data}) : ($data);
  0         0  
106 8 100 100     60 $check++ if $value->can($key)
107             && $self->new->do($match, @args)->check($value->$key);
108             }
109 6 100       35 ((@pairs / 2) == $check) ? true : false
110 3         29 });
111              
112 3         31 return $self;
113             }
114              
115             sub assertion {
116 0     0 1 0 my ($self) = @_;
117              
118 0         0 my $assert = $self->SUPER::assertion;
119              
120 0         0 $assert->clear->expression('string');
121              
122 0         0 return $assert;
123             }
124              
125             sub boolean {
126 91     91 1 174 my ($self, @code) = @_;
127              
128 91 50   3   408 $self->constraint('boolean', @code ? @code : sub{true});
  3         9  
129              
130 91         339 return $self;
131             }
132              
133             sub check {
134 509     509 1 1148 my ($self, $data) = @_;
135              
136 509         1710 my $value = Venus::Type->new(value => $data);
137              
138 509     202   2748 my @args = (value => $value, on_none => sub{false});
  202         664  
139              
140 509         1424 return $self->constraints->renew(@args)->result;
141             }
142              
143             sub checker {
144 1     1 1 4 my ($self, $data) = @_;
145              
146 1 50       7 $self->expression($data) if $data;
147              
148 1         15 return $self->defer('check');
149             }
150              
151             sub clear {
152 93     93 1 165 my ($self) = @_;
153              
154 93         177 $self->constraints->clear;
155 93         241 $self->coercions->clear;
156              
157 93         299 return $self;
158             }
159              
160             sub code {
161 13     13 1 37 my ($self, @code) = @_;
162              
163 13 50   20   97 $self->constraint('code', @code ? @code : sub{true});
  20         81  
164              
165 13         100 return $self;
166             }
167              
168             sub coderef {
169 3     3 1 14 my ($self, @code) = @_;
170              
171 3         18 return $self->code(@code);
172             }
173              
174             sub coerce {
175 67     67 1 174 my ($self, $data) = @_;
176              
177 67         324 my $value = Venus::Type->new(value => $data);
178              
179 67     58   388 my @args = (value => $value, on_none => sub{$data});
  58         173  
180              
181 67         223 return $self->coercions->renew(@args)->result;
182             }
183              
184             sub coercion {
185 12     12 1 34 my ($self, $type, $code) = @_;
186              
187 12         45 $self->coercions->when('coded', $type)->then($code);
188              
189 12         268 return $self;
190             }
191              
192             sub coercions {
193 174     174 1 463 my ($self) = @_;
194              
195 174         557 my $match = Venus::Match->new;
196              
197 174 50 66     1181 return $self->{coercions} ||= $match if ref $self;
198              
199 0         0 return $match;
200             }
201              
202             sub conditions {
203 368     368 1 4825 my ($self) = @_;
204              
205 368         578 return $self;
206             }
207              
208             sub constraint {
209 587     587 1 1482 my ($self, $type, $code) = @_;
210              
211 587         1160 $self->constraints->when('coded', $type)->then($code);
212              
213 587         1249 return $self;
214             }
215              
216             sub constraints {
217 1341     1341 1 2214 my ($self) = @_;
218              
219 1341         3770 my $match = Venus::Match->new;
220              
221 1341 50 66     9128 return $self->{constraints} ||= $match if ref $self;
222              
223 0         0 return $match;
224             }
225              
226             sub consumes {
227 1     1 0 6 my ($self, $role) = @_;
228              
229 1     0   9 my $where = $self->constraint('object', sub{true})->constraints->where;
  0         0  
230              
231 1     2   8 $where->when(sub{$_->value->DOES($role)})->then(sub{true});
  2         9  
  1         6  
232              
233 1         14 return $self;
234             }
235              
236             sub defined {
237 1     1 1 5 my ($self, @code) = @_;
238              
239 5     5   25 $self->constraints->when(sub{CORE::defined($_->value)})
240 1 50   4   5 ->then(@code ? @code : sub{true});
  4         14  
241              
242 1         11 return $self;
243             }
244              
245             sub either {
246 317     317 1 682 my ($self, @data) = @_;
247              
248 317         823 for (my $i = 0; $i < @data; $i++) {
249 623 100       1536 my ($match, @args) = (ref $data[$i]) ? (@{$data[$i]}) : ($data[$i]);
  127         362  
250 623         1514 $self->accept($match, @args);
251             }
252              
253 317         878 return $self;
254             }
255              
256             sub enum {
257 1     1 1 5 my ($self, @data) = @_;
258              
259 1         3 for my $item (@data) {
260 26 50   26   52 $self->constraints->when(sub{CORE::defined($_->value) && $_->value eq $item})
261 4     4   10 ->then(sub{true});
  4         13  
262             }
263              
264 1         12 return $self;
265             }
266              
267             sub expression {
268 196     196 1 416 my ($self, $data) = @_;
269              
270 196 50       448 return $self if !$data;
271              
272 196         1773 $data =
273             $data =~ s/\s*\n+\s*/ /gr =~ s/^\s+|\s+$//gr =~ s/\[\s+/[/gr =~ s/\s+\]/]/gr;
274              
275 196         704 $self->expects([$data]);
276              
277 196         648 my @parsed = $self->parse($data);
278              
279 196         744 $self->either(@parsed);
280              
281 196         662 return $self;
282             }
283              
284             sub float {
285 122     122 1 230 my ($self, @code) = @_;
286              
287 122 50   19   608 $self->constraint('float', @code ? @code : sub{true});
  19         77  
288              
289 122         471 return $self;
290             }
291              
292             sub format {
293 4     4 1 14 my ($self, $name, @code) = @_;
294              
295 4 50       15 if (!$name) {
296 0         0 return $self;
297             }
298 4 50       53 if (lc($name) eq 'array') {
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
    50          
299 0 0   0   0 return $self->coercion('array', @code ? (@code) : sub{$_->value});
  0         0  
300             }
301             elsif (lc($name) eq 'boolean') {
302 0 0   0   0 return $self->coercion('boolean', @code ? (@code) : sub{$_->value});
  0         0  
303             }
304             elsif (lc($name) eq 'code') {
305 0 0   0   0 return $self->coercion('code', @code ? (@code) : sub{$_->value});
  0         0  
306             }
307             elsif (lc($name) eq 'float') {
308 1 50   0   10 return $self->coercion('float', @code ? (@code) : sub{$_->value});
  0         0  
309             }
310             elsif (lc($name) eq 'hash') {
311 0 0   0   0 return $self->coercion('hash', @code ? (@code) : sub{$_->value});
  0         0  
312             }
313             elsif (lc($name) eq 'number') {
314 1 50   0   6 return $self->coercion('number', @code ? (@code) : sub{$_->value});
  0         0  
315             }
316             elsif (lc($name) eq 'object') {
317 1 50   0   6 return $self->coercion('object', @code ? (@code) : sub{$_->value});
  0         0  
318             }
319             elsif (lc($name) eq 'regexp') {
320 0 0   0   0 return $self->coercion('regexp', @code ? (@code) : sub{$_->value});
  0         0  
321             }
322             elsif (lc($name) eq 'scalar') {
323 0 0   0   0 return $self->coercion('scalar', @code ? (@code) : sub{$_->value});
  0         0  
324             }
325             elsif (lc($name) eq 'string') {
326 0 0   0   0 return $self->coercion('string', @code ? (@code) : sub{$_->value});
  0         0  
327             }
328             elsif (lc($name) eq 'undef') {
329 0 0   0   0 return $self->coercion('undef', @code ? (@code) : sub{$_->value});
  0         0  
330             }
331             else {
332             return $self->coercion('object', sub {
333 2 50   2   11 UNIVERSAL::isa($_->value, $name)
    100          
334             ? (@code ? $code[0]->($_->value) : $_->value)
335             : $_->value;
336 1         9 });
337             }
338             }
339              
340             sub hash {
341 2     2 1 8 my ($self, @code) = @_;
342              
343 2 50   2   26 $self->constraint('hash', @code ? @code : sub{true});
  2         15  
344              
345 2         24 return $self;
346             }
347              
348             sub hashkeys {
349 29     29 1 79 my ($self, @pairs) = @_;
350              
351             $self->constraints->when(sub{
352             CORE::defined($_->value) && UNIVERSAL::isa($_->value, 'HASH')
353 36 100 66 36   85 && (keys %{$_->value}) > 0
  32         73  
354             })->then(sub{
355 21     21   43 my $check = 0;
356 21         54 my $value = $_->value;
357 21 50       68 return false if @pairs % 2;
358 21         72 for (my $i = 0; $i < @pairs;) {
359 32         158 my ($key, $data) = (map $pairs[$_], $i++, $i++);
360 32 100       140 my ($match, @args) = (ref $data) ? (@{$data}) : ($data);
  14         41  
361 32 100       107 $check++ if $self->new->do($match, @args)->check($value->{$key});
362             }
363 21 100       125 ((@pairs / 2) == $check) ? true : false
364 29         85 });
365              
366 29         151 return $self;
367             }
368              
369             sub hashref {
370 1     1 1 4 my ($self, @code) = @_;
371              
372 1         5 return $self->hash(@code);
373             }
374              
375             sub identity {
376 5     5 1 15 my ($self, $name) = @_;
377              
378 5 100   7   32 $self->constraint('object', sub {$_->value->isa($name) ? true : false});
  7         40  
379              
380 5         40 return $self;
381             }
382              
383             sub inherits {
384 1     1 1 3 my ($self, $name) = @_;
385              
386 1 100   2   8 $self->constraint('object', sub {$_->value->isa($name) ? true : false});
  2         12  
387              
388 1         21 return $self;
389             }
390              
391             sub integrates {
392 1     1 1 3 my ($self, $name) = @_;
393              
394             $self->constraint('object', sub {
395 2 50   2   12 $_->value->can('does') ? ($_->value->does($name) ? true : false) : false
    100          
396 1         10 });
397              
398 1         14 return $self;
399             }
400              
401             sub maybe {
402 6     6 1 24 my ($self, $match, @args) = @_;
403              
404 6 50       31 $self->$match(@args) if $match;
405 6         22 $self->undef;
406              
407 6         22 return $self;
408             }
409              
410             sub number {
411 142     142 1 331 my ($self, @code) = @_;
412              
413 142 100   32   760 $self->constraint('number', @code ? @code : sub{true});
  32         155  
414              
415 142         625 return $self;
416             }
417              
418             sub object {
419 7     7 1 23 my ($self, @code) = @_;
420              
421 7 100   3   55 $self->constraint('object', @code ? @code : sub{true});
  3         12  
422              
423 7         47 return $self;
424             }
425              
426             sub package {
427 1     1 1 5 my ($self) = @_;
428              
429 1     0   6 my $where = $self->constraint('string', sub{true})->constraints->where;
  0         0  
430              
431 3     3   12 $where->when(sub{$_->value =~ /^[A-Z](?:(?:\w|::)*[a-zA-Z0-9])?$/})->then(sub{
432 3     3   1131 require Venus::Space;
433              
434 3         11 Venus::Space->new($_->value)->loaded
435 1         9 });
436              
437 1         11 return $self;
438             }
439              
440             sub parse {
441 220     220 1 490 my ($self, $expr) = @_;
442              
443 220   100     496 $expr ||= '';
444              
445 220         1611 $expr =
446             $expr =~ s/\s*\n+\s*/ /gr =~ s/^\s+|\s+$//gr =~ s/\[\s+/[/gr =~ s/\s+\]/]/gr;
447              
448 220         524 return _type_parse($expr);
449             }
450              
451             sub received {
452 31     31 0 84 my ($self, $data) = @_;
453              
454 31         145 require Scalar::Util;
455              
456 31 100       114 if (!defined $data) {
457 9         27 return '';
458             }
459              
460 22         76 my $blessed = Scalar::Util::blessed($data);
461 22   33     102 my $isvenus = $blessed && $data->isa('Venus::Core') && $data->can('does');
462              
463 22 100 66     130 if (!$blessed && !ref $data) {
464 13         38 return $data;
465             }
466 9 50 33     32 if ($blessed && ref($data) eq 'Regexp') {
467 0         0 return "$data";
468             }
469 9 50 33     30 if ($isvenus && $data->does('Venus::Role::Explainable')) {
470 0     0   0 return $self->dump(sub{$data->explain});
  0         0  
471             }
472 9 50 33     41 if ($isvenus && $data->does('Venus::Role::Valuable')) {
473 0     0   0 return $self->dump(sub{$data->value});
  0         0  
474             }
475 9 50 33     30 if ($isvenus && $data->does('Venus::Role::Dumpable')) {
476 0         0 return $data->dump;
477             }
478 9 50 33     33 if ($blessed && overload::Method($data, '""')) {
479 0         0 return "$data";
480             }
481 9 50 33     33 if ($blessed && $data->can('as_string')) {
482 0         0 return $data->as_string;
483             }
484 9 50 33     28 if ($blessed && $data->can('to_string')) {
485 0         0 return $data->to_string;
486             }
487 9 50 33     36 if ($blessed && $data->isa('Venus::Kind')) {
488 0         0 return $data->stringified;
489             }
490             else {
491 9     9   88 return $self->dump(sub{$data});
  9         60  
492             }
493             }
494              
495             sub reference {
496 1     1 1 4 my ($self, @code) = @_;
497              
498             $self->constraints
499 7 50   7   20 ->when(sub{CORE::defined($_->value) && ref($_->value)})
500 1 50   4   6 ->then(@code ? @code : sub{true});
  4         14  
501              
502 1         12 return $self;
503             }
504              
505             sub regexp {
506 1     1 1 5 my ($self, @code) = @_;
507              
508 1 50   1   11 $self->constraint('regexp', @code ? @code : sub{true});
  1         17  
509              
510 1         12 return $self;
511             }
512              
513             sub render {
514 23     23 1 56 my ($self, $into, $data) = @_;
515              
516 23         71 return _type_render($into, $data);
517             }
518              
519             sub routines {
520 1     1 1 7 my ($self, @data) = @_;
521              
522             $self->object->constraints->then(sub{
523 2     2   9 my $value = $_->value;
524 2 100       40 (@data == grep $value->can($_), @data) ? true : false
525 1         7 });
526              
527 1         12 return $self;
528             }
529              
530             sub scalar {
531 2     2 1 7 my ($self, @code) = @_;
532              
533 2 50   2   22 $self->constraint('scalar', @code ? @code : sub{true});
  2         12  
534              
535 2         23 return $self;
536             }
537              
538             sub scalarref {
539 1     1 1 4 my ($self, @code) = @_;
540              
541 1         6 return $self->scalar(@code);
542             }
543              
544             sub string {
545 161     161 1 348 my ($self, @code) = @_;
546              
547 161 50   99   962 $self->constraint('string', @code ? @code : sub{true});
  99         326  
548              
549 161         652 return $self;
550             }
551              
552             sub tuple {
553 1     1 1 4 my ($self, @data) = @_;
554              
555             $self->constraints->when(sub{
556             CORE::defined($_->value) && CORE::ref($_->value) eq 'ARRAY'
557 10 100 66 10   24 && @data == @{$_->value}
  6         15  
558             })->then(sub{
559 5     5   9 my $check = 0;
560 5         12 my $value = $_->value;
561 5 50       15 return false if @data != @$value;
562 5         14 for (my $i = 0; $i < @data; $i++) {
563 15 100       45 my ($match, @args) = (ref $data[$i]) ? (@{$data[$i]}) : ($data[$i]);
  5         15  
564 15 100       39 $check++ if $self->new->do($match, @args)->check($value->[$i]);
565             }
566 5 100       21 (@data == $check) ? true : false
567 1         6 });
568              
569 1         13 return $self;
570             }
571              
572             sub undef {
573 7     7 1 17 my ($self, @code) = @_;
574              
575 7 50   3   49 $self->constraint('undef', @code ? @code : sub{true});
  3         18  
576              
577 7         29 return $self;
578             }
579              
580             sub validate {
581 135     135 1 301 my ($self, $data) = @_;
582              
583 135         381 my $valid = $self->check($data);
584              
585 135 100       743 return $data if $valid;
586              
587 30         375 return $self->error({throw => 'error_on_validate', value => $data});
588             }
589              
590             sub validator {
591 1     1 1 4 my ($self, $data) = @_;
592              
593 1 50       9 $self->expression($data) if $data;
594              
595 1         7 return $self->defer('validate');
596             }
597              
598             sub value {
599 3     3 1 11 my ($self, @code) = @_;
600              
601             $self->constraints
602 9 50   9   28 ->when(sub{CORE::defined($_->value) && !ref($_->value)})
603 3 50   6   16 ->then(@code ? @code : sub{true});
  6         19  
604              
605 3         20 return $self;
606             }
607              
608             sub within {
609 6     6 1 26 my ($self, $type, @next) = @_;
610              
611 6 50       23 if (!$type) {
612 0         0 return $self;
613             }
614              
615 6         18 my $where = $self->new;
616              
617 6 100 100     67 if (lc($type) eq 'hash' || lc($type) eq 'hashref') {
    50 66        
618             $self->constraints->when(sub{
619             CORE::defined($_->value) && UNIVERSAL::isa($_->value, 'HASH')
620 28 100 100 28   72 && (keys %{$_->value}) > 0
  20         43  
621             })->then(sub{
622 16     16   36 my $value = $_->value;
623 16 50       104 UNIVERSAL::isa($value, 'HASH')
624             && CORE::values(%$value) == grep $where->check($_), CORE::values(%$value)
625 3         12 });
626             }
627             elsif (lc($type) eq 'array' || lc($type) eq 'arrayref') {
628             $self->constraints->when(sub{
629             CORE::defined($_->value) && UNIVERSAL::isa($_->value, 'ARRAY')
630 21 100 100 21   70 && @{$_->value} > 0
  12         27  
631             })->then(sub{
632 9     9   23 my $value = $_->value;
633 9 50       54 UNIVERSAL::isa($value, 'ARRAY')
634             && @$value == grep $where->check($_), @$value
635 3         13 });
636             }
637             else {
638 0         0 $self->error({throw => 'error_on_within', type => $type, args => [@next]});
639             }
640              
641 6 100       55 $where->accept(map +(ref($_) ? @$_ : $_), $next[0]) if @next;
    100          
642              
643 6         55 return $where;
644             }
645              
646             sub yesno {
647 1     1 1 6 my ($self, @code) = @_;
648              
649             $self->constraints->when(sub{
650 8 100   8   20 CORE::defined($_->value) && $_->value =~ /^(?:1|y(?:es)?|0|n(?:o)?)$/i
651 1 50   6   6 })->then(@code ? @code : sub{true});
  6         18  
652              
653 1         15 return $self;
654             }
655              
656             # ERRORS
657              
658             sub error_on_validate {
659 31     31 1 84 my ($self, $data) = @_;
660              
661 31         152 require Venus::Type;
662              
663 31         235 my $legend = {
664             array => 'arrayref',
665             code => 'coderef',
666             hash => 'hashref',
667             regexp => 'regexpref',
668             scalar => 'scalarref',
669             scalar => 'scalarref',
670             };
671              
672 31         87 my $value = $data->{value};
673              
674 31         115 my $identified = Venus::Type->new(value => $value)->identify;
675 31   66     121 my $identity = $legend->{lc($identified)} || lc($identified);
676              
677 31   100     115 my $expected = (join(' OR ', @{$self->expects})) || 'indescribable constraints';
678 31         135 my $received = $self->received($value);
679              
680 31         136 my $message = join(' ', sprintf($self->message, $self->name, $identity, $expected),
681             join("\n\n", "Received:", $received, ''));
682              
683 31         174 my $stash = {
684             identity => $identity,
685             variable => $value,
686             };
687              
688 31         131 my $result = {
689             name => 'on.validate',
690             raise => true,
691             stash => $stash,
692             message => $message,
693             };
694              
695 31         192 return $result;
696             }
697              
698             sub error_on_within {
699 1     1 1 3 my ($self, $data) = @_;
700              
701 1         3 my $message = 'Invalid type ("{{type}}") provided to the "within" method';
702              
703             my $stash = {
704             self => $self,
705             type => $data->{type},
706             args => $data->{args},
707 1         5 };
708              
709 1         4 my $result = {
710             name => 'on.within',
711             raise => true,
712             stash => $stash,
713             message => $message,
714             };
715              
716 1         3 return $result;
717             }
718              
719             # ROUTINES
720              
721             sub _type_parse {
722 483     483   1055 my @items = _type_parse_pipes(@_);
723              
724 483         1082 my $either = @items > 1;
725              
726 483         1227 @items = map _type_parse_nested($_), @items;
727              
728 483 100 100     3438 return wantarray && !$either ? @items : [$either ? ("either") : (), @items];
    100          
729             }
730              
731             sub _type_parse_lists {
732 133     133   263 my @items = @_;
733              
734 133         208 my $r0 = '[\"\'\[\]]';
735 133         188 my $r1 = '[^\"\'\[\]]';
736 133         200 my $r2 = _type_subexpr_type_2();
737 133         264 my $r3 = _type_subexpr_delimiter();
738              
739             return (
740             grep length,
741 133         212 map {split/,\s*(?=(?:$r1*$r0$r1*$r0)*$r1*$)(${r2}(?:${r3}[^,]*)?)?/}
  133         1737  
742             @items
743             );
744             }
745              
746             sub _type_parse_nested {
747 825     825   1652 my ($expr) = @_;
748              
749 825 100       1322 return ($expr) if $expr !~ _type_regexp(_type_subexpr_type_2());
750              
751 66         215 my @items = ($expr);
752              
753 66         347 @items = ($expr =~ /^(\w+)\s*\[\s*(.*)\s*\]+$/g);
754              
755 66         222 @items = map _type_parse_lists($_), @items;
756              
757 66 100       154 @items = map +(
758 261         427 $_ =~ qr/^@{[_type_subexpr_type_2()]},.*$/ ? _type_parse_lists($_) : $_
759             ),
760             @items;
761              
762 66         140 @items = map {s/^["']+|["']+$//gr} @items;
  263         1066  
763              
764 66         214 @items = map _type_parse($_), @items;
765              
766 66 100       285 return (@items > 1 ? [@items] : @items);
767             }
768              
769             sub _type_parse_pipes {
770 818     818   1459 my ($expr) = @_;
771              
772 818         1109 my @items;
773              
774             # i.e. tuple[number, string] | tuple[string, number]
775 818 100       1483 if
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
776             (
777             _type_regexp_eval(
778             $expr, _type_regexp(_type_subexpr_type_2(), _type_subexpr_type_2())
779             )
780             )
781             {
782 3         13 @items = map _type_parse_tuples($_),
783             _type_regexp_eval($expr,
784             _type_regexp_groups(_type_subexpr_type_2(), _type_subexpr_type_2()));
785             }
786             # i.e. string | tuple[number, string]
787             elsif
788             (
789             _type_regexp_eval($expr,
790             _type_regexp(_type_subexpr_type_1(), _type_subexpr_type_2()))
791             )
792             {
793 4         17 @items = map _type_parse_tuples($_),
794             _type_regexp_eval($expr,
795             _type_regexp_groups(_type_subexpr_type_1(), _type_subexpr_type_2()));
796             }
797             # i.e. tuple[number, string] | string
798             elsif
799             (
800             _type_regexp_eval($expr,
801             _type_regexp(_type_subexpr_type_2(), _type_subexpr_type_1()))
802             )
803             {
804 3         20 @items = map _type_parse_tuples($_),
805             _type_regexp_eval($expr,
806             _type_regexp_groups(_type_subexpr_type_2(), _type_subexpr_type_1()));
807             }
808             # special condition: i.e. tuple[number, string]
809             elsif
810             (
811             _type_regexp_eval($expr, _type_regexp(_type_subexpr_type_2()))
812             )
813             {
814 49         149 @items = ($expr);
815             }
816             # i.e. "..." | tuple[number, string]
817             elsif
818             (
819             _type_regexp_eval($expr,
820             _type_regexp(_type_subexpr_type_3(), _type_subexpr_type_2()))
821             )
822             {
823 4         30 @items = _type_regexp_eval($expr,
824             _type_regexp_groups(_type_subexpr_type_3(), _type_subexpr_type_2()));
825 4         16 @items = (_type_parse_pipes($items[0]), _type_parse_tuples($items[1]));
826             }
827             # i.e. tuple[number, string] | "..."
828             elsif
829             (
830             _type_regexp_eval($expr,
831             _type_regexp(_type_subexpr_type_2(), _type_subexpr_type_3()))
832             )
833             {
834 3         10 @items = _type_regexp_eval($expr,
835             _type_regexp_groups(_type_subexpr_type_2(), _type_subexpr_type_3()));
836 3         21 @items = (_type_parse_tuples($items[0]), _type_parse_pipes($items[1]));
837             }
838             # i.e. Package::Name | "..."
839             elsif
840             (
841             _type_regexp_eval($expr,
842             _type_regexp(_type_subexpr_type_4(), _type_subexpr_type_3()))
843             )
844             {
845 325         721 @items = _type_regexp_eval($expr,
846             _type_regexp_groups(_type_subexpr_type_4(), _type_subexpr_type_3()));
847 325         1253 @items = ($items[0], _type_parse_pipes($items[1]));
848             }
849             # i.e. "..." | Package::Name
850             elsif
851             (
852             _type_regexp_eval($expr,
853             _type_regexp(_type_subexpr_type_3(), _type_subexpr_type_4()))
854             )
855             {
856 0         0 @items = _type_regexp_eval($expr,
857             _type_regexp_groups(_type_subexpr_type_3(), _type_subexpr_type_4()));
858 0         0 @items = (_type_parse_pipes($items[0]), $items[1]);
859             }
860             # i.e. string | "..."
861             elsif
862             (
863             _type_regexp_eval($expr,
864             _type_regexp(_type_subexpr_type_1(), _type_subexpr_type_3()))
865             )
866             {
867 0         0 @items = _type_regexp_eval($expr,
868             _type_regexp_groups(_type_subexpr_type_1(), _type_subexpr_type_3()));
869 0         0 @items = ($items[0], _type_parse_pipes($items[1]));
870             }
871             # i.e. "..." | string
872             elsif
873             (
874             _type_regexp_eval($expr,
875             _type_regexp(_type_subexpr_type_3(), _type_subexpr_type_1()))
876             )
877             {
878 0         0 @items = _type_regexp_eval($expr,
879             _type_regexp_groups(_type_subexpr_type_3(), _type_subexpr_type_1()));
880 0         0 @items = (_type_parse_pipes($items[0]), $items[1]);
881             }
882             # i.e. "..." | "..."
883             elsif
884             (
885             _type_regexp_eval($expr,
886             _type_regexp(_type_subexpr_type_3(), _type_subexpr_type_3()))
887             )
888             {
889 0         0 @items = map _type_parse_pipes($_),
890             _type_regexp_eval($expr,
891             _type_regexp_groups(_type_subexpr_type_3(), _type_subexpr_type_3()));
892             }
893             else {
894 427         1066 @items = ($expr);
895             }
896              
897 818         7935 return (@items);
898             }
899              
900             sub _type_parse_tuples {
901 27 100   27   71 map +(scalar(_type_regexp_eval($_,
902             _type_regexp(_type_subexpr_type_2(), _type_subexpr_type_2())))
903             ? (_type_parse_pipes($_))
904             : ($_)), @_
905             }
906              
907             sub _type_regexp {
908 8078     8078   10411 qr/^@{[_type_regexp_joined(@_)]}$/
  8078         11941  
909             }
910              
911             sub _type_regexp_eval {
912 7595     7595   37885 map {s/^\s+|\s+$//gr} ($_[0] =~ $_[1])
  1078         5103  
913             }
914              
915             sub _type_regexp_groups {
916 342     342   457 qr/^@{[_type_regexp_joined(_type_subexpr_groups(@_))]}$/
  342         646  
917             }
918              
919             sub _type_regexp_joined {
920 8420     8420   11700 join(_type_subexpr_delimiter(), @_)
921             }
922              
923             sub _type_render {
924 77     77   147 my ($into, $data) = @_;
925              
926 77 100       156 if (ref $data eq 'HASH') {
927             $data = join ', ', map +(qq("$_"), _type_render($into, $$data{$_})),
928 33         54 sort keys %{$data};
  33         188  
929 33         98 $data = "$into\[$data\]";
930             }
931              
932 77 100       143 if (ref $data eq 'ARRAY') {
933 1 50       4 $data = join ', ', map +(/^\w+$/ ? qq("$_") : $_), @{$data};
  1         15  
934 1         6 $data = "$into\[$data\]";
935             }
936              
937 77         232 return $data;
938             }
939              
940             sub _type_subexpr_delimiter {
941 8553     8553   174158 '\s*\|\s*'
942             }
943              
944             sub _type_subexpr_groups {
945 342     342   1395 map "($_)", @_
946             }
947              
948             sub _type_subexpr_type_1 {
949 2487     2487   4589 '\w+'
950             }
951              
952             sub _type_subexpr_type_2 {
953 6877     6877   13115 '\w+\s*\[.*\]+'
954             }
955              
956             sub _type_subexpr_type_3 {
957 4733     4733   8542 '.*'
958             }
959              
960             sub _type_subexpr_type_4 {
961 1504     1504   2804 '[A-Za-z][:\^\w]+\w*'
962             }
963              
964             1;
965              
966              
967              
968             =head1 NAME
969              
970             Venus::Assert - Assert Class
971              
972             =cut
973              
974             =head1 ABSTRACT
975              
976             Assert Class for Perl 5
977              
978             =cut
979              
980             =head1 SYNOPSIS
981              
982             package main;
983              
984             use Venus::Assert;
985              
986             my $assert = Venus::Assert->new('Example');
987              
988             # $assert->format(float => sub {sprintf('%.2f', $_->value)});
989              
990             # $assert->accept(float => sub {$_->value > 1});
991              
992             # $assert->check;
993              
994             =cut
995              
996             =head1 DESCRIPTION
997              
998             This package provides a mechanism for asserting type constraints and coercions
999             on data.
1000              
1001             =cut
1002              
1003             =head1 ATTRIBUTES
1004              
1005             This package has the following attributes:
1006              
1007             =cut
1008              
1009             =head2 expects
1010              
1011             expects(ArrayRef)
1012              
1013             This attribute is read-write, accepts C<(ArrayRef)> values, and is optional.
1014              
1015             =cut
1016              
1017             =head2 message
1018              
1019             message(Str)
1020              
1021             This attribute is read-write, accepts C<(Str)> values, and is optional.
1022              
1023             =cut
1024              
1025             =head2 name
1026              
1027             name(Str)
1028              
1029             This attribute is read-write, accepts C<(Str)> values, and is optional.
1030              
1031             =cut
1032              
1033             =head1 INHERITS
1034              
1035             This package inherits behaviors from:
1036              
1037             L
1038              
1039             =cut
1040              
1041             =head1 INTEGRATES
1042              
1043             This package integrates behaviors from:
1044              
1045             L
1046              
1047             =cut
1048              
1049             =head1 METHODS
1050              
1051             This package provides the following methods:
1052              
1053             =cut
1054              
1055             =head2 accept
1056              
1057             accept(Str $name, Any @args) (Object)
1058              
1059             The accept method registers a constraint based on the built-in type or package
1060             name provided as the first argument. The built-in types are I<"array">,
1061             I<"boolean">, I<"code">, I<"float">, I<"hash">, I<"number">, I<"object">,
1062             I<"regexp">, I<"scalar">, I<"string">, or I<"undef">. Any name given that is
1063             not a built-in type is assumed to be a method (i.e. a method call) or an
1064             I<"object"> of the name provided. Additional arguments are assumed to be
1065             arguments for the dispatched method call. Optionally, you can provide a
1066             callback to further constrain/validate the provided value, returning truthy or
1067             falsy, for methods that support it.
1068              
1069             I>
1070              
1071             =over 4
1072              
1073             =item accept example 1
1074              
1075             # given: synopsis
1076              
1077             package main;
1078              
1079             $assert = $assert->accept('float');
1080              
1081             # bless(..., "Venus::Assert")
1082              
1083             # ...
1084              
1085             # $assert->check;
1086              
1087             # 0
1088              
1089             # $assert->check(1.01);
1090              
1091             # 1
1092              
1093             =back
1094              
1095             =over 4
1096              
1097             =item accept example 2
1098              
1099             # given: synopsis
1100              
1101             package main;
1102              
1103             $assert = $assert->accept('number');
1104              
1105             # bless(..., "Venus::Assert")
1106              
1107             # ...
1108              
1109             # $assert->check(1.01);
1110              
1111             # 0
1112              
1113             # $assert->check(1_01);
1114              
1115             # 1
1116              
1117             =back
1118              
1119             =over 4
1120              
1121             =item accept example 3
1122              
1123             # given: synopsis
1124              
1125             package Example1;
1126              
1127             sub new {
1128             bless {};
1129             }
1130              
1131             package Example2;
1132              
1133             sub new {
1134             bless {};
1135             }
1136              
1137             package main;
1138              
1139             $assert = $assert->accept('object');
1140              
1141             # bless(..., "Venus::Assert")
1142              
1143             # ...
1144              
1145             # $assert->check;
1146              
1147             # 0
1148              
1149             # $assert->check(qr//);
1150              
1151             # 0
1152              
1153             # $assert->check(Example1->new);
1154              
1155             # 1
1156              
1157             # $assert->check(Example2->new);
1158              
1159             # 1
1160              
1161             =back
1162              
1163             =over 4
1164              
1165             =item accept example 4
1166              
1167             # given: synopsis
1168              
1169             package Example1;
1170              
1171             sub new {
1172             bless {};
1173             }
1174              
1175             package Example2;
1176              
1177             sub new {
1178             bless {};
1179             }
1180              
1181             package main;
1182              
1183             $assert = $assert->accept('Example1');
1184              
1185             # bless(..., "Venus::Assert")
1186              
1187             # ...
1188              
1189             # $assert->check;
1190              
1191             # 0
1192              
1193             # $assert->check(qr//);
1194              
1195             # 0
1196              
1197             # $assert->check(Example1->new);
1198              
1199             # 1
1200              
1201             # $assert->check(Example2->new);
1202              
1203             # 0
1204              
1205             =back
1206              
1207             =cut
1208              
1209             =head2 any
1210              
1211             any() (Assert)
1212              
1213             The any method configures the object to accept any value and returns the
1214             invocant.
1215              
1216             I>
1217              
1218             =over 4
1219              
1220             =item any example 1
1221              
1222             # given: synopsis
1223              
1224             package main;
1225              
1226             $assert = $assert->any;
1227              
1228             # $assert->check;
1229              
1230             # true
1231              
1232             =back
1233              
1234             =cut
1235              
1236             =head2 array
1237              
1238             array(CodeRef $check) (Assert)
1239              
1240             The array method configures the object to accept array references and returns
1241             the invocant.
1242              
1243             I>
1244              
1245             =over 4
1246              
1247             =item array example 1
1248              
1249             # given: synopsis
1250              
1251             package main;
1252              
1253             $assert = $assert->array;
1254              
1255             # $assert->check([]);
1256              
1257             # true
1258              
1259             =back
1260              
1261             =cut
1262              
1263             =head2 arrayref
1264              
1265             arrayref(CodeRef $check) (Assert)
1266              
1267             The arrayref method configures the object to accept array references and
1268             returns the invocant.
1269              
1270             I>
1271              
1272             =over 4
1273              
1274             =item arrayref example 1
1275              
1276             # given: synopsis
1277              
1278             package main;
1279              
1280             $assert = $assert->arrayref;
1281              
1282             # $assert->check([]);
1283              
1284             # true
1285              
1286             =back
1287              
1288             =cut
1289              
1290             =head2 attributes
1291              
1292             attributes(Str | ArrayRef[Str] @pairs) (Assert)
1293              
1294             The attributes method configures the object to accept objects containing
1295             attributes whose values' match the attribute names and types specified, and
1296             returns the invocant.
1297              
1298             I>
1299              
1300             =over 4
1301              
1302             =item attributes example 1
1303              
1304             # given: synopsis
1305              
1306             package main;
1307              
1308             $assert = $assert->attributes;
1309              
1310             # $assert->check(Venus::Assert->new);
1311              
1312             # true
1313              
1314             =back
1315              
1316             =over 4
1317              
1318             =item attributes example 2
1319              
1320             # given: synopsis
1321              
1322             package main;
1323              
1324             $assert = $assert->attributes(name => 'string');
1325              
1326             # $assert->check(bless{});
1327              
1328             # false
1329              
1330             # $assert->check(Venus::Assert->new);
1331              
1332             # true
1333              
1334             =back
1335              
1336             =over 4
1337              
1338             =item attributes example 3
1339              
1340             # given: synopsis
1341              
1342             package Example3;
1343              
1344             use Venus::Class;
1345              
1346             attr 'name';
1347              
1348             package main;
1349              
1350             $assert = $assert->attributes(name => 'string', message => 'string');
1351              
1352             # $assert->check(bless{});
1353              
1354             # false
1355              
1356             # $assert->check(Venus::Assert->new);
1357              
1358             # true
1359              
1360             # $assert->check(Example3->new);
1361              
1362             # false
1363              
1364             =back
1365              
1366             =cut
1367              
1368             =head2 boolean
1369              
1370             boolean(CodeRef $check) (Assert)
1371              
1372             The boolean method configures the object to accept boolean values and returns
1373             the invocant.
1374              
1375             I>
1376              
1377             =over 4
1378              
1379             =item boolean example 1
1380              
1381             # given: synopsis
1382              
1383             package main;
1384              
1385             $assert = $assert->boolean;
1386              
1387             # $assert->check(false);
1388              
1389             # true
1390              
1391             =back
1392              
1393             =cut
1394              
1395             =head2 check
1396              
1397             check(Any $data) (Bool)
1398              
1399             The check method returns true or false if the data provided passes the
1400             registered constraints.
1401              
1402             I>
1403              
1404             =over 4
1405              
1406             =item check example 1
1407              
1408             # given: synopsis
1409              
1410             package main;
1411              
1412             $assert->constraint(float => sub { $_->value > 1 });
1413              
1414             my $check = $assert->check;
1415              
1416             # 0
1417              
1418             =back
1419              
1420             =over 4
1421              
1422             =item check example 2
1423              
1424             # given: synopsis
1425              
1426             package main;
1427              
1428             $assert->constraint(float => sub { $_->value > 1 });
1429              
1430             my $check = $assert->check('0.01');
1431              
1432             # 0
1433              
1434             =back
1435              
1436             =over 4
1437              
1438             =item check example 3
1439              
1440             # given: synopsis
1441              
1442             package main;
1443              
1444             $assert->constraint(float => sub { $_->value > 1 });
1445              
1446             my $check = $assert->check('1.01');
1447              
1448             # 1
1449              
1450             =back
1451              
1452             =over 4
1453              
1454             =item check example 4
1455              
1456             # given: synopsis
1457              
1458             package main;
1459              
1460             $assert->constraint(float => sub { $_->value > 1 });
1461              
1462             my $check = $assert->check(time);
1463              
1464             # 0
1465              
1466             =back
1467              
1468             =cut
1469              
1470             =head2 checker
1471              
1472             checker(Str $expr) (CodeRef)
1473              
1474             The checker method calls L with the type assertion signature
1475             provided and returns a coderef which calls the L method when called.
1476              
1477             I>
1478              
1479             =over 4
1480              
1481             =item checker example 1
1482              
1483             # given: synopsis
1484              
1485             package main;
1486              
1487             my $checker = $assert->checker('string');
1488              
1489             # sub { ... }
1490              
1491             # $checker->('hello');
1492              
1493             # true
1494              
1495             # $checker->(['goodbye']);
1496              
1497             # false
1498              
1499             =back
1500              
1501             =cut
1502              
1503             =head2 clear
1504              
1505             clear() (Assert)
1506              
1507             The clear method resets all match conditions for both constraints and coercions
1508             and returns the invocant.
1509              
1510             I>
1511              
1512             =over 4
1513              
1514             =item clear example 1
1515              
1516             # given: synopsis
1517              
1518             package main;
1519              
1520             $assert = $assert->clear;
1521              
1522             # bless(..., "Venus::Assert")
1523              
1524             =back
1525              
1526             =cut
1527              
1528             =head2 code
1529              
1530             code(CodeRef $check) (Assert)
1531              
1532             The code method configures the object to accept code references and returns
1533             the invocant.
1534              
1535             I>
1536              
1537             =over 4
1538              
1539             =item code example 1
1540              
1541             # given: synopsis
1542              
1543             package main;
1544              
1545             $assert = $assert->code;
1546              
1547             # $assert->check(sub{});
1548              
1549             # true
1550              
1551             =back
1552              
1553             =cut
1554              
1555             =head2 coderef
1556              
1557             coderef(CodeRef $check) (Assert)
1558              
1559             The coderef method configures the object to accept code references and returns
1560             the invocant.
1561              
1562             I>
1563              
1564             =over 4
1565              
1566             =item coderef example 1
1567              
1568             # given: synopsis
1569              
1570             package main;
1571              
1572             $assert = $assert->coderef;
1573              
1574             # $assert->check(sub{});
1575              
1576             # true
1577              
1578             =back
1579              
1580             =cut
1581              
1582             =head2 coerce
1583              
1584             coerce(Any $data) (Any)
1585              
1586             The coerce method returns the coerced data if the data provided matches any of
1587             the registered coercions.
1588              
1589             I>
1590              
1591             =over 4
1592              
1593             =item coerce example 1
1594              
1595             # given: synopsis
1596              
1597             package main;
1598              
1599             $assert->coercion(float => sub { sprintf('%.2f', $_->value) });
1600              
1601             my $coerce = $assert->coerce;
1602              
1603             # undef
1604              
1605             =back
1606              
1607             =over 4
1608              
1609             =item coerce example 2
1610              
1611             # given: synopsis
1612              
1613             package main;
1614              
1615             $assert->coercion(float => sub { sprintf('%.2f', $_->value) });
1616              
1617             my $coerce = $assert->coerce('1.01');
1618              
1619             # "1.01"
1620              
1621             =back
1622              
1623             =over 4
1624              
1625             =item coerce example 3
1626              
1627             # given: synopsis
1628              
1629             package main;
1630              
1631             $assert->coercion(float => sub { sprintf('%.2f', $_->value) });
1632              
1633             my $coerce = $assert->coerce('1.00001');
1634              
1635             # "1.00"
1636              
1637             =back
1638              
1639             =over 4
1640              
1641             =item coerce example 4
1642              
1643             # given: synopsis
1644              
1645             package main;
1646              
1647             $assert->coercion(float => sub { sprintf('%.2f', $_->value) });
1648              
1649             my $coerce = $assert->coerce('hello world');
1650              
1651             # "hello world"
1652              
1653             =back
1654              
1655             =cut
1656              
1657             =head2 coercion
1658              
1659             coercion(Str $type, CodeRef $code) (Object)
1660              
1661             The coercion method registers a coercion based on the type provided.
1662              
1663             I>
1664              
1665             =over 4
1666              
1667             =item coercion example 1
1668              
1669             # given: synopsis
1670              
1671             package main;
1672              
1673             $assert = $assert->coercion(float => sub { sprintf('%.2f', $_->value) });
1674              
1675             # bless(..., "Venus::Assert")
1676              
1677             =back
1678              
1679             =cut
1680              
1681             =head2 coercions
1682              
1683             coercions() (Match)
1684              
1685             The coercions method returns the registered coercions as a L object.
1686              
1687             I>
1688              
1689             =over 4
1690              
1691             =item coercions example 1
1692              
1693             # given: synopsis
1694              
1695             package main;
1696              
1697             my $coercions = $assert->coercions;
1698              
1699             # bless(..., "Venus::Match")
1700              
1701             =back
1702              
1703             =cut
1704              
1705             =head2 conditions
1706              
1707             conditions() (Assert)
1708              
1709             The conditions method is an object construction hook that allows subclasses to
1710             configure the object on construction setting up constraints and coercions and
1711             returning the invocant.
1712              
1713             I>
1714              
1715             =over 4
1716              
1717             =item conditions example 1
1718              
1719             # given: synopsis
1720              
1721             package main;
1722              
1723             $assert = $assert->conditions;
1724              
1725             =back
1726              
1727             =over 4
1728              
1729             =item conditions example 2
1730              
1731             package Example::Type::PositveNumber;
1732              
1733             use base 'Venus::Assert';
1734              
1735             sub conditions {
1736             my ($self) = @_;
1737              
1738             $self->number(sub {
1739             $_->value >= 0
1740             });
1741              
1742             return $self;
1743             }
1744              
1745             package main;
1746              
1747             my $assert = Example::Type::PositveNumber->new;
1748              
1749             # $assert->check(0);
1750              
1751             # true
1752              
1753             # $assert->check(1);
1754              
1755             # true
1756              
1757             # $assert->check(-1);
1758              
1759             # false
1760              
1761             =back
1762              
1763             =cut
1764              
1765             =head2 constraint
1766              
1767             constraint(Str $type, CodeRef $code) (Object)
1768              
1769             The constraint method registers a constraint based on the type provided.
1770              
1771             I>
1772              
1773             =over 4
1774              
1775             =item constraint example 1
1776              
1777             # given: synopsis
1778              
1779             package main;
1780              
1781             $assert = $assert->constraint(float => sub { $_->value > 1 });
1782              
1783             # bless(..., "Venus::Assert")
1784              
1785             =back
1786              
1787             =cut
1788              
1789             =head2 constraints
1790              
1791             constraints() (Match)
1792              
1793             The constraints method returns the registered constraints as a L
1794             object.
1795              
1796             I>
1797              
1798             =over 4
1799              
1800             =item constraints example 1
1801              
1802             # given: synopsis
1803              
1804             package main;
1805              
1806             my $constraints = $assert->constraints;
1807              
1808             # bless(..., "Venus::Match")
1809              
1810             =back
1811              
1812             =cut
1813              
1814             =head2 defined
1815              
1816             defined(CodeRef $check) (Assert)
1817              
1818             The defined method configures the object to accept any value that's not
1819             undefined and returns the invocant.
1820              
1821             I>
1822              
1823             =over 4
1824              
1825             =item defined example 1
1826              
1827             # given: synopsis
1828              
1829             package main;
1830              
1831             $assert = $assert->defined;
1832              
1833             # $assert->check(0);
1834              
1835             # true
1836              
1837             =back
1838              
1839             =cut
1840              
1841             =head2 either
1842              
1843             either(Str | ArrayRef[Str|ArrayRef] $dispatch) (Assert)
1844              
1845             The either method configures the object to accept "either" of the conditions
1846             provided, which may be a string or arrayref representing a method call, and
1847             returns the invocant.
1848              
1849             I>
1850              
1851             =over 4
1852              
1853             =item either example 1
1854              
1855             # given: synopsis
1856              
1857             package main;
1858              
1859             $assert = $assert->either('string');
1860              
1861             # $assert->check('1');
1862              
1863             # true
1864              
1865             # $assert->check(1);
1866              
1867             # false
1868              
1869             =back
1870              
1871             =over 4
1872              
1873             =item either example 2
1874              
1875             # given: synopsis
1876              
1877             package main;
1878              
1879             $assert = $assert->either('string', 'number');
1880              
1881             # $assert->check(true);
1882              
1883             # false
1884              
1885             # $assert->check('1');
1886              
1887             # true
1888              
1889             # $assert->check(1);
1890              
1891             # true
1892              
1893             =back
1894              
1895             =over 4
1896              
1897             =item either example 3
1898              
1899             # given: synopsis
1900              
1901             package main;
1902              
1903             $assert = $assert->either('number', 'boolean');
1904              
1905             # $assert->check(true);
1906              
1907             # true
1908              
1909             # $assert->check('1');
1910              
1911             # false
1912              
1913             # $assert->check(1);
1914              
1915             # true
1916              
1917             =back
1918              
1919             =cut
1920              
1921             =head2 enum
1922              
1923             enum(Any @data) (Assert)
1924              
1925             The enum method configures the object to accept any one of the provide options,
1926             and returns the invocant.
1927              
1928             I>
1929              
1930             =over 4
1931              
1932             =item enum example 1
1933              
1934             # given: synopsis
1935              
1936             package main;
1937              
1938             $assert = $assert->enum('s', 'm', 'l', 'xl');
1939              
1940             # $assert->check('s');
1941              
1942             # true
1943              
1944             # $assert->check('xs');
1945              
1946             # false
1947              
1948             =back
1949              
1950             =cut
1951              
1952             =head2 expression
1953              
1954             expression(Str $expr) (Assert)
1955              
1956             The expression method parses a string representation of an type assertion
1957             signature, registers the subexpressions using the L and L
1958             methods, and returns the invocant.
1959              
1960             I>
1961              
1962             =over 4
1963              
1964             =item expression example 1
1965              
1966             # given: synopsis
1967              
1968             package main;
1969              
1970             $assert = $assert->expression('string');
1971              
1972             # $assert->check('hello');
1973              
1974             # true
1975              
1976             # $assert->check(['goodbye']);
1977              
1978             # false
1979              
1980             =back
1981              
1982             =over 4
1983              
1984             =item expression example 2
1985              
1986             # given: synopsis
1987              
1988             package main;
1989              
1990             $assert = $assert->expression('string | coderef');
1991              
1992             # $assert->check('hello');
1993              
1994             # true
1995              
1996             # $assert->check(sub{'hello'});
1997              
1998             # true
1999              
2000             # $assert->check(['goodbye']);
2001              
2002             # false
2003              
2004             =back
2005              
2006             =over 4
2007              
2008             =item expression example 3
2009              
2010             # given: synopsis
2011              
2012             package main;
2013              
2014             $assert = $assert->expression('string | coderef | Venus::Assert');
2015              
2016             # $assert->check('hello');
2017              
2018             # true
2019              
2020             # $assert->check(sub{'hello'});
2021              
2022             # true
2023              
2024             # $assert->check($assert);
2025              
2026             # true
2027              
2028             # $assert->check(['goodbye']);
2029              
2030             # false
2031              
2032             =back
2033              
2034             =over 4
2035              
2036             =item expression example 4
2037              
2038             # given: synopsis
2039              
2040             package main;
2041              
2042             $assert = $assert->expression('Venus::Assert | within[arrayref, Venus::Assert]');
2043              
2044             # $assert->check('hello');
2045              
2046             # false
2047              
2048             # $assert->check(sub{'hello'});
2049              
2050             # false
2051              
2052             # $assert->check($assert);
2053              
2054             # true
2055              
2056             # $assert->check(['goodbye']);
2057              
2058             # false
2059              
2060             # $assert->check([$assert]);
2061              
2062             # true
2063              
2064             =back
2065              
2066             =over 4
2067              
2068             =item expression example 5
2069              
2070             # given: synopsis
2071              
2072             package main;
2073              
2074             $assert = $assert->expression('
2075             string
2076             | within[
2077             arrayref, within[
2078             hashref, string
2079             ]
2080             ]
2081             ');
2082              
2083             # $assert->check('hello');
2084              
2085             # true
2086              
2087             # $assert->check(sub{'hello'});
2088              
2089             # false
2090              
2091             # $assert->check($assert);
2092              
2093             # false
2094              
2095             # $assert->check([]);
2096              
2097             # false
2098              
2099             # $assert->check([{'test' => ['okay']}]);
2100              
2101             # false
2102              
2103             # $assert->check([{'test' => 'okay'}]);
2104              
2105             # true
2106              
2107             =back
2108              
2109             =cut
2110              
2111             =head2 float
2112              
2113             float(CodeRef $check) (Assert)
2114              
2115             The float method configures the object to accept floating-point values and
2116             returns the invocant.
2117              
2118             I>
2119              
2120             =over 4
2121              
2122             =item float example 1
2123              
2124             # given: synopsis
2125              
2126             package main;
2127              
2128             $assert = $assert->float;
2129              
2130             # $assert->check(1.23);
2131              
2132             # true
2133              
2134             =back
2135              
2136             =cut
2137              
2138             =head2 format
2139              
2140             format(Str $name, CodeRef $callback) (Object)
2141              
2142             The format method registers a coercion based on the built-in type or package
2143             name and callback provided. The built-in types are I<"array">, I<"boolean">,
2144             I<"code">, I<"float">, I<"hash">, I<"number">, I<"object">, I<"regexp">,
2145             I<"scalar">, I<"string">, or I<"undef">. Any name given that is not a built-in
2146             type is assumed to be an I<"object"> of the name provided.
2147              
2148             I>
2149              
2150             =over 4
2151              
2152             =item format example 1
2153              
2154             # given: synopsis
2155              
2156             package main;
2157              
2158             $assert = $assert->format('float', sub{int $_->value});
2159              
2160             # bless(..., "Venus::Assert")
2161              
2162             # ...
2163              
2164             # $assert->coerce;
2165              
2166             # undef
2167              
2168             # $assert->coerce(1.01);
2169              
2170             # 1
2171              
2172             =back
2173              
2174             =over 4
2175              
2176             =item format example 2
2177              
2178             # given: synopsis
2179              
2180             package main;
2181              
2182             $assert = $assert->format('number', sub{ sprintf('%.2f', $_->value) });
2183              
2184             # bless(..., "Venus::Assert")
2185              
2186             # ...
2187              
2188             # $assert->coerce(1.01);
2189              
2190             # 1.01
2191              
2192             # $assert->coerce(1_01);
2193              
2194             # 101.00
2195              
2196             =back
2197              
2198             =over 4
2199              
2200             =item format example 3
2201              
2202             # given: synopsis
2203              
2204             package Example1;
2205              
2206             sub new {
2207             bless {};
2208             }
2209              
2210             package Example2;
2211              
2212             sub new {
2213             bless {};
2214             }
2215              
2216             package main;
2217              
2218             $assert = $assert->format('object', sub{ ref $_->value });
2219              
2220             # bless(..., "Venus::Assert")
2221              
2222             # ...
2223              
2224             # $assert->coerce(qr//);
2225              
2226             # qr//
2227              
2228             # $assert->coerce(Example1->new);
2229              
2230             # "Example1"
2231              
2232             # $assert->coerce(Example2->new);
2233              
2234             # "Example2"
2235              
2236             =back
2237              
2238             =over 4
2239              
2240             =item format example 4
2241              
2242             # given: synopsis
2243              
2244             package Example1;
2245              
2246             sub new {
2247             bless {};
2248             }
2249              
2250             package Example2;
2251              
2252             sub new {
2253             bless {};
2254             }
2255              
2256             package main;
2257              
2258             $assert = $assert->format('Example1', sub{ ref $_->value });
2259              
2260             # bless(..., "Venus::Assert")
2261              
2262             # ...
2263              
2264             # $assert->coerce(qr//);
2265              
2266             # qr//
2267              
2268             # $assert->coerce(Example1->new);
2269              
2270             # "Example1"
2271              
2272             # $assert->coerce(Example2->new);
2273              
2274             # bless({}, "Example2")
2275              
2276             =back
2277              
2278             =cut
2279              
2280             =head2 hash
2281              
2282             hash(CodeRef $check) (Assert)
2283              
2284             The hash method configures the object to accept hash references and returns
2285             the invocant.
2286              
2287             I>
2288              
2289             =over 4
2290              
2291             =item hash example 1
2292              
2293             # given: synopsis
2294              
2295             package main;
2296              
2297             $assert = $assert->hash;
2298              
2299             # $assert->check({});
2300              
2301             # true
2302              
2303             =back
2304              
2305             =cut
2306              
2307             =head2 hashkeys
2308              
2309             hashkeys(Str | ArrayRef[Str] @pairs) (Assert)
2310              
2311             The hashkeys method configures the object to accept hash based values
2312             containing the keys whose values' match the specified types, and returns the
2313             invocant.
2314              
2315             I>
2316              
2317             =over 4
2318              
2319             =item hashkeys example 1
2320              
2321             # given: synopsis
2322              
2323             package main;
2324              
2325             $assert = $assert->hashkeys;
2326              
2327             # $assert->check({});
2328              
2329             # false
2330              
2331             # $assert->check({random => rand});
2332              
2333             # true
2334              
2335             =back
2336              
2337             =over 4
2338              
2339             =item hashkeys example 2
2340              
2341             # given: synopsis
2342              
2343             package main;
2344              
2345             $assert = $assert->hashkeys(random => 'float');
2346              
2347             # $assert->check({});
2348              
2349             # false
2350              
2351             # $assert->check({random => rand});
2352              
2353             # true
2354              
2355             # $assert->check({random => time});
2356              
2357             # false
2358              
2359             =back
2360              
2361             =over 4
2362              
2363             =item hashkeys example 3
2364              
2365             # given: synopsis
2366              
2367             package main;
2368              
2369             $assert = $assert->hashkeys(random => ['either', 'float', 'number']);
2370              
2371             # $assert->check({});
2372              
2373             # false
2374              
2375             # $assert->check({random => rand});
2376              
2377             # true
2378              
2379             # $assert->check({random => time});
2380              
2381             # true
2382              
2383             # $assert->check({random => 'okay'});
2384              
2385             # false
2386              
2387             # $assert->check(bless{random => rand});
2388              
2389             # true
2390              
2391             # $assert->check(bless{random => time});
2392              
2393             # true
2394              
2395             # $assert->check(bless{random => 'okay'});
2396              
2397             # false
2398              
2399             =back
2400              
2401             =cut
2402              
2403             =head2 hashref
2404              
2405             hashref(CodeRef $check) (Assert)
2406              
2407             The hashref method configures the object to accept hash references and returns
2408             the invocant.
2409              
2410             I>
2411              
2412             =over 4
2413              
2414             =item hashref example 1
2415              
2416             # given: synopsis
2417              
2418             package main;
2419              
2420             $assert = $assert->hashref;
2421              
2422             # $assert->check({});
2423              
2424             # true
2425              
2426             =back
2427              
2428             =cut
2429              
2430             =head2 identity
2431              
2432             identity(Str $name) (Assert)
2433              
2434             The identity method configures the object to accept objects of the type
2435             specified as the argument, and returns the invocant.
2436              
2437             I>
2438              
2439             =over 4
2440              
2441             =item identity example 1
2442              
2443             # given: synopsis
2444              
2445             package main;
2446              
2447             $assert = $assert->identity('Venus::Assert');
2448              
2449             # $assert->check(Venus::Assert->new);
2450              
2451             # true
2452              
2453             =back
2454              
2455             =cut
2456              
2457             =head2 inherits
2458              
2459             inherits(Str $name) (Assert)
2460              
2461             The inherits method configures the object to accept objects of the type
2462             specified as the argument, and returns the invocant. This method is a proxy for
2463             the L method.
2464              
2465             I>
2466              
2467             =over 4
2468              
2469             =item inherits example 1
2470              
2471             # given: synopsis
2472              
2473             package main;
2474              
2475             $assert = $assert->inherits('Venus::Assert');
2476              
2477             # $assert->check(Venus::Assert->new);
2478              
2479             # true
2480              
2481             =back
2482              
2483             =cut
2484              
2485             =head2 integrates
2486              
2487             integrates(Str $name) (Assert)
2488              
2489             The integrates method configures the object to accept objects that support the
2490             C<"does"> behavior and consumes the "role" specified as the argument, and
2491             returns the invocant.
2492              
2493             I>
2494              
2495             =over 4
2496              
2497             =item integrates example 1
2498              
2499             # given: synopsis
2500              
2501             package main;
2502              
2503             $assert = $assert->integrates('Venus::Role::Doable');
2504              
2505             # $assert->check(Venus::Assert->new);
2506              
2507             # true
2508              
2509             =back
2510              
2511             =cut
2512              
2513             =head2 maybe
2514              
2515             maybe(Str $type, Any @args) (Assert)
2516              
2517             The maybe method configures the object to accept the type provided as an
2518             argument, or undef, and returns the invocant.
2519              
2520             I>
2521              
2522             =over 4
2523              
2524             =item maybe example 1
2525              
2526             # given: synopsis
2527              
2528             package main;
2529              
2530             $assert = $assert->maybe('code');
2531              
2532             # $assert->check(sub{});
2533              
2534             # true
2535              
2536             # $assert->check(undef);
2537              
2538             # true
2539              
2540             =back
2541              
2542             =cut
2543              
2544             =head2 number
2545              
2546             number(CodeRef $check) (Assert)
2547              
2548             The number method configures the object to accept numberic values and returns
2549             the invocant.
2550              
2551             I>
2552              
2553             =over 4
2554              
2555             =item number example 1
2556              
2557             # given: synopsis
2558              
2559             package main;
2560              
2561             $assert = $assert->number;
2562              
2563             # $assert->check(0);
2564              
2565             # true
2566              
2567             =back
2568              
2569             =cut
2570              
2571             =head2 object
2572              
2573             object(CodeRef $check) (Assert)
2574              
2575             The object method configures the object to accept objects and returns the
2576             invocant.
2577              
2578             I>
2579              
2580             =over 4
2581              
2582             =item object example 1
2583              
2584             # given: synopsis
2585              
2586             package main;
2587              
2588             $assert = $assert->object;
2589              
2590             # $assert->check(bless{});
2591              
2592             # true
2593              
2594             =back
2595              
2596             =cut
2597              
2598             =head2 package
2599              
2600             package() (Assert)
2601              
2602             The package method configures the object to accept package names (which are
2603             loaded) and returns the invocant.
2604              
2605             I>
2606              
2607             =over 4
2608              
2609             =item package example 1
2610              
2611             # given: synopsis
2612              
2613             package main;
2614              
2615             $assert = $assert->package;
2616              
2617             # $assert->check('Venus');
2618              
2619             # true
2620              
2621             =back
2622              
2623             =cut
2624              
2625             =head2 parse
2626              
2627             parse(Str $expr) (Any)
2628              
2629             The parse method accepts a string representation of a type assertion signature
2630             and returns a data structure representing one or more method calls to be used
2631             for validating the assertion signature.
2632              
2633             I>
2634              
2635             =over 4
2636              
2637             =item parse example 1
2638              
2639             # given: synopsis
2640              
2641             package main;
2642              
2643             my $parsed = $assert->parse('');
2644              
2645             # ['']
2646              
2647             =back
2648              
2649             =over 4
2650              
2651             =item parse example 2
2652              
2653             # given: synopsis
2654              
2655             package main;
2656              
2657             my $parsed = $assert->parse('any');
2658              
2659             # ['any']
2660              
2661             =back
2662              
2663             =over 4
2664              
2665             =item parse example 3
2666              
2667             # given: synopsis
2668              
2669             package main;
2670              
2671             my $parsed = $assert->parse('string | number');
2672              
2673             # ['either', 'string', 'number']
2674              
2675             =back
2676              
2677             =over 4
2678              
2679             =item parse example 4
2680              
2681             # given: synopsis
2682              
2683             package main;
2684              
2685             my $parsed = $assert->parse('enum[up,down,left,right]');
2686              
2687             # [['enum', 'up', 'down', 'left', 'right']]
2688              
2689             =back
2690              
2691             =over 4
2692              
2693             =item parse example 5
2694              
2695             # given: synopsis
2696              
2697             package main;
2698              
2699             my $parsed = $assert->parse('number | float | boolean');
2700              
2701             # ['either', 'number', 'float', 'boolean']
2702              
2703             =back
2704              
2705             =over 4
2706              
2707             =item parse example 6
2708              
2709             # given: synopsis
2710              
2711             package main;
2712              
2713             my $parsed = $assert->parse('Example');
2714              
2715             # ['Example']
2716              
2717             =back
2718              
2719             =over 4
2720              
2721             =item parse example 7
2722              
2723             # given: synopsis
2724              
2725             package main;
2726              
2727             my $parsed = $assert->parse('coderef | Venus::Code');
2728              
2729             # ['either', 'coderef', 'Venus::Code']
2730              
2731             =back
2732              
2733             =over 4
2734              
2735             =item parse example 8
2736              
2737             # given: synopsis
2738              
2739             package main;
2740              
2741             my $parsed = $assert->parse('tuple[number, arrayref, coderef]');
2742              
2743             # [['tuple', 'number', 'arrayref', 'coderef']]
2744              
2745             =back
2746              
2747             =over 4
2748              
2749             =item parse example 9
2750              
2751             # given: synopsis
2752              
2753             package main;
2754              
2755             my $parsed = $assert->parse('tuple[number, within[arrayref, hashref], coderef]');
2756              
2757             # [['tuple', 'number', ['within', 'arrayref', 'hashref'], 'coderef']]
2758              
2759             =back
2760              
2761             =over 4
2762              
2763             =item parse example 10
2764              
2765             # given: synopsis
2766              
2767             package main;
2768              
2769             my $parsed = $assert->parse(
2770             'tuple[number, within[arrayref, hashref] | arrayref, coderef]'
2771             );
2772              
2773             # [
2774             # ['tuple', 'number',
2775             # ['either', ['within', 'arrayref', 'hashref'], 'arrayref'], 'coderef']
2776             # ]
2777              
2778              
2779              
2780              
2781             =back
2782              
2783             =over 4
2784              
2785             =item parse example 11
2786              
2787             # given: synopsis
2788              
2789             package main;
2790              
2791             my $parsed = $assert->parse(
2792             'hashkeys["id", number | float, "upvotes", within[arrayref, boolean]]'
2793             );
2794              
2795             # [[
2796             # 'hashkeys',
2797             # 'id',
2798             # ['either', 'number', 'float'],
2799             # 'upvotes',
2800             # ['within', 'arrayref', 'boolean']
2801             # ]]
2802              
2803             =back
2804              
2805             =cut
2806              
2807             =head2 reference
2808              
2809             reference(CodeRef $check) (Assert)
2810              
2811             The reference method configures the object to accept references and returns the
2812             invocant.
2813              
2814             I>
2815              
2816             =over 4
2817              
2818             =item reference example 1
2819              
2820             # given: synopsis
2821              
2822             package main;
2823              
2824             $assert = $assert->reference;
2825              
2826             # $assert->check(sub{});
2827              
2828             # true
2829              
2830             =back
2831              
2832             =cut
2833              
2834             =head2 regexp
2835              
2836             regexp(CodeRef $check) (Assert)
2837              
2838             The regexp method configures the object to accept regular expression objects
2839             and returns the invocant.
2840              
2841             I>
2842              
2843             =over 4
2844              
2845             =item regexp example 1
2846              
2847             # given: synopsis
2848              
2849             package main;
2850              
2851             $assert = $assert->regexp;
2852              
2853             # $assert->check(qr//);
2854              
2855             # true
2856              
2857             =back
2858              
2859             =cut
2860              
2861             =head2 render
2862              
2863             render(Str $into, Str $expression) (Str)
2864              
2865             The render method builds and returns a type expressions suitable for providing
2866             to L based on the data provided.
2867              
2868             I>
2869              
2870             =over 4
2871              
2872             =item render example 1
2873              
2874             # given: synopsis
2875              
2876             package main;
2877              
2878             $assert = $assert->render;
2879              
2880             # undef
2881              
2882             =back
2883              
2884             =over 4
2885              
2886             =item render example 2
2887              
2888             # given: synopsis
2889              
2890             package main;
2891              
2892             $assert = $assert->render(undef, 'string');
2893              
2894             # "string"
2895              
2896             =back
2897              
2898             =over 4
2899              
2900             =item render example 3
2901              
2902             # given: synopsis
2903              
2904             package main;
2905              
2906             $assert = $assert->render('routines', ['say', 'say_pretty']);
2907              
2908             # 'routines["say", "say_pretty"]'
2909              
2910             =back
2911              
2912             =over 4
2913              
2914             =item render example 4
2915              
2916             # given: synopsis
2917              
2918             package main;
2919              
2920             $assert = $assert->render('hashkeys', {id => 'number', name => 'string'});
2921              
2922             # 'hashkeys["id", number, "name", string]'
2923              
2924             =back
2925              
2926             =over 4
2927              
2928             =item render example 5
2929              
2930             # given: synopsis
2931              
2932             package main;
2933              
2934             $assert = $assert->render('hashkeys', {
2935             id => 'number',
2936             profile => {
2937             level => 'string',
2938             },
2939             });
2940              
2941             # 'hashkeys["id", number, "profile", hashkeys["level", string]]'
2942              
2943             =back
2944              
2945             =cut
2946              
2947             =head2 routines
2948              
2949             routines(Str @names) (Assert)
2950              
2951             The routines method configures the object to accept an object having all of the
2952             routines provided, and returns the invocant.
2953              
2954             I>
2955              
2956             =over 4
2957              
2958             =item routines example 1
2959              
2960             # given: synopsis
2961              
2962             package main;
2963              
2964             $assert = $assert->routines('new', 'print', 'say');
2965              
2966             # $assert->check(Venus::Assert->new);
2967              
2968             # true
2969              
2970             =back
2971              
2972             =cut
2973              
2974             =head2 scalar
2975              
2976             scalar(CodeRef $check) (Assert)
2977              
2978             The scalar method configures the object to accept scalar references and returns
2979             the invocant.
2980              
2981             I>
2982              
2983             =over 4
2984              
2985             =item scalar example 1
2986              
2987             # given: synopsis
2988              
2989             package main;
2990              
2991             $assert = $assert->scalar;
2992              
2993             # $assert->check(\1);
2994              
2995             # true
2996              
2997             =back
2998              
2999             =cut
3000              
3001             =head2 scalarref
3002              
3003             scalarref(CodeRef $check) (Assert)
3004              
3005             The scalarref method configures the object to accept scalar references and returns
3006             the invocant.
3007              
3008             I>
3009              
3010             =over 4
3011              
3012             =item scalarref example 1
3013              
3014             # given: synopsis
3015              
3016             package main;
3017              
3018             $assert = $assert->scalarref;
3019              
3020             # $assert->check(\1);
3021              
3022             # true
3023              
3024             =back
3025              
3026             =cut
3027              
3028             =head2 string
3029              
3030             string(CodeRef $check) (Assert)
3031              
3032             The string method configures the object to accept string values and returns the
3033             invocant.
3034              
3035             I>
3036              
3037             =over 4
3038              
3039             =item string example 1
3040              
3041             # given: synopsis
3042              
3043             package main;
3044              
3045             $assert = $assert->string;
3046              
3047             # $assert->check('');
3048              
3049             # true
3050              
3051             =back
3052              
3053             =cut
3054              
3055             =head2 tuple
3056              
3057             tuple(Str | ArrayRef[Str] @types) (Assert)
3058              
3059             The tuple method configures the object to accept array references which conform
3060             to a tuple specification, and returns the invocant. The value being evaluated
3061             must contain at-least one element to match.
3062              
3063             I>
3064              
3065             =over 4
3066              
3067             =item tuple example 1
3068              
3069             # given: synopsis
3070              
3071             package main;
3072              
3073             $assert = $assert->tuple('number', ['maybe', 'array'], 'code');
3074              
3075             # $assert->check([200, [], sub{}]);
3076              
3077             # true
3078              
3079             =back
3080              
3081             =cut
3082              
3083             =head2 undef
3084              
3085             undef(CodeRef $check) (Assert)
3086              
3087             The undef method configures the object to accept undefined values and returns
3088             the invocant.
3089              
3090             I>
3091              
3092             =over 4
3093              
3094             =item undef example 1
3095              
3096             # given: synopsis
3097              
3098             package main;
3099              
3100             $assert = $assert->undef;
3101              
3102             # $assert->check(undef);
3103              
3104             # true
3105              
3106             =back
3107              
3108             =cut
3109              
3110             =head2 validate
3111              
3112             validate(Any $data) (Any)
3113              
3114             The validate method returns the data provided if the data provided passes the
3115             registered constraints, or throws an exception.
3116              
3117             I>
3118              
3119             =over 4
3120              
3121             =item validate example 1
3122              
3123             # given: synopsis
3124              
3125             package main;
3126              
3127             $assert->constraint(float => sub { $_->value > 1 });
3128              
3129             my $result = $assert->validate;
3130              
3131             # Exception! (isa Venus::Assert::Error) (see error_on_validate)
3132              
3133             =back
3134              
3135             =over 4
3136              
3137             =item validate example 2
3138              
3139             # given: synopsis
3140              
3141             package main;
3142              
3143             $assert->constraint(float => sub { $_->value > 1 });
3144              
3145             my $result = $assert->validate('0.01');
3146              
3147             # Exception! (isa Venus::Assert::Error) (see error_on_validate)
3148              
3149             =back
3150              
3151             =over 4
3152              
3153             =item validate example 3
3154              
3155             # given: synopsis
3156              
3157             package main;
3158              
3159             $assert->constraint(float => sub { $_->value > 1 });
3160              
3161             my $result = $assert->validate('1.01');
3162              
3163             # "1.01"
3164              
3165             =back
3166              
3167             =over 4
3168              
3169             =item validate example 4
3170              
3171             # given: synopsis
3172              
3173             package main;
3174              
3175             $assert->constraint(float => sub { $_->value > 1 });
3176              
3177             my $result = $assert->validate(time);
3178              
3179             # Exception! (isa Venus::Assert::Error) (see error_on_validate)
3180              
3181             =back
3182              
3183             =cut
3184              
3185             =head2 validator
3186              
3187             validator(Str $expr) (CodeRef)
3188              
3189             The validator method returns a coderef that can be used as a value validator,
3190             which returns the data provided if the data provided passes the registered
3191             constraints, or throws an exception.
3192              
3193             I>
3194              
3195             =over 4
3196              
3197             =item validator example 1
3198              
3199             # given: synopsis
3200              
3201             package main;
3202              
3203             my $validator = $assert->validator('string');
3204              
3205             # sub { ... }
3206              
3207             # $validator->('hello');
3208              
3209             # "hello"
3210              
3211             # $validator->(['goodbye']);
3212              
3213             # Exception! (isa Venus::Error) (see error_on_validate)
3214              
3215             =back
3216              
3217             =cut
3218              
3219             =head2 value
3220              
3221             value(CodeRef $check) (Assert)
3222              
3223             The value method configures the object to accept defined, non-reference,
3224             values, and returns the invocant.
3225              
3226             I>
3227              
3228             =over 4
3229              
3230             =item value example 1
3231              
3232             # given: synopsis
3233              
3234             package main;
3235              
3236             $assert = $assert->value;
3237              
3238             # $assert->check(1_000_000);
3239              
3240             # true
3241              
3242             =back
3243              
3244             =cut
3245              
3246             =head2 within
3247              
3248             within(Str $type) (Assert)
3249              
3250             The within method configures the object, registering a constraint action as a
3251             sub-match operation, to accept array or hash based values, and returns a
3252             L instance for the sub-match operation (not the invocant). This
3253             operation can traverse blessed array or hash based values. The value being
3254             evaluated must contain at-least one element to match.
3255              
3256             I>
3257              
3258             =over 4
3259              
3260             =item within example 1
3261              
3262             # given: synopsis
3263              
3264             package main;
3265              
3266             my $within = $assert->within('array')->code;
3267              
3268             my $action = $assert;
3269              
3270             # $assert->check([]);
3271              
3272             # false
3273              
3274             # $assert->check([sub{}]);
3275              
3276             # true
3277              
3278             # $assert->check([{}]);
3279              
3280             # false
3281              
3282             # $assert->check(bless[]);
3283              
3284             # false
3285              
3286             # $assert->check(bless[sub{}]);
3287              
3288             # true
3289              
3290             =back
3291              
3292             =over 4
3293              
3294             =item within example 2
3295              
3296             # given: synopsis
3297              
3298             package main;
3299              
3300             my $within = $assert->within('hash')->code;
3301              
3302             my $action = $assert;
3303              
3304             # $assert->check({});
3305              
3306             # false
3307              
3308             # $assert->check({test => sub{}});
3309              
3310             # true
3311              
3312             # $assert->check({test => {}});
3313              
3314             # false
3315              
3316             # $assert->check({test => bless{}});
3317              
3318             # false
3319              
3320             # $assert->check({test => bless sub{}});
3321              
3322             # false
3323              
3324             =back
3325              
3326             =over 4
3327              
3328             =item within example 3
3329              
3330             # given: synopsis
3331              
3332             package main;
3333              
3334             my $within = $assert->within('hashref', 'code');
3335              
3336             my $action = $assert;
3337              
3338             # $assert->check({});
3339              
3340             # false
3341              
3342             # $assert->check({test => sub{}});
3343              
3344             # true
3345              
3346             # $assert->check({test => {}});
3347              
3348             # false
3349              
3350             # $assert->check({test => bless{}});
3351              
3352             # false
3353              
3354             # $assert->check({test => bless sub{}});
3355              
3356             # false
3357              
3358             =back
3359              
3360             =cut
3361              
3362             =head2 yesno
3363              
3364             yesno(CodeRef $check) (Assert)
3365              
3366             The yesno method configures the object to accept a string value that's either
3367             C<"yes"> or C<1>, C<"no"> or C<0>, and returns the invocant.
3368              
3369             I>
3370              
3371             =over 4
3372              
3373             =item yesno example 1
3374              
3375             # given: synopsis
3376              
3377             package main;
3378              
3379             $assert = $assert->yesno;
3380              
3381             # $assert->check(undef);
3382              
3383             # false
3384              
3385             # $assert->check(0);
3386              
3387             # true
3388              
3389             # $assert->check('No');
3390              
3391             # true
3392              
3393             # $assert->check('n');
3394              
3395             # true
3396              
3397             # $assert->check(1);
3398              
3399             # true
3400              
3401             # $assert->check('Yes');
3402              
3403             # true
3404              
3405             # $assert->check('y');
3406              
3407             # true
3408              
3409             # $assert->check('Okay');
3410              
3411             # false
3412              
3413             =back
3414              
3415             =cut
3416              
3417             =head1 ERRORS
3418              
3419             This package may raise the following errors:
3420              
3421             =cut
3422              
3423             =over 4
3424              
3425             =item error: C
3426              
3427             This package may raise an error_on_validate exception.
3428              
3429             B
3430              
3431             # given: synopsis;
3432              
3433             my $input = {
3434             throw => 'error_on_validate',
3435             value => '...',
3436             };
3437              
3438             my $error = $assert->catch('error', $input);
3439              
3440             # my $name = $error->name;
3441              
3442             # "on_validate"
3443              
3444             # my $message = $error->message;
3445              
3446             # "..."
3447              
3448             # my $identity = $error->stash('identity');
3449              
3450             # "string"
3451              
3452             # my $variable = $error->stash('variable');
3453              
3454             # "..."
3455              
3456             =back
3457              
3458             =over 4
3459              
3460             =item error: C
3461              
3462             This package may raise an error_on_within exception.
3463              
3464             B
3465              
3466             # given: synopsis;
3467              
3468             my $input = {
3469             throw => 'error_on_within',
3470             type => 'coderef',
3471             args => ['string'],
3472             };
3473              
3474             my $error = $assert->catch('error', $input);
3475              
3476             # my $ = $error->name;
3477              
3478             # "on_within"
3479              
3480             # my $message = $error->render;
3481              
3482             # "Invalid type (\"$type\") palid ed to the \"within\" method"
3483              
3484             # my $self = $error->stash('self');
3485              
3486             # $assert
3487              
3488             # my $type = $error->stash('type');
3489              
3490             # "coderef"
3491              
3492             # my $args = $error->stash('args');
3493              
3494             # ["string"]
3495              
3496             =back
3497              
3498             =head1 AUTHORS
3499              
3500             Awncorp, C
3501              
3502             =cut
3503              
3504             =head1 LICENSE
3505              
3506             Copyright (C) 2000, Al Newkirk.
3507              
3508             This program is free software, you can redistribute it and/or modify it under
3509             the terms of the Apache license version 2.0.
3510              
3511             =cut