File Coverage

blib/lib/Types/XMLSchema.pm
Criterion Covered Total %
statement 8 10 80.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 12 14 85.7


line stmt bran cond sub pod time code
1             package Types::XMLSchema;
2             BEGIN {
3 1     1   19179 $Types::XMLSchema::AUTHORITY = 'cpan:AJGB';
4             }
5             #ABSTRACT: XMLSchema compatible Moose types library
6             $Types::XMLSchema::VERSION = '0.01';
7 1     1   7 use warnings;
  1         1  
  1         24  
8 1     1   3 use strict;
  1         1  
  1         65  
9              
10             use Type::Library
11 0           -base,
12             -declare => [qw(
13             XsString
14             XsInteger
15             XsPositiveInteger
16             XsNonPositiveInteger
17             XsNegativeInteger
18             XsNonNegativeInteger
19             XsLong
20             XsUnsignedLong
21             XsInt
22             XsUnsignedInt
23             XsShort
24             XsUnsignedShort
25             XsByte
26             XsUnsignedByte
27             XsBoolean
28             XsFloat
29             XsDouble
30             XsDecimal
31             XsDuration
32             XsDateTime
33             XsTime
34             XsDate
35             XsGYearMonth
36             XsGYear
37             XsGMonthDay
38             XsGDay
39             XsGMonth
40             XsBase64Binary
41             XsAnyURI
42              
43             MathBigFloat
44             DateTimeDuration
45             DateTime
46             IOHandle
47             URI
48 1     1   197 )];
  0            
49             use Type::Utils -all;
50             use Types::Standard qw/
51             Int
52             Str
53             Bool
54             Num
55             ArrayRef
56             /;
57              
58             use Regexp::Common qw( number );
59             use MIME::Base64 qw( encode_base64 );
60             use Encode qw( encode );
61             use DateTime::Duration;
62             use DateTime::TimeZone;
63             use DateTime;
64             use IO::Handle;
65             use URI;
66             use Math::BigInt;
67             use Math::BigFloat;
68              
69              
70             my $MathBigInt = class_type { class => 'Math::BigInt' };
71             my $MathBigFloat = class_type { class => 'Math::BigFloat' };
72             my $DateTimeDuration = class_type { class => 'DateTime::Duration' };
73             my $DateTime = class_type { class => 'DateTime' };
74             my $IOHandle = class_type { class => 'IO::Handle' };
75             my $URI = class_type { class => 'URI' };
76              
77              
78             declare XsString =>
79             as Str;
80              
81              
82              
83             declare XsInteger =>
84             as $MathBigInt,
85             where { ! $_->is_nan && ! $_->is_inf };
86              
87             coerce XsInteger
88             => from Int, via { Math::BigInt->new($_) }
89             => from Str, via { Math::BigInt->new($_) };
90              
91              
92             declare XsPositiveInteger => as $MathBigInt, where { $_ > 0 };
93             coerce XsPositiveInteger
94             => from Int, via { Math::BigInt->new($_) }
95             => from Str, via { Math::BigInt->new($_) };
96              
97              
98             declare XsNonPositiveInteger => as $MathBigInt, where { $_ <= 0 };
99             coerce XsNonPositiveInteger
100             => from Int, via { Math::BigInt->new($_) }
101             => from Str, via { Math::BigInt->new($_) };
102              
103              
104             declare XsNegativeInteger => as $MathBigInt, where { $_ < 0 };
105             coerce XsNegativeInteger
106             => from Int, via { Math::BigInt->new($_) }
107             => from Str, via { Math::BigInt->new($_) };
108              
109              
110             declare XsNonNegativeInteger =>
111             as $MathBigInt,
112             where { $_ >= 0 };
113             coerce XsNonNegativeInteger
114             => from Int, via { Math::BigInt->new($_) }
115             => from Str, via { Math::BigInt->new($_) };
116              
117              
118             {
119             my $min = Math::BigInt->new('-9223372036854775808');
120             my $max = Math::BigInt->new('9223372036854775807');
121              
122             declare XsLong =>
123             as $MathBigInt,
124             where { $_ <= $max && $_ >= $min };
125             coerce XsLong
126             => from Int, via { Math::BigInt->new($_) }
127             => from Str, via { Math::BigInt->new($_) };
128             }
129              
130              
131             {
132             my $max = Math::BigInt->new('18446744073709551615');
133              
134             declare XsUnsignedLong =>
135             as $MathBigInt,
136             where { $_ >= 0 && $_ <= $max };
137             coerce XsUnsignedLong
138             => from Int, via { Math::BigInt->new($_) }
139             => from Str, via { Math::BigInt->new($_) };
140             }
141              
142              
143             declare XsInt =>
144             as Int,
145             where { $_ <= 2147483647 && $_ >= -2147483648 };
146              
147              
148             declare XsUnsignedInt =>
149             as Int,
150             where { $_ <= 4294967295 && $_ >= 0};
151              
152              
153             declare XsShort =>
154             as Int,
155             where { $_ <= 32767 && $_ >= -32768 };
156              
157              
158             declare XsUnsignedShort =>
159             as Int,
160             where { $_ <= 65535 && $_ >= 0 };
161              
162              
163             declare XsByte =>
164             as Int,
165             where { $_ <= 127 && $_ >= -128 };
166              
167              
168             declare XsUnsignedByte =>
169             as Int,
170             where { $_ <= 255 && $_ >= 0 };
171              
172              
173             declare XsBoolean =>
174             as Bool;
175              
176              
177              
178             {
179             my $m = Math::BigFloat->new(2 ** 24);
180             my $min = $m * Math::BigFloat->new(2 ** -149);
181             my $max = $m * Math::BigFloat->new(2 ** 104);
182              
183             declare XsFloat =>
184             as $MathBigFloat,
185             where { $_->is_nan || $_->is_inf || ( $_ <= $max && $_ >= $min ) };
186             coerce XsFloat
187             => from Num, via { Math::BigFloat->new($_) }
188             => from Str, via { Math::BigFloat->new($_) };
189             }
190              
191              
192             {
193             my $m = Math::BigFloat->new(2 ** 53);
194             my $min = $m * Math::BigFloat->new(2 ** -1075);
195             my $max = $m * Math::BigFloat->new(2 ** 970);
196              
197             declare XsDouble =>
198             as $MathBigFloat,
199             where { $_->is_nan || $_->is_inf || ( $_ < $max && $_ > $min ) };
200             coerce XsDouble
201             => from Num, via { Math::BigFloat->new($_) }
202             => from Str, via { Math::BigFloat->new($_) };
203             }
204              
205              
206             declare XsDecimal =>
207             as $MathBigFloat,
208             where { ! $_->is_nan && ! $_->is_inf };
209             coerce XsDecimal
210             => from Num, via { Math::BigFloat->new($_) }
211             => from Str, via { Math::BigFloat->new($_) };
212              
213              
214              
215             declare XsDuration =>
216             as Str,
217             where { /^\-?P\d+Y\d+M\d+DT\d+H\d+M\d+(?:\.\d+)?S$/ };
218              
219             coerce XsDuration
220             => from $DateTimeDuration =>
221             via {
222             my $is_negative;
223             if ($_->is_negative) {
224             $is_negative = 1;
225             $_ = $_->inverse;
226             }
227             my ($s, $ns) = $_->in_units(qw(
228             seconds
229             nanoseconds
230             ));
231             if ( int($ns) ) {
232             $s = sprintf("%d.%09d", $s, $ns);
233             $s =~ s/0+$//;
234             }
235             return sprintf('%sP%dY%dM%dDT%dH%dM%sS',
236             $is_negative ? '-' : '',
237             $_->in_units(qw(
238             years
239             months
240             days
241             hours
242             minutes
243             )),
244             $s
245             );
246             };
247              
248              
249              
250             declare XsDateTime =>
251             as Str,
252             where { /^\-?\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?(?:[\-\+]\d{2}:?\d{2})?$/ };
253              
254             coerce XsDateTime
255             => from $DateTime =>
256             via {
257             my $datetime = $_->strftime( $_->nanosecond ? "%FT%T.%N" : "%FT%T");
258             $datetime =~ s/0+$// if $_->nanosecond;
259             my $tz = $_->time_zone;
260              
261             return $datetime if $tz->is_floating;
262             return $datetime .'Z' if $tz->is_utc;
263              
264             if ( DateTime::TimeZone->offset_as_string($_->offset) =~
265             /^([\+\-]\d{2})(\d{2})/ ) {
266             return "$datetime$1:$2";
267             }
268             return $datetime;
269             };
270              
271              
272              
273             declare XsTime =>
274             as Str,
275             where { /^\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?(?:[\-\+]\d{2}:?\d{2})?$/ };
276              
277             coerce XsTime
278             => from $DateTime =>
279             via {
280             my $time = $_->strftime( $_->nanosecond ? "%T.%N" : "%T");
281             $time =~ s/0+$// if $_->nanosecond;
282             my $tz = $_->time_zone;
283              
284             return $time if $tz->is_floating;
285             return $time .'Z' if $tz->is_utc;
286              
287             if ( DateTime::TimeZone->offset_as_string($_->offset) =~
288             /^([\+\-]\d{2})(\d{2})/ ) {
289             return "$time$1:$2";
290             }
291             return $time;
292             };
293              
294              
295              
296             declare XsDate =>
297             as Str,
298             where { /^\-?\d{4}\-\d{2}\-\d{2}Z?(?:[\-\+]\d{2}:?\d{2})?$/ };
299              
300             coerce XsDate
301             => from $DateTime =>
302             via {
303             my $date = $_->strftime("%F");
304             my $tz = $_->time_zone;
305              
306             return $date if $tz->is_floating;
307             return $date .'Z' if $tz->is_utc;
308              
309             if ( DateTime::TimeZone->offset_as_string($_->offset) =~
310             /^([\+\-]\d{2})(\d{2})/ ) {
311             return "$date$1:$2";
312             }
313             return $date;
314              
315             };
316              
317              
318              
319             declare __XsIntPair =>
320             as ArrayRef[Int] =>
321             where { @$_ == 2 };
322              
323              
324             declare XsGYearMonth =>
325             as Str,
326             where { /^\d{4}\-\d{2}$/ };
327              
328             coerce XsGYearMonth
329             => from __XsIntPair =>
330             via {
331             return sprintf("%02d-%02d", @$_);
332             }
333             => from $DateTime =>
334             via {
335             return $_->strftime("%Y-%m");
336             };
337              
338              
339              
340             declare XsGYear =>
341             as Str,
342             where { /^\d{4}$/ };
343              
344             coerce XsGYear
345             => from $DateTime =>
346             via {
347             return $_->strftime("%Y");
348             };
349              
350              
351              
352             declare XsGMonthDay =>
353             as Str,
354             where { /^\-\-\d{2}\-\d{2}$/ };
355              
356             coerce XsGMonthDay
357             => from __XsIntPair =>
358             via {
359             return sprintf("--%02d-%02d", @$_);
360             }
361             => from $DateTime =>
362             via {
363             return $_->strftime("--%m-%d");
364             };
365              
366              
367              
368             declare XsGDay =>
369             as Str,
370             where { /^\-\-\-\d{2}$/ };
371              
372             coerce XsGDay
373             => from Int,
374             via {
375             return sprintf("---%02d", $_);
376             }
377             => from $DateTime =>
378             via {
379             return $_->strftime("---%d");
380             };
381              
382              
383              
384             declare XsGMonth =>
385             as Str,
386             where { $_ => /^\-\-\d{2}$/ };
387              
388             coerce XsGMonth
389             => from Int,
390             via {
391             return sprintf("--%02d", $_);
392             }
393             => from $DateTime =>
394             via {
395             return $_->strftime("--%m");
396             };
397              
398              
399              
400             declare XsBase64Binary =>
401             as Str,
402             where { $_ =~ /^[a-zA-Z0-9=\+\/]+$/m };
403              
404             coerce XsBase64Binary
405             => from $IOHandle =>
406             via {
407             local $/;
408             my $content = <$_>;
409             return encode_base64(encode("UTF-8", $content));
410             };
411              
412              
413              
414             declare XsAnyURI =>
415             as Str,
416             where { $_ =~ /^\w+:\/\/.*$/ };
417              
418             coerce XsAnyURI
419             => from $URI,
420             via {
421             return $_->as_string;
422             };
423              
424              
425             1; # End of Types::XMLSchema
426              
427             __END__