File Coverage

blib/lib/PDL/IO/Sereal.pm
Criterion Covered Total %
statement 100 115 86.9
branch 30 68 44.1
condition 8 24 33.3
subroutine 18 18 100.0
pod 2 2 100.0
total 158 227 69.6


line stmt bran cond sub pod time code
1             package PDL::IO::Sereal;
2              
3 2     2   166503 use strict;
  2         2  
  2         47  
4 2     2   6 use warnings;
  2         1  
  2         151  
5              
6             require Exporter;
7             our @ISA = qw(Exporter);
8             our @EXPORT_OK = qw(rsereal wsereal);
9             our %EXPORT_TAGS = (all => \@EXPORT_OK);
10              
11             our $VERSION = '0.003';
12              
13 2 50   2   11 use constant DEBUG => $ENV{PDL_IO_SEREAL_DEBUG} ? 1 : 0;
  2         2  
  2         94  
14              
15 2     2   552 use PDL;
  2         9  
  2         9  
16 2     2   152455 use PDL::Types;
  2         3  
  2         182  
17 2     2   8 use PDL::IO::Misc qw(bswap2 bswap4 bswap8);
  2         3  
  2         8  
18 2     2   116 use Sereal::Encoder qw(encode_sereal);
  2         2  
  2         92  
19 2     2   6 use Sereal::Decoder qw(decode_sereal);
  2         4  
  2         95  
20 2     2   6 use Scalar::Util qw(looks_like_number);
  2         2  
  2         68  
21              
22 2     2   12 use Carp;
  2         3  
  2         112  
23             $Carp::Internal{ (__PACKAGE__) }++;
24              
25             sub import {
26 2     2   14 my $package = shift;
27             {
28 2     2   6 no strict 'refs';
  2         2  
  2         1590  
  2         2  
29 2 100       6 *{'PDL::wsereal'} = \&wsereal if grep { /^(:all|wsereal)$/ } @_;
  1         4  
  1         8  
30 2         2 *{'PDL::FREEZE'} = \&_FREEZE;
  2         8  
31 2         2 *{'PDL::THAW'} = \&_THAW;
  2         6  
32             }
33 2 100       1733 __PACKAGE__->export_to_level(1, $package, @_) if @_;
34             }
35              
36             sub wsereal {
37 1     1 1 37565 my ($pdl, $filename) = @_;
38 1         34 my $sereal = encode_sereal($pdl, {freeze_callbacks=>1, compress=>Sereal::Encoder::SRL_ZLIB});
39 1         11 _write_file($filename, $sereal);
40 1         5 return $pdl;
41             }
42              
43             sub rsereal {
44 1     1 1 6 my $filename = shift;
45 1         5 my $sereal = _read_file($filename);
46 1         60797 my $pdl = decode_sereal($sereal);
47 1         5 return $pdl;
48             }
49              
50             sub _FREEZE {
51 2     2   6 my ($self, $serializer) = @_;
52 2         13 my $ref = $self->get_dataref;
53 2         17 my $out = {
54             version => 1,
55             dims => [$self->dims],
56             type_name => $self->type->ioname,
57             type_size => PDL::Core::howbig($self->type),
58             packed_data => $$ref,
59             native_one => pack('L', 1),
60             };
61 2 50       3638 if (ref $self->hdr eq 'HASH') {
62 2         6 $out->{hash_hdr} = $self->hdr;
63             }
64 2 50       18 if ($self->isa("HASH")) {
65 0         0 for (keys %$self) {
66 0 0       0 next if $_ eq 'PDL'; # "PDL" is reserved
67 0         0 $out->{hash_main}{$_} = $self->{$_};
68             }
69             }
70 2 50       38 if ($self->badflag) {
71 0         0 $out->{bad_flag} = $self->badflag;
72 0         0 $out->{bad_value} = $self->badvalue;
73             }
74 2 50       9 $out->{hdrcpy_flag} = 1 if $self->hdrcpy;
75 2         445979 return $out;
76             }
77              
78             sub _THAW {
79 2     2   7 my ($class, $serializer, $data) = @_;
80 2 50 33     22 croak "THAW: bad input data" unless ref $data eq 'HASH' && looks_like_number($data->{version});
81 2 50       6 if ($data->{version} == 1) {
82 2 50 33     10 croak "THAW: invalid type_name" unless defined $data->{type_name} && !ref $data->{type_name};
83 2 50 33     10 croak "THAW: invalid type_size" unless defined $data->{type_size} && looks_like_number($data->{type_size});
84 2 50       6 croak "THAW: invalid dims" unless ref $data->{dims} eq 'ARRAY';
85 2 50 33     15 croak "THAW: invalid native_one" unless defined $data->{native_one} && !ref $data->{native_one};
86 2 50 33     8 croak "THAW: invalid packed_data" unless defined $data->{packed_data} && !ref $data->{packed_data};
87 2         16 my $type = PDL::Type->new($data->{type_name});
88 2 50       44 croak "THAW: unsupported type" unless $type;
89 2         51 my $type_sz = PDL::Core::howbig($type);
90 2 50       20 croak "THAW: type '$data->{type_name}' size mismatch ($type_sz != $data->{type_size})" unless $type_sz == $data->{type_size};
91 2         9 my $native_one = unpack('L', $data->{native_one});
92 2 50 33     10 croak "THAW: unknown endianness" unless $native_one == 0x01000000 || $native_one == 0x00000001;
93 2 50       4 my $do_swap = $native_one == 0x01000000 ? 1 : 0;
94 2         3 my $pdl = PDL::new_from_specification($class, $type, @{$data->{dims}});
  2         7  
95 2         85 my $dataref = $pdl->get_dataref;
96 2 50       8 croak "THAW: data size mismatch" unless length $$dataref == length $data->{packed_data};
97 2         3 $$dataref = $data->{packed_data};
98 2 50 33     7 if ($do_swap && $type_sz > 1) {
99 0 0       0 bswap2($pdl) if($type_sz==2);
100 0 0       0 bswap4($pdl) if($type_sz==4);
101 0 0       0 bswap8($pdl) if($type_sz==8);
102             }
103 2         4 $pdl->upd_data;
104 2 50       6 if (ref $data->{hash_hdr} eq "HASH") {
105 2         6 $pdl->sethdr($data->{hash_hdr});
106             }
107 2 50 33     12 if ($pdl->isa("HASH") && ref $data->{hash_main} eq "HASH") {
108 0         0 for (keys %{$data->{hash_main}}) {
  0         0  
109 0 0       0 next if $_ eq 'PDL'; # "PDL" is reserved
110 0         0 $pdl->{$_} = $data->{hash_main}{$_};
111             }
112             }
113 2 50       4 if ($data->{bad_flag}) {
114 0         0 $pdl->badflag($data->{bad_flag});
115 0 0       0 $pdl->badvalue($data->{bad_value}) if defined $data->{bad_value};
116             }
117 2 50       4 $pdl->hdrcpy(1) if $data->{hdrcpy_flag};
118 2         17 return $pdl;
119             }
120             else {
121 0         0 croak "THAW: invalid version";
122             }
123             }
124              
125             sub _read_file {
126 1     1   2 my ($filename) = @_;
127 1 50       34 open my $fh, '<', $filename or croak "rsereal: cannot open '$filename': $!";
128 1         1 my $rv;
129 1         2 my $data = '';
130 1         44 while ($rv = sysread($fh, my $buffer, 102400, 0)) {
131 55         3746 $data .= $buffer
132             }
133 1 50       5 croak "rsereal: cannot read file '$filename': $!" if !defined $rv;
134 1         2451 return $data;
135             }
136              
137             sub _write_file {
138 1     1   968 my ($filename, $data) = @_;
139 1 50       159 open my $fh, '>', $filename or croak "wsereal: cannot open '$filename': $!";
140 1         12180 my $rv = syswrite($fh, $data);
141 1 50       56 croak "wsereal: cannot write '$filename': $!" if !defined $rv;
142             }
143              
144             1;
145              
146             __END__