File Coverage

blib/lib/AnyEvent/Sereal.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1 1     1   69914 use strict;
  1         2  
  1         32  
2 1     1   5 use warnings;
  1         2  
  1         44  
3             package AnyEvent::Sereal;
4             {
5             $AnyEvent::Sereal::VERSION = '0.004';
6             }
7              
8 1     1   5 use AnyEvent ();
  1         1  
  1         15  
9 1     1   1162 use AnyEvent::Handle;
  1         7532  
  1         55  
10              
11             our $SERIALIZED_MAX_SIZE = 1_000_000; # bytes
12              
13             {
14             package # hide from pause
15             AnyEvent::Handle;
16              
17 1     1   12 use Sereal::Encoder 0.09 ();
  1         34  
  1         20  
18 1     1   6 use Sereal::Decoder 0.09 ();
  1         27  
  1         134  
19              
20             # push_write(sereal => $data, [$options])
21             register_write_type(
22             sereal => sub
23             {
24             my $self = shift;
25             my $data = shift;
26              
27             # When options are passed, we will create a new encoder instance
28             undef $self->{_sereal_encoder} if @_;
29              
30             pack("w/a*",
31             ($self->{_sereal_encoder} ||= Sereal::Encoder::->new(@_))
32             ->encode($data));
33             });
34              
35             # push_read(sereal => [$sereal_options], $cb->($hdl, $data))
36             register_read_type(
37             sereal => sub
38             {
39             my $self = shift;
40             my $cb = shift;
41              
42             # When options are passed, we will create a new decoder instance
43             undef $self->{_sereal_decoder} if @_;
44              
45             $self->{_sereal_decoder} ||= Sereal::Decoder::->new(@_);
46              
47             return sub
48             {
49             # when we can use 5.10 we can use ".", but for 5.8 we
50             # use the re-pack method
51 1     1   5 defined(my $len = eval { no warnings 'uninitialized';
  1         2  
  1         339  
52             unpack "w", $_[0]{rbuf} })
53             or return;
54              
55             if ($len > $AnyEvent::Sereal::SERIALIZED_MAX_SIZE)
56             {
57             $_[0]->_error(Errno::E2BIG);
58             return;
59             }
60              
61             my $format = length pack "w", $len;
62              
63             if ($format + $len <= length $_[0]{rbuf})
64             {
65             my $data = substr($_[0]{rbuf}, $format, $len);
66             substr($_[0]{rbuf}, 0, $format + $len, '');
67              
68             my $dec;
69             eval { $dec = $_[0]{_sereal_decoder}->decode($data); 1 }
70             or return $_[0]->_error(Errno::EBADMSG);
71              
72             $cb->($_[0], $dec);
73             }
74             else
75             {
76             # remove prefix
77             substr($_[0]{rbuf}, 0, $format, '');
78              
79             # read remaining chunk
80             $_[0]->unshift_read(
81             chunk => $len, sub
82             {
83             my $dec;
84             eval { $dec = $_[0]{_sereal_decoder}->decode($_[1]);
85             1 } or return $_[0]->_error(Errno::EBADMSG);
86              
87             $cb->($_[0], $dec);
88             });
89             }
90              
91             return 1;
92             };
93             });
94             }
95              
96             1;
97             __END__