@@ -31,12 +31,149 @@ sub api {
3131 $self -> {api };
3232}
3333
34+ sub get_message {
35+ shift @{$_ [0]-> {_messages }};
36+ }
37+
38+ sub encode {
39+ my $self = shift ;
40+ return $self -> {api } == 3 ? $self -> _encode_resp3(@_ ) : $self -> _encode_resp2(@_ );
41+ }
42+
43+ sub on_message {
44+ my ($self , $cb ) = @_ ;
45+ $self -> {_on_message_cb } = $cb || \&_gather_messages;
46+ }
47+
48+ sub parse {
49+ my $self = shift ;
50+ return $self -> {api } == 3 ? $self -> _parse_resp3(@_ ) : $self -> _parse_resp2(@_ );
51+ }
52+
53+ sub _gather_messages {
54+ push @{$_ [0]-> {_messages }}, $_ [1];
55+ }
56+
3457my %simple_types = (' +' => 1, ' -' => 1, ' :' => 1);
58+
59+ sub _encode_resp2 {
60+ my $self = shift ;
61+
62+ my $encoded_message = ' ' ;
63+ while (@_ ) {
64+ my $message = shift ;
65+
66+ # Bulk string
67+ if ($message -> {type } eq ' $' ) {
68+ if (defined $message -> {data }) {
69+ $encoded_message .= ' $' . length ($message -> {data }) . " \r\n " . $message -> {data } . " \r\n " ;
70+ }
71+ else {
72+ $encoded_message .= " \$ -1\r\n " ;
73+ }
74+ }
75+ # Array (multi bulk)
76+ elsif ($message -> {type } eq ' *' ) {
77+ if (defined $message -> {data }) {
78+ $encoded_message .= ' *' . scalar (@{$message -> {data }}) . " \r\n " ;
79+ unshift @_ , @{$message -> {data }};
80+ }
81+ else {
82+ $encoded_message .= " *-1\r\n " ;
83+ }
84+ }
85+ # String, error, integer
86+ elsif (exists $simple_types {$message -> {type }}) {
87+ $encoded_message .= $message -> {type } . $message -> {data } . " \r\n " ;
88+ }
89+ else {
90+ Carp::croak(qq/ Unknown message type $message ->{type}/ );
91+ }
92+ }
93+
94+ return $encoded_message ;
95+ }
96+
97+ sub _parse_resp2 {
98+ my $self = shift ;
99+ $self -> {_buffer }.= shift ;
100+
101+ my $message = $self -> {_message } ||= {};
102+ my $buffer = \$self -> {_buffer };
103+
104+ CHUNK:
105+ while ((my $pos = index ($$buffer , " \r\n " )) != -1) {
106+ # Check our state: are we parsing new message or completing existing
107+ if (!$message -> {type }) {
108+ if ($pos < 1) {
109+ Carp::croak(qq/ Unexpected input "$$buffer "/ );
110+ }
111+
112+ $message -> {type } = substr $$buffer , 0, 1;
113+ $message -> {_argument } = substr $$buffer , 1, $pos - 1;
114+ substr $$buffer , 0, $pos + 2, ' ' ; # Remove type + argument + \r\n
115+ }
116+
117+ # Simple Strings, Errors, Integers
118+ if (exists $simple_types {$message -> {type }}) {
119+ $message -> {data } = delete $message -> {_argument };
120+ }
121+ # Bulk Strings
122+ elsif ($message -> {type } eq ' $' ) {
123+ if ($message -> {_argument } eq ' -1' ) {
124+ $message -> {data } = undef ;
125+ }
126+ elsif (length ($$buffer ) >= $message -> {_argument } + 2) {
127+ $message -> {data } = substr $$buffer , 0, $message -> {_argument }, ' ' ;
128+ substr $$buffer , 0, 2, ' ' ; # Remove \r\n
129+ }
130+ else {
131+ return # Wait more data
132+ }
133+ }
134+ # Arrays
135+ elsif ($message -> {type } eq ' *' ) {
136+ if ($message -> {_argument } eq ' -1' ) {
137+ $message -> {data } = undef ;
138+ } else {
139+ $message -> {data } = [];
140+ if ($message -> {_argument } > 0) {
141+ $message = $self -> {_message } = {_parent => $message };
142+ next ;
143+ }
144+ }
145+ }
146+ # Invalid input
147+ else {
148+ Carp::croak(qq/ Unexpected input "$self ->{_message}{type}"/ );
149+ }
150+
151+ delete $message -> {_argument };
152+ delete $self -> {_message };
153+
154+ # Fill parents with data
155+ while (my $parent = delete $message -> {_parent }) {
156+ push @{$parent -> {data }}, $message ;
157+
158+ if (@{$parent -> {data }} < $parent -> {_argument }) {
159+ $message = $self -> {_message } = {_parent => $parent };
160+ next CHUNK;
161+ }
162+ else {
163+ $message = $parent ;
164+ delete $parent -> {_argument };
165+ }
166+ }
167+
168+ $self -> {_on_message_cb }-> ($self , $message );
169+ $message = $self -> {_message } = {};
170+ }
171+ }
172+
35173my %blob_types = (' $' => 1, ' !' => 1, ' =' => 1);
36174my %aggregate_types = (' *' => 1, ' %' => 1, ' ~' => 1, ' |' => 1, ' >' => 1);
37- my $rn = " \r\n " ;
38175
39- sub encode {
176+ sub _encode_resp3 {
40177 my $self = shift ;
41178
42179 my $encoded_message = ' ' ;
@@ -53,7 +190,7 @@ sub encode {
53190 }
54191
55192 # Bulk string, Blob error, Verbatim string
56- elsif ($message -> { type } eq ' $ ' or ( $self -> { api } == 3 and exists $blob_types {$message -> {type }}) ) {
193+ elsif (exists $blob_types {$message -> {type }}) {
57194 if (defined $message -> {data }) {
58195 $encoded_message .= $message -> {type } . length ($message -> {data }) . " \r\n " . $message -> {data } . " \r\n " ;
59196 }
@@ -62,8 +199,7 @@ sub encode {
62199 }
63200 }
64201 # Array, Set, Push
65- elsif ($message -> {type } eq ' *'
66- or ($self -> {api } == 3 and ($message -> {type } eq ' ~' or $message -> {type } eq ' >' ))) {
202+ elsif ($message -> {type } eq ' *' or $message -> {type } eq ' ~' or $message -> {type } eq ' >' ) {
67203 if (defined $message -> {data }) {
68204 $encoded_message .= $message -> {type } . scalar (@{$message -> {data }}) . " \r\n " ;
69205 unshift @_ , @{$message -> {data }};
@@ -73,7 +209,7 @@ sub encode {
73209 }
74210 }
75211 # Map
76- elsif ($self -> { api } == 3 and $ message-> {type } eq ' %' ) {
212+ elsif ($message -> {type } eq ' %' ) {
77213 if (ref $message -> {data } eq ' ARRAY' ) {
78214 $encoded_message .= $message -> {type } . int (@{$message -> {data }} / 2) . " \r\n " ;
79215 unshift @_ , @{$message -> {data }};
@@ -84,12 +220,11 @@ sub encode {
84220 }
85221 }
86222 # String, error, integer, big number
87- elsif (exists $simple_types {$message -> {type }}
88- or ($self -> {api } == 3 and $message -> {type } eq ' (' )) {
223+ elsif (exists $simple_types {$message -> {type }} or $message -> {type } eq ' (' ) {
89224 $encoded_message .= $message -> {type } . $message -> {data } . " \r\n " ;
90225 }
91226 # Double
92- elsif ($self -> { api } == 3 and $ message-> {type } eq ' ,' ) {
227+ elsif ($message -> {type } eq ' ,' ) {
93228 # inf
94229 if ($message -> {data } == $message -> {data } * 2) {
95230 $encoded_message .= ' ,' . ($message -> {data } > 0 ? ' ' : ' -' ) . " inf\r\n " ;
@@ -103,11 +238,11 @@ sub encode {
103238 }
104239 }
105240 # Null
106- elsif ($self -> { api } == 3 and $ message-> {type } eq ' _' ) {
241+ elsif ($message -> {type } eq ' _' ) {
107242 $encoded_message .= " _\r\n " ;
108243 }
109244 # Boolean
110- elsif ($self -> { api } == 3 and $ message-> {type } eq ' #' ) {
245+ elsif ($message -> {type } eq ' #' ) {
111246 $encoded_message .= ' #' . ($message -> {data } ? ' t' : ' f' ) . " \r\n " ;
112247 }
113248 else {
@@ -118,16 +253,7 @@ sub encode {
118253 return $encoded_message ;
119254}
120255
121- sub get_message {
122- shift @{$_ [0]-> {_messages }};
123- }
124-
125- sub on_message {
126- my ($self , $cb ) = @_ ;
127- $self -> {_on_message_cb } = $cb || \&_gather_messages;
128- }
129-
130- sub parse {
256+ sub _parse_resp3 {
131257 my $self = shift ;
132258 $self -> {_buffer }.= shift ;
133259
@@ -148,7 +274,7 @@ sub parse {
148274 }
149275
150276 # Streamed String Parts - must be checked for first
151- if ($self -> { api } == 3 and $ message-> {_streaming }) {
277+ if ($message -> {_streaming }) {
152278 unless ($message -> {type } eq ' ;' ) {
153279 Carp::croak(qq/ Unexpected input "$message ->{type}"/ );
154280 }
@@ -172,30 +298,30 @@ sub parse {
172298 $message -> {data } = delete $message -> {_argument };
173299 }
174300 # Null
175- elsif ($self -> { api } == 3 and $ message-> {type } eq ' _' ) {
301+ elsif ($message -> {type } eq ' _' ) {
176302 delete $message -> {_argument };
177303 $message -> {data } = undef ;
178304 }
179305 # Booleans
180- elsif ($self -> { api } == 3 and $ message-> {type } eq ' #' ) {
306+ elsif ($message -> {type } eq ' #' ) {
181307 $message -> {data } = !!(delete ($message -> {_argument }) eq ' t' );
182308 }
183309 # Doubles
184- elsif ($self -> { api } == 3 and $ message-> {type } eq ' ,' ) {
310+ elsif ($message -> {type } eq ' ,' ) {
185311 $message -> {data } = delete $message -> {_argument };
186312 $message -> {data } = ' nan' if $message -> {data } =~ m / ^[-+] ?nan/ i ;
187313 }
188314 # Big Numbers
189- elsif ($self -> { api } == 3 and $ message-> {type } eq ' (' ) {
315+ elsif ($message -> {type } eq ' (' ) {
190316 require Math::BigInt;
191317 $message -> {data } = Math::BigInt-> new(delete $message -> {_argument });
192318 }
193319 # Bulk/Blob Strings, Blob Errors, Verbatim Strings
194- elsif ($message -> { type } eq ' $ ' or ( $self -> { api } == 3 and exists $blob_types {$message -> {type }}) ) {
320+ elsif (exists $blob_types {$message -> {type }}) {
195321 if ($message -> {_argument } eq ' -1' ) {
196322 $message -> {data } = undef ;
197323 }
198- elsif ($self -> { api } == 3 and $ message-> {type } eq ' $' and $message -> {_argument } eq ' ?' ) {
324+ elsif ($message -> {type } eq ' $' and $message -> {_argument } eq ' ?' ) {
199325 $message -> {data } = ' ' ;
200326 $message = $self -> {_message } = {_streaming => $message };
201327 next ;
@@ -209,23 +335,23 @@ sub parse {
209335 }
210336 }
211337 # Arrays, Maps, Sets, Attributes, Push
212- elsif ($message -> { type } eq ' * ' or ( $self -> { api } == 3 and exists $aggregate_types {$message -> {type }}) ) {
338+ elsif (exists $aggregate_types {$message -> {type }}) {
213339 if ($message -> {_argument } eq ' -1' ) {
214340 $message -> {data } = undef ;
215341 } else {
216- if ($self -> { api } == 3 and ( $ message-> {type } eq ' %' or $message -> {type } eq ' |' ) ) {
342+ if ($message -> {type } eq ' %' or $message -> {type } eq ' |' ) {
217343 $message -> {data } = {};
218344 } else {
219345 $message -> {data } = [];
220346 }
221347
222- if (( $self -> { api } == 3 and $ message-> {_argument } eq ' ?' ) or $message -> {_argument } > 0) {
348+ if ($ message-> {_argument } eq ' ?' or $message -> {_argument } > 0) {
223349 $message = $self -> {_message } = {_parent => $message };
224350 next ;
225351 }
226352 }
227353 # Populate empty attributes for next message if we reach here
228- if ($self -> { api } == 3 and $ message-> {type } eq ' |' ) {
354+ if ($message -> {type } eq ' |' ) {
229355 $message -> {attributes } = {};
230356 delete $message -> {type };
231357 delete $message -> {data };
@@ -234,8 +360,7 @@ sub parse {
234360 }
235361 }
236362 # Streamed Aggregate End
237- elsif ($self -> {api } == 3 and $message -> {type } eq ' .'
238- and $message -> {_parent } and $message -> {_parent }{_argument } eq ' ?' ) {
363+ elsif ($message -> {type } eq ' .' and $message -> {_parent } and $message -> {_parent }{_argument } eq ' ?' ) {
239364 $message = delete $message -> {_parent };
240365 delete $message -> {_elements };
241366 }
@@ -250,7 +375,7 @@ sub parse {
250375 # Fill parents with data
251376 while (my $parent = delete $message -> {_parent }) {
252377 # Map key or value
253- if ($self -> { api } == 3 and ( $ parent-> {type } eq ' %' or $parent -> {type } eq ' |' ) ) {
378+ if ($parent -> {type } eq ' %' or $parent -> {type } eq ' |' ) {
254379 if (exists $parent -> {_key }) {
255380 $parent -> {_elements }++;
256381 $parent -> {data }{delete $parent -> {_key }} = $message ;
@@ -265,8 +390,7 @@ sub parse {
265390 }
266391
267392 # Do we need more elements?
268- if (($self -> {api } == 3 and $parent -> {_argument } eq ' ?' )
269- or ($parent -> {_elements } || 0) < $parent -> {_argument }) {
393+ if ($parent -> {_argument } eq ' ?' or ($parent -> {_elements } || 0) < $parent -> {_argument }) {
270394 $message = $self -> {_message } = {_parent => $parent };
271395 next CHUNK;
272396 }
@@ -278,7 +402,7 @@ sub parse {
278402 delete $message -> {_key };
279403
280404 # Attributes apply to the following message
281- if ($self -> { api } == 3 and $ message-> {type } eq ' |' ) {
405+ if ($message -> {type } eq ' |' ) {
282406 $self -> {_message } = $message ;
283407 $message -> {attributes } = delete $message -> {data };
284408 delete $message -> {type };
@@ -291,10 +415,6 @@ sub parse {
291415 }
292416}
293417
294- sub _gather_messages {
295- push @{$_ [0]-> {_messages }}, $_ [1];
296- }
297-
2984181;
299419__END__
300420
0 commit comments