File Coverage

blib/lib/Avro/Schema.pm
Criterion Covered Total %
statement 356 398 89.4
branch 150 202 74.2
condition 78 120 65.0
subroutine 60 63 95.2
pod 0 4 0.0
total 644 787 81.8


line stmt bran cond sub pod time code
1             # Licensed to the Apache Software Foundation (ASF) under one
2             # or more contributor license agreements. See the NOTICE file
3             # distributed with this work for additional information
4             # regarding copyright ownership. The ASF licenses this file
5             # to you under the Apache License, Version 2.0 (the
6             # "License"); you may not use this file except in compliance
7             # with the License. You may obtain a copy of the License at
8             #
9             # https://www.apache.org/licenses/LICENSE-2.0
10             #
11             # Unless required by applicable law or agreed to in writing,
12             # software distributed under the License is distributed on an
13             # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14             # KIND, either express or implied. See the License for the
15             # specific language governing permissions and limitations
16             # under the License.
17              
18             use strict;
19 6     6   3264 use warnings;
  6         21  
  6         174  
20 6     6   27  
  6         11  
  6         131  
21             use Carp;
22 6     6   26 use JSON::XS();
  6         6  
  6         355  
23 6     6   2962 use Try::Tiny;
  6         21854  
  6         120  
24 6     6   2096  
  6         8600  
  6         4494  
25             our $VERSION = '1.11.1';
26              
27             my $json = JSON::XS->new->allow_nonref;
28              
29             my $schema = shift;
30             my $json_string = shift;
31 70     70 0 20701 my $names = shift || {};
32 70         99 my $namespace = shift || "";
33 70   50     241  
34 70   50     189 my $struct = try {
35             $json->decode($json_string);
36             }
37 70     70   4332 catch {
38             throw Avro::Schema::Error::Parse(
39             "Cannot parse json string: $_"
40 4     4   62 );
41             };
42             return $schema->parse_struct($struct, $names, $namespace);
43 70         363 }
44 66         911  
45             my $class = shift;
46             my $struct = shift;
47             return $json->encode($struct);
48 10     10 0 18 }
49 10         15  
50 10         109 my $schema = shift;
51             my $struct = shift;
52             my $names = shift || {};
53             my $namespace = shift || "";
54 227     227 0 654  
55 227         245 ## 1.3.2 A JSON object
56 227   100     392 if (ref $struct eq 'HASH') {
57 227   100     507 my $type = $struct->{type}
58             or throw Avro::Schema::Error::Parse("type is missing");
59             if ( Avro::Schema::Primitive->is_type_valid($type) ) {
60 227 100       471 return Avro::Schema::Primitive->new(type => $type);
    100          
61             }
62 87 50       210 ## XXX technically we shouldn't allow error type other than in
63 87 100       211 ## a Protocol definition
64 11         28 if ($type eq 'record' or $type eq 'error') {
65             return Avro::Schema::Record->new(
66             struct => $struct,
67             names => $names,
68 76 100 100     331 namespace => $namespace,
    100          
    100          
    100          
    50          
69 23         80 );
70             }
71             elsif ($type eq 'enum') {
72             return Avro::Schema::Enum->new(
73             struct => $struct,
74             names => $names,
75             namespace => $namespace,
76 6         26 );
77             }
78             elsif ($type eq 'array') {
79             return Avro::Schema::Array->new(
80             struct => $struct,
81             names => $names,
82             namespace => $namespace,
83 19         85 );
84             }
85             elsif ($type eq 'map') {
86             return Avro::Schema::Map->new(
87             struct => $struct,
88             names => $names,
89             namespace => $namespace,
90 17         69 );
91             }
92             elsif ($type eq 'fixed') {
93             return Avro::Schema::Fixed->new(
94             struct => $struct,
95             names => $names,
96             namespace => $namespace,
97 11         31 );
98             }
99             else {
100             throw Avro::Schema::Error::Parse("unknown type: $type");
101             }
102             }
103             ## 1.3.2 A JSON array, representing a union of embedded types.
104 0         0 elsif (ref $struct eq 'ARRAY') {
105             return Avro::Schema::Union->new(
106             struct => $struct,
107             names => $names,
108             namespace => $namespace,
109 16         59 );
110             }
111             ## 1.3.2 A JSON string, naming a defined type.
112             else {
113             my $type = $struct;
114             ## It's one of our custom defined type
115            
116             ## Short name provided, prepend the namespace
117 124         145 if ( $type !~ /\./ ) {
118             my $fulltype = $namespace . '.' . $type;
119             if (exists $names->{$fulltype}) {
120             return $names->{$fulltype};
121 124 50       247 }
122 124         193 }
123 124 100       248
124 1         3 ## Fully-qualified name
125             if (exists $names->{$type}) {
126             return $names->{$type};
127             }
128            
129 123 100       199 ## It's a primitive type
130 11         20 return Avro::Schema::Primitive->new(type => $type);
131             }
132             }
133              
134 112         241 my $class = shift;
135             my %param = @_;
136              
137             my $reader = $param{reader}
138             or croak "missing reader schema";
139 1908     1908 0 5570 my $writer = $param{writer}
140 1908         3133 or croak "missing writer schema";
141              
142             my $wtype = ref $writer ? $writer->type : $writer;
143 1908 50       3133 my $rtype = ref $reader ? $reader->type : $reader;
144             ## 1.3.2 either schema is a union
145 1908 50       2743 return $wtype if $wtype eq 'union' or $rtype eq 'union';
146              
147 1908 50       3351 ## 1.3.2 both schemas have same primitive type
148 1908 50       2880 return $wtype if $wtype eq $rtype
149             && Avro::Schema::Primitive->is_type_valid($wtype);
150 1908 100 66     4739  
151             ## 1.3.2
152             ## int is promotable to long, float, or double
153 1905 100 100     3646 if ($wtype eq 'int' && (
154             $rtype eq 'float' or $rtype eq 'long' or $rtype eq 'double'
155             )) {
156             return $rtype;
157             }
158 592 50 66     902 ## long is promotable to float or double
      66        
159             if ($wtype eq 'long' && (
160             $rtype eq 'float' or $rtype eq 'double'
161 3         12 )) {
162             return $rtype;
163             }
164 589 100 66     876 ## float is promotable to double
      66        
165             if ($wtype eq 'float' && $rtype eq 'double') {
166             return $rtype;
167 1         3 }
168             return 0 unless $rtype eq $wtype;
169              
170 588 100 100     909 ## 1.3.2 {subtype and/or names} match
171 1         4 if ($rtype eq 'array') {
172             return $wtype if $class->match(
173 587 100       804 reader => $reader->items,
174             writer => $writer->items,
175             );
176 575 100       901 }
    100          
    100          
    100          
    50          
177 427 100       705 elsif ($rtype eq 'record') {
178             return $wtype if $reader->fullname eq $writer->fullname;
179             }
180             elsif ($rtype eq 'map') {
181             return $wtype if $class->match(
182             reader => $reader->values,
183 11 100       31 writer => $writer->values,
184             );
185             }
186 115 100       235 elsif ($rtype eq 'fixed') {
187             return $wtype if $reader->size eq $writer->size
188             && $reader->fullname eq $writer->fullname;
189             }
190             elsif ($rtype eq 'enum') {
191             return $wtype if $reader->fullname eq $writer->fullname;
192 14 100 66     25 }
193             return 0;
194             }
195              
196 8 100       13  
197             our @ISA = qw/Avro::Schema/;
198 7         26 use Carp;
199              
200             my $class = shift;
201             my %param = @_;
202              
203             my $type = $param{type};
204 6     6   43 if (!$type) {
  6         9  
  6         1395  
205             my ($t) = $class =~ /::([^:]+)$/;
206             $type = lc ($t);
207 226     226   257 }
208 226         350 my $schema = bless {
209             type => $type,
210 226         278 }, $class;
211 226 100       373 return $schema;
212 204         1113 }
213 204         420  
214             my $schema = shift;
215 226         451 return $schema->{type};
216             }
217              
218 226         452 my $schema = shift;
219             my $known_names = shift || {};
220             return Avro::Schema->to_string($schema->to_struct($known_names));
221             }
222 5252     5252   6671  
223 5252         7863 our @ISA = qw/Avro::Schema::Base/;
224             use Carp;
225             use Config;
226             use Regexp::Common qw/number/;
227 10     10   22  
228 10   50     40 my %PrimitiveType = map { $_ => 1 } qw/
229 10         28 null
230             boolean
231             int
232             long
233             float
234 6     6   36 double
  6         9  
  6         311  
235 6     6   39 bytes
  6         11  
  6         274  
236 6     6   2968 string
  6         13377  
  6         25  
237             /;
238              
239             my %Singleton = ( );
240              
241             ## FIXME: useless lazy generation
242             my $class = shift;
243             my %param = @_;
244              
245             my $type = $param{type}
246             or croak "Schema must have a type";
247              
248             throw Avro::Schema::Error::Parse("Not a primitive type $type")
249             unless $class->is_type_valid($type);
250              
251             if (! exists $Singleton{ $type } ) {
252             my $schema = $class->SUPER::new( type => $type );
253 126     126   155 $Singleton{ $type } = $schema;
254 126         257 }
255             return $Singleton{ $type };
256             }
257 126 50       239  
258             return $PrimitiveType{ $_[1] || "" };
259 126 100       213 }
260              
261             ## Returns true or false wheter the given data is valid for
262 125 100       249 ## this schema
263 22         77 my $schema = shift;
264 22         49 my $data = shift;
265             my $type = $schema->{type};
266 125         355 if ($type eq 'int') {
267             no warnings;
268             my $packed_int = pack "l", $data;
269             my $unpacked_int = unpack "l", $packed_int;
270 2101   50 2101   7751 return $unpacked_int eq $data ? 1 : 0;
271             }
272             if ($type eq 'long') {
273             if ($Config{use64bitint}) {
274             return 0 unless defined $data;
275             my $packed_int = pack "q", $data;
276 33     33   37 my $unpacked_int = unpack "q", $packed_int;
277 33         38 return $unpacked_int eq $data ? 1 : 0;
278 33         47  
279 33 100       58 }
280 6     6   19131 else {
  6         9  
  6         2398  
281 13         35 require Math::BigInt;
282 13         37 my $int = eval { Math::BigInt->new($data) };
283 13 100       35 if ($@) {
284             warn "probably a unblessed ref: $@";
285 20 100       42 return 0;
286 11 50       68 }
287 11 100       25 return 0 if $int->is_nan;
288 10         28 my $max = Math::BigInt->new( "0x7FFF_FFFF_FFFF_FFFF" );
289 10         24 return $int->bcmp($max) <= 0 ? 1 : 0;
290 10 100       37 }
291             }
292             if ($type eq 'float' or $type eq 'double') {
293             $data =~ /^$RE{num}{real}$/ ? return 1 : 0;
294 0         0 }
295 0         0 if ($type eq "bytes" or $type eq "string") {
  0         0  
296 0 0       0 return 1 unless !defined $data or ref $data;
297 0         0 }
298 0         0 if ($type eq 'null') {
299             return defined $data ? 0 : 1;
300 0 0       0 }
301 0         0 if ($type eq 'boolean') {
302 0 0       0 return 0 if ref $data; # sometimes risky
303             return 1 if $data =~ m{yes|no|y|n|t|f|true|false}i;
304             return 0;
305 9 100 66     43 }
306 1 50       5 return 0;
307             }
308 8 100 100     30  
309 5 100 100     24 my $schema = shift;
310             return $schema->type;
311 5 100       12 }
312 3 100       12  
313             our @ISA = qw/Avro::Schema::Base/;
314 2 50       7 use Scalar::Util;
315 0 0       0  
316 0 0       0 my %NamedType = map { $_ => 1 } qw/
317 0         0 record
318             enum
319 2         6 fixed
320             /;
321              
322             my $class = shift;
323 10     10   13 my %param = @_;
324 10         17  
325             my $schema = $class->SUPER::new(%param);
326              
327             my $names = $param{names} || {};
328             my $struct = $param{struct} || {};
329 6     6   43 my $name = $struct->{name};
  6         9  
  6         4069  
330             unless (defined $name && length $name) {
331             throw Avro::Schema::Error::Parse( "Missing name for $class" );
332             }
333             my $namespace = $struct->{namespace};
334             unless (defined $namespace && length $namespace) {
335             $namespace = $param{namespace};
336             }
337              
338 152     152   182 $schema->set_names($namespace, $name);
339 152         279 $schema->add_name($names);
340              
341 152         330 return $schema;
342             }
343 152   50     311  
344 152   50     246 return $NamedType{ $_[1] || "" };
345 152         197 }
346 152 50 33     462  
347 0         0 my $schema = shift;
348             my ($namespace, $name) = @_;
349 152         180  
350 152 100 66     308 my @parts = split /\./, ($name || ""), -1;
351 111         146 if (@parts > 1) {
352             $name = pop @parts;
353             $namespace = join ".", @parts;
354 152         347 if (grep { ! length $_ } @parts) {
355 80         177 throw Avro::Schema::Error::Name(
356             "name '$name' is not a valid name"
357 80         151 );
358             }
359             }
360              
361 36   50 36   109 ## 1.3.2 The name portion of a fullname, and record field names must:
362             ## * start with [A-Za-z_]
363             ## * subsequently contain only [A-Za-z0-9_]
364             my $type = $schema->{type};
365 152     152   171 unless (length $name && $name =~ m/^[A-Za-z_][A-Za-z0-9_]*$/) {
366 152         242 throw Avro::Schema::Error::Name(
367             "name '$name' is not valid for $type"
368 152   100     404 );
369 152 100       281 }
370 13         18 if (defined $namespace && length $namespace) {
371 13         23 for (split /\./, $namespace, -1) {
372 13 100       21 unless ($_ && /^[A-Za-z_][A-Za-z0-9_]*$/) {
  20         48  
373 5         17 throw Avro::Schema::Error::Name(
374             "namespace '$namespace' is not valid for $type"
375             );
376             }
377             }
378             }
379             $schema->{name} = $name;
380             $schema->{namespace} = $namespace;
381             }
382 147         228  
383 147 100 100     632 my $schema = shift;
384 31         99 my ($names) = @_;
385              
386             my $name = $schema->fullname;
387             if ( exists $names->{ $name } ) {
388 116 100 100     292 throw Avro::Schema::Error::Parse( "Name $name is already defined" );
389 52         101 }
390 68 100 100     214 $names->{$name} = $schema;
391 36         115 Scalar::Util::weaken( $names->{$name} );
392             return;
393             }
394              
395             my $schema = shift;
396             return join ".",
397 80         151 grep { defined $_ && length $_ }
398 80         147 map { $schema->{$_ } }
399             qw/namespace name/;
400             }
401              
402 80     80   91 my $schema = shift;
403 80         109 return $schema->{namespace};
404             }
405 80         145  
406 80 50       190 our @ISA = qw/Avro::Schema::Named/;
407 0         0 use Scalar::Util;
408              
409 80         137 my %ValidOrder = map { $_ => 1 } qw/ascending descending ignore/;
410 80         252  
411 80         103 my $class = shift;
412             my %param = @_;
413              
414             my $names = $param{names} ||= {};
415 184     184   560 my $schema = $class->SUPER::new(%param);
416              
417 368 100       1226 my $fields = $param{struct}{fields}
418 184         254 or throw Avro::Schema::Error::Parse("Record must have Fields");
  368         686  
419              
420             throw Avro::Schema::Error::Parse("Record.Fields must me an array")
421             unless ref $fields eq 'ARRAY';
422              
423 75     75   98 my $namespace = $schema->namespace;
424 75         134  
425             my @fields;
426             for my $field (@$fields) {
427             my $f = Avro::Schema::Field->new($field, $names, $namespace);
428             push @fields, $f;
429 6     6   38 }
  6         11  
  6         12917  
430             $schema->{fields} = \@fields;
431             return $schema;
432             }
433              
434 135     135   37608 my $schema = shift;
435 135         273 my $known_names = shift || {};
436             ## consider that this record type is now known (will serialize differently)
437 135   100     443 my $fullname = $schema->fullname;
438 135         342 if ($known_names->{ $fullname }++) {
439             return $fullname;
440             }
441 63 50       142 return {
442             type => $schema->{type},
443 63 50       138 name => $fullname,
444             fields => [
445             map { $_->to_struct($known_names) } @{ $schema->{fields} }
446 63         115 ],
447             };
448 63         76 }
449 63         102  
450 83         185 my $schema = shift;
451 65         124 return $schema->{fields};
452             }
453 45         99  
454 45         228 my $schema = shift;
455             unless (exists $schema->{_fields_as_hash}) {
456             $schema->{_fields_as_hash} = {
457             map { $_->{name} => $_ } @{ $schema->{fields} }
458 6     6   10 };
459 6   100     12 }
460             return $schema->{_fields_as_hash};
461 6         9 }
462 6 100       15  
463 3         6 my $schema = shift;
464             my $data = shift;
465             for my $field (@{ $schema->{fields} }) {
466             my $key = $field->{name};
467             return 0 unless $field->is_data_valid($data->{$key});
468             }
469 3         6 return 1;
  6         10  
  3         5  
470             }
471              
472              
473             my $field = shift;
474             my $known_names = shift || {};
475 52     52   1540 my $type = $field->{type}->to_struct($known_names);
476 52         188 return { name => $field->{name}, type => $type };
477             }
478              
479             my $class = shift;
480 10     10   2009 my ($struct, $names, $namespace) = @_;
481 10 100       22  
482             my $name = $struct->{name};
483 4         6 throw Avro::Schema::Error::Parse("Record.Field.name is required")
  8         31  
  4         10  
484             unless defined $name && length $name;
485              
486 10         39 my $type = $struct->{type};
487             throw Avro::Schema::Error::Parse("Record.Field.name is required")
488             unless defined $type && length $type;
489              
490 2     2   3 $type = Avro::Schema->parse_struct($type, $names, $namespace);
491 2         3 my $field = { name => $name, type => $type };
492 2         2 #TODO: find where to weaken precisely
  2         5  
493 2         2 #Scalar::Util::weaken($struct->{type});
494 2 100       6  
495             if (exists $struct->{default}) {
496 1         3 my $is_valid = $type->is_data_valid($struct->{default});
497             my $t = $type->type;
498             throw Avro::Schema::Error::Parse(
499             "default value doesn't validate $t: '$struct->{default}'"
500             ) unless $is_valid;
501              
502 6     6   5 ## small Perlish special case
503 6   50     12 if ($type eq 'boolean') {
504 6         13 $field->{default} = $struct->{default} ? 1 : 0;
505 6         26 }
506             else {
507             $field->{default} = $struct->{default};
508             }
509 84     84   96 }
510 84         125 if (my $order = $struct->{order}) {
511             throw Avro::Schema::Error::Parse(
512 84         104 "Order '$order' is not valid'"
513 84 50 33     239 ) unless $ValidOrder{$order};
514             $field->{order} = $order;
515             }
516 84         114 return bless $field, $class;
517 84 50 33     240 }
518              
519             my $field = shift;
520 84         201 my $data = shift;
521 82         186 return 1 if $field->{type}->is_data_valid($data);
522             return 0;
523             }
524              
525 82 100       147 our @ISA = qw/Avro::Schema::Named/;
526 28         50  
527 28         265 my $class = shift;
528 28 100       110 my %param = @_;
529             my $schema = $class->SUPER::new(%param);
530             my $struct = $param{struct}
531             or throw Avro::Schema::Error::Parse("Enum instantiation");
532             my $symbols = $struct->{symbols} || [];
533 16 50       37  
534 0 0       0 unless (@$symbols) {
535             throw Avro::Schema::Error::Parse("Enum needs at least one symbol");
536             }
537 16         32 my %symbols;
538             my $pos = 0;
539             for (@$symbols) {
540 70 100       126 if (ref $_) {
541             throw Avro::Schema::Error::Parse(
542             "Enum.symbol should be a string"
543 7 100       30 );
544 3         5 }
545             throw Avro::Schema::Error::Parse("Duplicate symbol in Enum")
546 66         158 if exists $symbols{$_};
547              
548             $symbols{$_} = $pos++;
549             }
550 2     2   2 $schema->{hash_symbols} = \%symbols;
551 2         4 return $schema;
552 2 100       3 }
553 1         5  
554             my $schema = shift;
555             my $data = shift;
556             return 1 if defined $data && exists $schema->{hash_symbols}{$data};
557             return 0;
558             }
559              
560 6     6   12 my $schema = shift;
561 6         19 unless (exists $schema->{symbols}) {
562 6         30 my $sym = $schema->{hash_symbols};
563             $schema->{symbols} = [ sort { $sym->{$a} <=> $sym->{$b} } keys %$sym ];
564 6 50       24 }
565 6   50     17 return $schema->{symbols};
566             }
567 6 50       13  
568 0         0 my $schema = shift;
569             return $schema->{hash_symbols} || {};
570 6         8 }
571 6         10  
572 6         13 my $schema = shift;
573 15 50       35 my $known_names = shift || {};
574 0         0  
575             my $fullname = $schema->fullname;
576             if ($known_names->{ $fullname }++) {
577             return $fullname;
578             }
579 15 50       23 return {
580             type => 'enum',
581 15         27 name => $schema->fullname,
582             symbols => [ @{ $schema->symbols } ],
583 6         13 };
584 6         31 }
585              
586             our @ISA = qw/Avro::Schema::Base/;
587              
588 5     5   5 my $class = shift;
589 5         6 my %param = @_;
590 5 100 66     28 my $schema = $class->SUPER::new(%param);
591 2         16  
592             my $struct = $param{struct}
593             or throw Avro::Schema::Error::Parse("Enum instantiation");
594              
595 10     10   15 my $items = $struct->{items}
596 10 100       21 or throw Avro::Schema::Error::Parse("Array must declare 'items'");
597 3         6  
598 3         16 $items = Avro::Schema->parse_struct($items, $param{names}, $param{namespace});
  9         19  
599             $schema->{items} = $items;
600 10         36 return $schema;
601             }
602              
603             my $schema = shift;
604 5     5   7 my $default = shift;
605 5   50     15 return 1 if $default && ref $default eq 'ARRAY';
606             return 0;
607             }
608              
609 3     3   14 my $schema = shift;
610 3   100     8 return $schema->{items};
611             }
612 3         5  
613 3 50       10 my $schema = shift;
614 0         0 my $known_names = shift || {};
615              
616             return {
617             type => 'array',
618             items => $schema->{items}->to_struct($known_names),
619 3         6 };
  3         5  
620             }
621              
622             our @ISA = qw/Avro::Schema::Base/;
623              
624             my $class = shift;
625             my %param = @_;
626             my $schema = $class->SUPER::new(%param);
627 19     19   25  
628 19         50 my $struct = $param{struct}
629 19         74 or throw Avro::Schema::Error::Parse("Map instantiation");
630              
631             my $values = $struct->{values};
632 19 50       60 unless (defined $values && length $values) {
633             throw Avro::Schema::Error::Parse("Map must declare 'values'");
634             }
635 19 50       44 $values = Avro::Schema->parse_struct($values, $param{names}, $param{namespace});
636             $schema->{values} = $values;
637 19         47  
638 19         50 return $schema;
639 19         70 }
640              
641             my $schema = shift;
642             my $default = shift;
643 2     2   5 return 1 if $default && ref $default eq 'HASH';
644 2         2 return 0;
645 2 50 33     13 }
646 0         0  
647             my $schema = shift;
648             return $schema->{values};
649             }
650 2340     2340   2497  
651 2340         4000 my $schema = shift;
652             my $known_names = shift || {};
653              
654             return {
655 6     6   9 type => 'map',
656 6   50     14 values => $schema->{values}->to_struct($known_names),
657             };
658             }
659              
660 6         18 our @ISA = qw/Avro::Schema::Base/;
661              
662             my $class = shift;
663             my %param = @_;
664             my $schema = $class->SUPER::new(%param);
665             my $union = $param{struct}
666             or throw Avro::Schema::Error::Parse("Union.new needs a struct");
667              
668 17     17   26 my $names = $param{names} ||= {};
669 17         51  
670 17         87 my @schemas;
671             my %seen_types;
672             for my $struct (@$union) {
673 17 50       51 my $sch = Avro::Schema->parse_struct($struct, $names, $param{namespace});
674             my $type = $sch->type;
675 17         26  
676 17 50 33     77 ## 1.3.2 Unions may not contain more than one schema with the same
677 0         0 ## type, except for the named types record, fixed and enum. For
678             ## example, unions containing two array types or two map types are not
679 17         48 ## permitted, but two types with different names are permitted.
680 17         40 if (Avro::Schema::Named->is_type_valid($type)) {
681             $type = $sch->fullname; # resolve Named types to their name
682 17         62 }
683             ## XXX: I could define &type_name doing the correct resolution for all classes
684             if ($seen_types{ $type }++) {
685             throw Avro::Schema::Error::Parse(
686 1     1   2 "$type is present more than once in the union"
687 1         2 )
688 1 50 33     5 }
689 0         0 ## 1.3.2 Unions may not immediately contain other unions.
690             if ($type eq 'union') {
691             throw Avro::Schema::Error::Parse(
692             "Cannot embed unions in union"
693 786     786   975 );
694 786         1569 }
695             push @schemas, $sch;
696             }
697             $schema->{schemas} = \@schemas;
698 6     6   11  
699 6   50     13 return $schema;
700             }
701              
702             my $schema = shift;
703 6         16 return $schema->{schemas};
704             }
705              
706             my $schema = shift;
707             my $data = shift;
708             for my $type ( @{ $schema->{schemas} } ) {
709             if ( $type->is_data_valid($data) ) {
710             return 1;
711 16     16   23 }
712 16         42 }
713 16         69 return 0;
714             }
715 16 50       40  
716             my $schema = shift;
717 16   50     41 my $known_names = shift || {};
718             return [ map { $_->to_struct($known_names) } @{$schema->{schemas}} ];
719 16         22 }
720              
721 16         35 our @ISA = qw/Avro::Schema::Named/;
722 36         67  
723 36         70 my $class = shift;
724             my %param = @_;
725             my $schema = $class->SUPER::new(%param);
726              
727             my $struct = $param{struct}
728             or throw Avro::Schema::Error::Parse("Fixed instantiation");
729 36 100       63  
730 9         21 my $size = $struct->{size};
731             unless (defined $size && length $size) {
732             throw Avro::Schema::Error::Parse("Fixed must declare 'size'");
733 36 100       87 }
734 3         13 if (ref $size) {
735             throw Avro::Schema::Error::Parse(
736             "Fixed.size should be a scalar"
737             );
738             }
739 33 100       56 unless ($size =~ m{^\d+$} && $size > 0) {
740 1         3 throw Avro::Schema::Error::Parse(
741             "Fixed.size should be a positive integer"
742             );
743             }
744 32         54 # Cast into numeric so that it will be encoded as a JSON number
745             $schema->{size} = $size + 0;
746 12         44  
747             return $schema;
748 12         51 }
749              
750             my $schema = shift;
751             my $default = shift;
752 7     7   11 my $size = $schema->{size};
753 7         15 return 1 if $default && bytes::length $default == $size;
754             return 0;
755             }
756              
757 0     0   0 my $schema = shift;
758 0         0 return $schema->{size};
759 0         0 }
  0         0  
760 0 0       0  
761 0         0 my $schema = shift;
762             my $known_names = shift || {};
763              
764 0         0 my $fullname = $schema->fullname;
765             if ($known_names->{ $fullname }++) {
766             return $fullname;
767             }
768 0     0   0  
769 0   0     0 return {
770 0         0 type => 'fixed',
  0         0  
  0         0  
771             name => $fullname,
772             size => $schema->{size},
773             };
774             }
775              
776             use parent 'Error::Simple';
777 11     11   15  
778 11         29 use parent 'Error::Simple';
779 11         38  
780             use parent 'Error::Simple';
781              
782 11 50       29 1;