File Coverage

blib/lib/AnyEvent/Digest.pm
Criterion Covered Total %
statement 79 95 83.1
branch 23 26 88.4
condition 5 8 62.5
subroutine 18 24 75.0
pod 6 6 100.0
total 131 159 82.3


line stmt bran cond sub pod time code
1             package AnyEvent::Digest;
2              
3 7     7   5853 use strict;
  7         11  
  7         316  
4 7     7   36 use warnings;
  7         13  
  7         349  
5              
6             # ABSTRACT: A tiny AnyEvent wrapper for Digest::*
7             our $VERSION = 'v0.0.5'; # VERSION
8              
9 7     7   39 use Carp;
  7         13  
  7         557  
10 7     7   7178 use AnyEvent;
  7         36660  
  7         232  
11 7     7   54 use Scalar::Util qw(refaddr);
  7         12  
  7         9664  
12              
13             my $AIO_DISABLED;
14 7     7   3933 eval 'use AnyEvent::AIO';
  6         33267  
  6         324  
15             $AIO_DISABLED = 1 if $@;
16 7     7   73 eval 'use IO::AIO';
  6         14  
  6         1436  
17             $AIO_DISABLED = 1 if $@;
18              
19             # Most methods are falled back to Digest
20             our $AUTOLOAD;
21             sub AUTOLOAD
22             {
23 4     4   1450 my $self = shift;
24 4         13 my $called = $AUTOLOAD;
25 4         57 $called =~ s/.*:://;
26 4 100       107 croak "AnyEvent::Digest: Unknown method `$called' is called for `".ref($self->{base})."'" unless $self->{base}->can($called);
27 3         69 $self->{base}->$called(@_);
28             }
29              
30 0     0   0 sub DESTROY {}
31              
32             sub _by_idle
33             {
34 2     2   5 my ($self, $cv, $work) = @_;
35 2         5 my $call; $call = sub {
36 8194 100   8194   15954 if($work->()) {
37 8192         23433 my $w; $w = AE::idle sub {
38 8192         106459 undef $w;
39 8192         16522 $call->();
40 8192         144019 };
41             } else {
42 2         109 undef $call;
43 2         31 $cv->send($self);
44             }
45 2         35 };
46 2         6 $call->();
47             }
48              
49             sub _file_by_idle
50             {
51 2     2   7 my ($self, $cv, $fh, $work) = @_;
52             $self->_by_idle($cv, sub {
53 8194     8194   6393701 my $ret = read $fh, my $dat, $self->{unit};
54 8194 100       25787 return $cv->croak("AnyEvent::Digest: Read error occurs") unless defined($ret);
55 8193         21244 return $work->($dat);
56 2         22 });
57             }
58              
59             sub _file_by_aio
60             {
61 1     1   8 my ($self, $cv, $fh, $work) = @_;
62             # my $size = 0;
63 1         16 my $call; $call = sub {
64 8212     8212   20522 my $dat = ''; # If not initialized, "Use of uninitialized value in subroutine entry" issued.
65             IO::AIO::aio_read($fh, undef, $self->{unit}, $dat, 0, sub {
66 8212 50       5354516 return $cv->croak("AnyEvent::Digest: Read error occurs") if $_[0] < 0;
67             # $size += $_[0];
68 8212 100       29355 if($work->($dat)) {
69             #print STDERR "0: $size $_[0] ",length($dat),"\n";
70 8211         31520 $call->();
71             } else {
72             #print STDERR "1: $size $_[0] ",length($dat),"\n";
73 1         5 undef $call;
74 1         86 $cv->send($self);
75             }
76 8212         2017092 });
77 1         12 };
78 1         5 $call->();
79             }
80              
81             my %dispatch = (
82             idle => \&_file_by_idle,
83             aio => \&_file_by_aio,
84             );
85              
86             sub _dispatch
87             {
88 3     3   23 my $method = $dispatch{$_[0]->{backend}};
89 3 50       17 croak "AnyEvent::Digest: Unknown backend `$_[0]->{backend}' is specified" unless defined $method;
90 3         17 return $method->(@_);
91             }
92              
93             sub new
94             {
95 8     8 1 16221 my ($class, $base, %args) = @_;
96 8   33     335 $class = ref $class || $class;
97 8   50     122 $args{unit} ||= 65536;
98 8 100       48 $args{backend} = 'idle' unless defined $args{backend};
99 8 100 100     131 croak "AnyEvent::Digest: `aio' backend requires `IO::AIO' and `AnyEvent::AIO'" if $args{backend} eq 'aio' && $AIO_DISABLED;
100 6 100       62 croak "AnyEvent::Digest: Unknown backend `$args{backend}' is specified" unless exists $dispatch{$args{backend}};
101 5 100       783 eval "require $base" or croak "AnyEvent::Digest: Unknown base digest module `$base' is specified";
102 4         88 return bless {
103 8         99 base => $base->new(@{$args{opts}}),
104 4         32 map { $_, $args{$_} } qw(backend unit),
105             }, $class;
106             }
107              
108             sub add_async
109             {
110 0     0 1 0 my $self = shift;
111 0         0 my $cv = AE::cv;
112 0         0 my (@dat) = @_;
113             $self->_by_idle($cv, sub {
114 0     0   0 my $dat = shift @dat;
115 0         0 $self->{base}->add($dat);
116 0         0 return scalar @dat;
117 0         0 });
118 0         0 return $cv;
119             }
120              
121             sub addfile_async
122             {
123 4     4 1 22388 my ($self, $target, $mode) = @_;
124 4         124 my $cv = AE::cv;
125 4         8877 my $fh;
126 4 100       32 if(ref $target) {
127 3         14 $fh = $target;
128             } else {
129 1 50       47 open $fh, '<:raw', $target or croak "AnyEvent::Digest: Open error occurs for `$target'";
130             }
131             $self->_dispatch($cv, $fh, sub {
132 16405     16405   54128 my $dat = shift;
133 16405 100       54677 if(! length $dat) {
134 2         1212 close $fh;
135 2         19 return;
136             }
137 16403         6107799 $self->{base}->add($dat);
138 3         50 });
139 3         306 return $cv;
140             }
141              
142             sub addfile
143             {
144 0     0 1   return shift->addfile_async(@_)->recv;
145             }
146              
147             sub addfile_base
148             {
149 0     0 1   return shift->{base}->addfile(@_);
150             }
151              
152             sub add_bits_async
153             {
154 0     0 1   my $self = shift;
155 0           my $cv = AE::cv;
156 0           $self->{base}->add_bits(@_);
157 0           $cv->send($self);
158 0           return $cv;
159             }
160              
161             1;
162              
163             __END__