Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package perl-Protocol-Redis for
openSUSE:Factory checked in at 2026-03-11 20:52:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Protocol-Redis (Old)
and /work/SRC/openSUSE:Factory/.perl-Protocol-Redis.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Protocol-Redis"
Wed Mar 11 20:52:24 2026 rev:6 rq:1338063 version:2.0.200
Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Protocol-Redis/perl-Protocol-Redis.changes
2026-02-11 19:11:13.585968794 +0100
+++
/work/SRC/openSUSE:Factory/.perl-Protocol-Redis.new.8177/perl-Protocol-Redis.changes
2026-03-11 20:52:55.852037719 +0100
@@ -1,0 +2,9 @@
+Thu Feb 12 06:17:24 UTC 2026 - Tina Müller <[email protected]>
+
+- updated to 2.0.200 (2.0002)
+ see /usr/share/doc/packages/perl-Protocol-Redis/Changes
+
+ 2.0002 11.02.2026 00:00:00
+ - Improve README, format code.
+
+-------------------------------------------------------------------
Old:
----
Protocol-Redis-2.0001.tar.gz
New:
----
Protocol-Redis-2.0002.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Protocol-Redis.spec ++++++
--- /var/tmp/diff_new_pack.3l6Rse/_old 2026-03-11 20:52:56.428061483 +0100
+++ /var/tmp/diff_new_pack.3l6Rse/_new 2026-03-11 20:52:56.432061648 +0100
@@ -18,10 +18,10 @@
%define cpan_name Protocol-Redis
Name: perl-Protocol-Redis
-Version: 2.0.100
+Version: 2.0.200
Release: 0
-# 2.0001 -> normalize -> 2.0.100
-%define cpan_version 2.0001
+# 2.0002 -> normalize -> 2.0.200
+%define cpan_version 2.0002
License: Artistic-1.0 OR GPL-1.0-or-later
Summary: Redis protocol parser/encoder with asynchronous capabilities
URL: https://metacpan.org/release/%{cpan_name}
@@ -58,6 +58,6 @@
%perl_gen_filelist
%files -f %{name}.files
-%doc Changes examples
+%doc Changes examples README
%license LICENSE
++++++ Protocol-Redis-2.0001.tar.gz -> Protocol-Redis-2.0002.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/Changes
new/Protocol-Redis-2.0002/Changes
--- old/Protocol-Redis-2.0001/Changes 2026-02-04 21:07:03.000000000 +0100
+++ new/Protocol-Redis-2.0002/Changes 2026-02-11 21:39:06.000000000 +0100
@@ -1,5 +1,8 @@
This file documents the revision history for Perl extension Protocol::Redis
+2.0002 11.02.2026 00:00:00
+ - Improve README, format code.
+
2.0001 04.02.2026 00:00:00
- Test and fix encoding 0 as a double in RESP3 (Grinnz).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/MANIFEST
new/Protocol-Redis-2.0002/MANIFEST
--- old/Protocol-Redis-2.0001/MANIFEST 2026-02-04 21:07:26.000000000 +0100
+++ new/Protocol-Redis-2.0002/MANIFEST 2026-02-11 21:41:12.000000000 +0100
@@ -5,7 +5,7 @@
LICENSE
Makefile.PL
MANIFEST This list of files
-README.pod
+README
t/redis.t
META.yml Module YAML meta-data (added by
MakeMaker)
META.json Module JSON meta-data (added by
MakeMaker)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/META.json
new/Protocol-Redis-2.0002/META.json
--- old/Protocol-Redis-2.0001/META.json 2026-02-04 21:07:26.000000000 +0100
+++ new/Protocol-Redis-2.0002/META.json 2026-02-11 21:41:12.000000000 +0100
@@ -30,6 +30,12 @@
"ExtUtils::MakeMaker" : "0"
}
},
+ "develop" : {
+ "requires" : {
+ "Pod::Readme::Brief" : "0",
+ "Pod::Simple::JustPod" : "0"
+ }
+ },
"runtime" : {
"requires" : {
"Carp" : "0",
@@ -53,6 +59,6 @@
"web" : "https://github.com/und3f/protocol-redis"
}
},
- "version" : "2.0001",
+ "version" : "2.0002",
"x_serialization_backend" : "JSON::PP version 4.16"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/META.yml
new/Protocol-Redis-2.0002/META.yml
--- old/Protocol-Redis-2.0001/META.yml 2026-02-04 21:07:26.000000000 +0100
+++ new/Protocol-Redis-2.0002/META.yml 2026-02-11 21:41:12.000000000 +0100
@@ -26,5 +26,5 @@
bugtracker: https://github.com/und3f/protocol-redis/issues
license: http://dev.perl.org/licenses/
repository: https://github.com/und3f/protocol-redis.git
-version: '2.0001'
+version: '2.0002'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/Makefile.PL
new/Protocol-Redis-2.0002/Makefile.PL
--- old/Protocol-Redis-2.0001/Makefile.PL 2026-02-04 21:07:03.000000000
+0100
+++ new/Protocol-Redis-2.0002/Makefile.PL 2026-02-11 21:39:06.000000000
+0100
@@ -1,8 +1,8 @@
use 5.008001;
-
+
use strict;
use warnings;
-
+
use ExtUtils::MakeMaker;
WriteMakefile(
@@ -14,24 +14,50 @@
META_MERGE => {
dynamic_config => 0,
- 'meta-spec' => { version => 2 },
+ 'meta-spec' => {version => 2},
resources => {
- license => [ 'http://dev.perl.org/licenses/' ],
+ license => ['http://dev.perl.org/licenses/'],
repository => {
- type => 'git',
- url => 'https://github.com/und3f/protocol-redis.git',
- web => 'https://github.com/und3f/protocol-redis',
+ type => 'git',
+ url => 'https://github.com/und3f/protocol-redis.git',
+ web => 'https://github.com/und3f/protocol-redis',
},
- bugtracker => { web =>
'https://github.com/und3f/protocol-redis/issues' },
+ bugtracker =>
+ {web => 'https://github.com/und3f/protocol-redis/issues'},
+ },
+ prereqs => {
+ develop => {
+ requires => {
+ 'Pod::Readme::Brief' => 0,
+ 'Pod::Simple::JustPod' => 0,
+ }
+ }
},
},
MIN_PERL_VERSION => '5.008001',
- PREREQ_PM => {
- 'Carp' => 0,
+ PREREQ_PM => {
+ 'Carp' => 0,
'Math::BigInt' => 0,
- 'Test::More' => '0.94',
+ 'Test::More' => '0.94',
},
- test => {TESTS => 't/*.t'},
-
+ test => {TESTS => 't/*.t'},
);
+
+sub MY::postamble {
+ return <<'MAKEFILE';
+create_distdir: README
+
+README: scripts/create-readme.pl
+ $(PERLRUN) $< $@
+
+README.pod: scripts/create-readme-pod.pl
+ $(PERLRUN) $< $@
+
+format:
+ find . -iname "*.p[ml]" -o -name "*.t" | xargs perltidy
+
+check-format:
+ find . -iname "*.p[ml]" -o -name "*.t" | xargs perltidy --assert-tidy
+MAKEFILE
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/README
new/Protocol-Redis-2.0002/README
--- old/Protocol-Redis-2.0001/README 1970-01-01 01:00:00.000000000 +0100
+++ new/Protocol-Redis-2.0002/README 2026-02-11 21:41:12.000000000 +0100
@@ -0,0 +1,28 @@
+Protocol::Redis
+
+Redis protocol parser/encoder with asynchronous capabilities and
+pipelining <http://redis.io/topics/pipelining> support.
+
+INSTALLATION
+
+This is a Perl module distribution. It should be installed with whichever
+tool you use to manage your installation of Perl, e.g. any of
+
+ cpanm .
+ cpan .
+ cpanp -i .
+
+Consult http://www.cpan.org/modules/INSTALL.html for further instruction.
+Should you wish to install this module manually, the procedure is
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+COPYRIGHT AND LICENSE
+
+Copyright (C) 2011-2026, Serhii Zasenko.
+
+This program is free software, you can redistribute it and/or modify it
+under the same terms as Perl 5.10.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/README.pod
new/Protocol-Redis-2.0002/README.pod
--- old/Protocol-Redis-2.0001/README.pod 2026-02-04 21:07:03.000000000
+0100
+++ new/Protocol-Redis-2.0002/README.pod 1970-01-01 01:00:00.000000000
+0100
@@ -1,261 +0,0 @@
-=head1 NAME
-
-Protocol::Redis - Redis protocol parser/encoder with asynchronous capabilities.
-
-=head1 SYNOPSIS
-
- use Protocol::Redis;
- my $redis = Protocol::Redis->new(api => 1);
-
- $redis->parse("+foo\r\n");
-
- # get parsed message
- my $message = $redis->get_message;
- print "parsed message: ", $message->{data}, "\n";
-
- # asynchronous parsing interface
- $redis->on_message(sub {
- my ($redis, $message) = @_;
- print "parsed message: ", $message->{data}, "\n";
- });
-
- # parse pipelined message
- $redis->parse("+bar\r\n-error\r\n");
-
- # create message
- print "Get key message:\n",
- $redis->encode({type => '*', data => [
- {type => '$', data => 'string'},
- {type => '+', data => 'OK'}
- ]});
-
- # RESP3 supported with api 3 specified
- my $redis = Protocol::Redis->new(api => 3);
-
- print $redis->encode({type => '%', data => {
- null => {type => '_', data => undef},
- bignum => {type => '(', data =>
'3492890328409238509324850943850943825024385'},
- string => {type => '$', data => 'this is a string'},
- # format prepended to verbatim strings (defaults to txt)
- verbatim => {type => '=', data => '*verbatim* string', format =>
'mkd'},
- # set is unordered but specified as array
- booleans => {type => '~', data => [
- {type => '#', data => 1},
- {type => '#', data => 0},
- ]},
- # map is hashlike but can be specified as an
- # (even-sized) array to encode non-string keys
- special_map => {type => '%', data => [
- {type => ':', data => 42} => {type => '$', data => 'The answer'},
- {type => '_'} => {type => '$', data => 'No data'},
- ]},
- }, attributes => {
- coordinates => {type => '*', data => [
- {type => ',', data => '36.001516'},
- {type => ',', data => '-78.943319'},
- ]},
- });
-
- # "|1\r\n\$11\r\ncoordinates\r\n*2\r\n,36.001516\r\n,-78.943319\r\n" .
- # "%6\r\n" .
- # "\$6\r\nbignum\r\n(3492890328409238509324850943850943825024385\r\n" .
- # "\$8\r\nbooleans\r\n~2\r\n#t\r\n#f\r\n" .
- # "\$4\r\nnull\r\n_\r\n" .
- # "\$11\r\nspecial_map\r\n%2\r\n:42\r\n\$10\r\nThe
answer\r\n_\r\n\$7\r\nNo data\r\n" .
- # "\$6\r\nstring\r\n\$16\r\nthis is a string\r\n" .
- # "\$8\r\nverbatim\r\n=21\r\nmkd:*verbatim* string\r\n"
-
- # sets represented in the protocol the same as arrays
- # remapping into a hash may be useful to access string set elements
- $redis->parse("~3\r\n+x\r\n+y\r\n+z\r\n");
- my %set = map {($_->{data} => 1)} @{$redis->get_message->{data}};
- die unless exists $set{x};
- print join ',', keys %set; # x,y,z in unspecified order
-
- # verbatim strings are prefixed by a format
- # this will be returned as the format key
- $redis->parse("=16\r\nmkd:* one\n* two\n\r\n");
- my $verbatim = $redis->get_message;
- die unless $verbatim->{format} eq 'mkd';
- print $verbatim->{data};
- # * one
- # * two
-
- # attributes are maps that apply to the following value
- $redis->parse("|1\r\n+hits\r\n:6\r\n\$4\r\nterm\r\n");
- my $term = $redis->get_message;
- print "$term->{data}: $term->{attributes}{hits}{data}\n";
-
-=head1 DESCRIPTION
-
-Redis protocol parser/encoder with asynchronous capabilities and
L<pipelining|http://redis.io/topics/pipelining> support.
-
-=head1 APIv1
-
-Protocol::Redis APIv1 uses
-"L<Unified Request Protocol|http://redis.io/topics/protocol>" for message
-encoding/parsing and supports methods described further. Client libraries
-should specify API version during Protocol::Redis construction.
-
-API version 1 corresponds to the protocol now known as
-L<RESP2|https://github.com/redis/redis-specifications/blob/master/protocol/RESP2.md>
-and can also thusly be specified as API version 2. It supports the RESP2 data
-types C<+-:$*>.
-
-=head1 APIv3
-
-API version 3 supports the same methods as API version 1, corresponding to the
-L<RESP3|https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md>
-protocol. RESP3 contains support for several additional data types (null,
-boolean, double, big number, blob error, verbatim string, map, and set), data
-attributes, streamed strings and aggregate data, and explicitly specified push
-data so that asynchronous and synchronous responses can share a connection. A
-client must request RESP3 support from the server with the HELLO command to use
-these features.
-
-APIv3 supports the RESP2 data types C<+-:$*> as well as the RESP3-specific data
-types C<< _,#!=(%~|> >>, with the following implementation notes:
-
-=over
-
-=item * Verbatim String
-
-The Verbatim String type, specified with the initial byte C<=>, is treated the
-same as the Blob String type C<$> except that the first three bytes specify
-the C<format>, followed by a colon C<:>, and the remaining bytes are the string
-data. When parsing, the C<format> will be returned as a separate key and not
-included in the string C<data>. When encoding, a C<format> can be specified and
-otherwise defaults to C<txt>, and will be prepended to the string data.
-
-=item * Big Number
-
-The Big Number type, specified with the initial byte C<(>, is parsed to a
-L<Math::BigInt> object, which can be used in numeric or string operations
-without losing precision.
-
-=item * Map
-
-The Map type, specified with the initial byte C<%>, is represented in Perl as a
-hash. The keys of a Map are allowed to be any data type, but for simplicity
-they are coerced to strings as required by Perl hashes, which the specification
-allows. When encoding a Map, a hash reference is normally passed, but an array
-reference of alternating keys and values may also be passed to allow specifying
-non-string keys. If passed as an array, the values will be encoded in the order
-specified, but the Map type is defined as unordered.
-
-=item * Attribute
-
-The Attribute type, specified with the initial byte C<|>, is much like the Map
-type, but instead of acting as a value in the message, it is applied as the
-C<attributes> key of the following value. Like Map, its keys are coerced to
-strings as it is represented as a Perl hash.
-
-=item * Set
-
-The Set type, specified with the initial byte C<~>, is represented as an array,
-since a Set can contain values of any data type, which native Perl hashes
-cannot represent as keys, and the specification does not require enforcing
-element uniqueness. If desired, the higher level client and server should
-handle deduplication of Set elements, and should also be aware that the type
-is defined as unordered and the values are likely to be tested for existence
-rather than position.
-
-=item * Push
-
-The Push type, specified with the initial byte C<< > >>, is treated no
-differently from an Array, but a client supporting RESP3 must be prepared to
-handle a Push value at any time rather than in response to a command. An
-asynchronous client would generally execute a predefined callback when a Push
-value is received; a synchronous client must also take this into consideration
-for how and when it reads messages.
-
-=back
-
-=head2 C<new>
-
- my $redis = Protocol::Redis->new(api => 1);
-
-Construct Protocol::Redis object with specific API version support.
-If specified API version not supported constructor should raise an exception.
-Client libraries should always specify API version.
-
-=head2 C<parse>
-
- $redis->parse("*2\r\n$4ping\r\n\r\n");
-
-Parse Redis protocol chunk.
-
-=head2 C<get_message>
-
- while (my $message = $redis->get_message) {
- ...
- }
-
-Get parsed message or undef.
-
-=head2 C<on_message>
-
- $redis->on_message(sub {
- my ($redis, $message) = @_;
-
- }
-
-Calls callback on each parsed message.
-
-=head2 C<encode>
-
- my $string = $redis->encode({type => '+', data => 'test'});
- $string = $redis->encode(
- {type => '*', data => [
- {type => '$', data => 'test'}]});
-
-Encode data into redis message.
-
-=head2 C<api>
-
- my $api_version = $redis->api;
-
-Get API version.
-
-
-=head1 SUPPORT
-
-=head2 IRC
-
- #redis on irc.perl.org
-
-=head1 DEVELOPMENT
-
-=head2 Repository
-
- http://github.com/und3f/protocol-redis
-
-=head1 AUTHOR
-
-Serhii Zasenko, C<[email protected]>.
-
-=head1 CREDITS
-
-In alphabetical order
-
-=over 2
-
-Dan Book (Grinnz)
-
-David Leadbeater (dgl)
-
-Jan Henning Thorsen (jhthorsen)
-
-Viacheslav Tykhanovskyi (vti)
-
-Yaroslav Korshak (yko)
-
-=back
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (C) 2011-2026, Serhii Zasenko.
-
-This program is free software, you can redistribute it and/or modify it under
-the same terms as Perl 5.10.
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/examples/benchmark.pl
new/Protocol-Redis-2.0002/examples/benchmark.pl
--- old/Protocol-Redis-2.0001/examples/benchmark.pl 2024-09-02
22:24:25.000000000 +0200
+++ new/Protocol-Redis-2.0002/examples/benchmark.pl 2026-02-11
21:39:06.000000000 +0100
@@ -11,7 +11,7 @@
use Protocol::Redis::Faster;
use Protocol::Redis::Test;
-my $redis = Protocol::Redis->new(api => 1);
+my $redis = Protocol::Redis->new(api => 1);
my $redis_fast = Protocol::Redis::Faster->new(api => 1);
$redis->on_message(sub { });
@@ -32,64 +32,72 @@
# Encode multi-bulk
$redis->encode({type => '*', data => [{type => '$', data => 'test'}]});
- $redis->encode(
- { type => '*',
+ $redis->encode({
+ type => '*',
data => [
{type => '$', data => 'test1'}, {type => '$', data => 'test2'}
]
}
- );
+ );
$redis->encode({type => '*', data => []});
$redis->encode({type => '*', data => undef});
- $redis->encode(
- { type => '*',
+ $redis->encode({
+ type => '*',
data => [
{type => '$', data => 'foo'},
{type => '$', data => undef},
{type => '$', data => 'bar'}
]
}
- );
+ );
}
-cmpthese(2**17, {
+cmpthese(
+ 2**17, {
'P:R:F encode' => sub { encode($redis_fast) },
- 'P:R encode' => sub { encode($redis) },
- });
+ 'P:R encode' => sub { encode($redis) },
+ }
+);
my $status_message = $redis->encode({type => '+', data => 'OK'});
cmpthese(
- -1,
- { 'P:R Status parse' => sub { $redis->parse($status_message) },
+ -1, {
+ 'P:R Status parse' => sub { $redis->parse($status_message) },
'P:R:F Status parse' => sub { $redis_fast->parse($status_message) },
-});
+ }
+);
-my $a = 'cmpthese',(
- -1,
- {
+my $a = 'cmpthese', (
+ -1, {
'P:R Splitted status parse' =>
sub { $redis->parse("+OK"); $redis->parse("\r\n") },
'P:R:F Splitted status parse' =>
sub { $redis_fast->parse("+OK"); $redis->parse("\r\n") },
}
-);
+ );
-my $bulk_message = $redis->encode({type => '$', data => 'test'}) .
$redis->encode({type => '$', data => undef});
-cmpthese(-1, {
- 'Bulk parse P:R' => sub { $redis->parse($bulk_message) },
+my $bulk_message = $redis->encode({type => '$', data => 'test'})
+ . $redis->encode({type => '$', data => undef});
+cmpthese(
+ -1, {
+ 'Bulk parse P:R' => sub { $redis->parse($bulk_message) },
'Bulk parse P:R:F' => sub { $redis_fast->parse($bulk_message) },
-});
+ }
+);
-my $mbulk_message = $redis->encode(
- { type => '*',
+my $mbulk_message = $redis->encode({
+ type => '*',
data =>
[{type => '$', data => 'test1'}, {type => '$', data => 'test2'}]
}
);
-cmpthese(-1, {
- 'P:R Multi-Bulk parse' => sub { $redis->parse($mbulk_message) },
- 'P:R:F Multi-Bulk parse' => sub { $redis_fast->parse($mbulk_message) },
- });
+cmpthese(
+ -1, {
+ 'P:R Multi-Bulk parse' => sub { $redis->parse($mbulk_message) },
+ 'P:R:F Multi-Bulk parse' =>
+ sub { $redis_fast->parse($mbulk_message) },
+ }
+);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/lib/Protocol/Redis/Test.pm
new/Protocol-Redis-2.0002/lib/Protocol/Redis/Test.pm
--- old/Protocol-Redis-2.0001/lib/Protocol/Redis/Test.pm 2026-02-04
20:48:58.000000000 +0100
+++ new/Protocol-Redis-2.0002/lib/Protocol/Redis/Test.pm 2026-02-11
21:39:06.000000000 +0100
@@ -88,18 +88,19 @@
# Parsing method tests
$redis->on_message(undef);
+
# simple string, error string, number
_parse_string_ok($redis);
_parse_null_ok($redis);
_parse_boolean_ok($redis);
_parse_double_ok($redis);
_parse_big_number_ok($redis);
- _parse_blob_ok($redis, '$'); # blob string
- _parse_blob_ok($redis, '!'); # blob error
- _parse_verbatim_ok($redis); # verbatim string
- _parse_array_ok($redis, '*'); # array
- _parse_array_ok($redis, '~'); # set
- _parse_array_ok($redis, '>'); # push
+ _parse_blob_ok($redis, '$'); # blob string
+ _parse_blob_ok($redis, '!'); # blob error
+ _parse_verbatim_ok($redis); # verbatim string
+ _parse_array_ok($redis, '*'); # array
+ _parse_array_ok($redis, '~'); # set
+ _parse_array_ok($redis, '>'); # push
_parse_map_ok($redis);
_parse_attribute_ok($redis);
_parse_streamed_string_ok($redis);
@@ -156,7 +157,7 @@
sub _parse_blob_ok {
my $redis = shift;
- my $type = shift || '$';
+ my $type = shift || '$';
# Bulk message
$redis->parse("${type}4\r\ntest\r\n");
@@ -224,13 +225,17 @@
$redis->parse(join("\r\n", '=8', 'txt:test', '=6', 'mkd:OK'));
$redis->parse("\r\n");
is_deeply $redis->get_message,
- {type => '=', data => 'test', format => 'txt'}, "two chunked verbatim
string messages";
- is_deeply $redis->get_message, {type => '=', data => 'OK', format =>
'mkd'};
+ {type => '=', data => 'test', format => 'txt'},
+ "two chunked verbatim string messages";
+ is_deeply $redis->get_message,
+ {type => '=', data => 'OK', format => 'mkd'};
# Pipelined verbatim message
$redis->parse(join("\r\n", ('=7', 'txt:ok1'), ('=7', 'txt:ok2'), ''));
- is_deeply [$redis->get_message, $redis->get_message],
- [{type => '=', data => 'ok1', format => 'txt'}, {type => '=', data =>
'ok2', format => 'txt'}],
+ is_deeply [$redis->get_message, $redis->get_message], [
+ {type => '=', data => 'ok1', format => 'txt'},
+ {type => '=', data => 'ok2', format => 'txt'}
+ ],
"pipelined verbatim string message";
# Binary test
@@ -257,7 +262,7 @@
sub _parse_array_ok {
my $redis = shift;
- my $type = shift || '*';
+ my $type = shift || '*';
# Array message
$redis->parse("${type}1\r\n\$4\r\ntest\r\n");
@@ -286,14 +291,17 @@
is_deeply $redis->get_message, {
type => $type,
- data => [
- {type => $type, data => [
- {type => '+', data => 'test1'},
- {type => '+', data => 'test2'},
- ]},
+ data => [{
+ type => $type,
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '+', data => 'test2'},
+ ]
+ },
{type => '+', data => 'test3'},
]
- }, "nested $type array message";
+ },
+ "nested $type array message";
$redis->parse("${type}0\r\n");
is_deeply $redis->get_message,
@@ -358,7 +366,8 @@
$redis->parse(
join("\r\n",
("${type}2", '$3', 'ok1', '$3', 'ok2'),
- ("${type}1", '$3', 'ok3'), '')
+ ("${type}1", '$3', 'ok3'),
+ '')
);
is_deeply $redis->get_message, {
@@ -443,14 +452,14 @@
my $message = $redis->get_message;
is $message->{type}, ',', 'double message type';
cmp_ok $message->{data}, '==', $message->{data} + 1, 'received infinity';
- cmp_ok $message->{data}, '>', 0, 'received positive infinity';
+ cmp_ok $message->{data}, '>', 0, 'received positive infinity';
# Negative infinity message
$redis->parse(",-inf\r\n");
$message = $redis->get_message;
is $message->{type}, ',', 'double message type';
cmp_ok $message->{data}, '==', $message->{data} - 1, 'received infinity';
- cmp_ok $message->{data}, '<', 0, 'received negative infinity';
+ cmp_ok $message->{data}, '<', 0, 'received negative infinity';
# NaN message
$redis->parse(",nan\r\n");
@@ -514,12 +523,15 @@
$redis->parse("%3\r\n\$5\r\ntest1\r\n");
$redis->parse(":1\r\n+test2\r\n,0.01\r\n:3\r\n_\r\n");
- is_deeply $redis->get_message,
- {type => '%', data => {
- test1 => {type => ':', data => '1'},
- test2 => {type => ',', data => '0.01'},
- '3' => {type => '_', data => undef},
- }}, 'complex map message';
+ is_deeply $redis->get_message, {
+ type => '%',
+ data => {
+ test1 => {type => ':', data => '1'},
+ test2 => {type => ',', data => '0.01'},
+ '3' => {type => '_', data => undef},
+ }
+ },
+ 'complex map message';
}
sub _parse_set_ok {
@@ -528,14 +540,17 @@
# Set message
$redis->parse("~5\r\n+test1\r\n\$5\r\ntest2\r\n:42\r\n#t\r\n_\r\n");
- is_deeply $redis->get_message,
- {type => '~', data => [
- {type => '+', data => 'test1'},
- {type => '$', data => 'test2'},
- {type => ':', data => '42'},
- {type => '#', data => !!1},
- {type => '_', data => undef},
- ]}, 'set message';
+ is_deeply $redis->get_message, {
+ type => '~',
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '$', data => 'test2'},
+ {type => ':', data => '42'},
+ {type => '#', data => !!1},
+ {type => '_', data => undef},
+ ]
+ },
+ 'set message';
# Empty set message
$redis->parse("~0\r\n");
@@ -547,29 +562,35 @@
# Set message with duplicates
$redis->parse("~3\r\n+test1\r\n+test2\r\n+test1\r\n");
- is_deeply $redis->get_message,
- {type => '~', data => [
- {type => '+', data => 'test1'},
- {type => '+', data => 'test2'},
- {type => '+', data => 'test1'},
- ]}, 'set message with duplicates';
+ is_deeply $redis->get_message, {
+ type => '~',
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '+', data => 'test2'},
+ {type => '+', data => 'test1'},
+ ]
+ },
+ 'set message with duplicates';
# Set message with non-duplicate but equal strings
$redis->parse("~8\r\n+test1\r\n\$5\r\ntest1\r\n");
$redis->parse(":1\r\n,1\r\n#t\r\n");
$redis->parse("_\r\n+\r\n\$0\r\n\r\n");
- is_deeply $redis->get_message,
- {type => '~', data => [
- {type => '+', data => 'test1'},
- {type => '$', data => 'test1'},
- {type => ':', data => '1'},
- {type => ',', data => '1'},
- {type => '#', data => !!1},
- {type => '_', data => undef},
- {type => '+', data => ''},
- {type => '$', data => ''},
- ]}, 'set message with non-duplicate but equal strings';
+ is_deeply $redis->get_message, {
+ type => '~',
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '$', data => 'test1'},
+ {type => ':', data => '1'},
+ {type => ',', data => '1'},
+ {type => '#', data => !!1},
+ {type => '_', data => undef},
+ {type => '+', data => ''},
+ {type => '$', data => ''},
+ ]
+ },
+ 'set message with non-duplicate but equal strings';
}
sub _parse_attribute_ok {
@@ -579,23 +600,29 @@
$redis->parse("|1\r\n+total\r\n:5\r\n*2\r\n");
$redis->parse("\$5\r\ntest1\r\n\$5\r\ntest2\r\n");
- is_deeply $redis->get_message,
- {type => '*', data => [
- {type => '$', data => 'test1'},
- {type => '$', data => 'test2'},
- ], attributes => {
- total => {type => ':', data => '5'},
- }}, 'message with attributes';
+ is_deeply $redis->get_message, {
+ type => '*',
+ data =>
+ [{type => '$', data => 'test1'}, {type => '$', data => 'test2'},],
+ attributes => {
+ total => {type => ':', data => '5'},
+ }
+ },
+ 'message with attributes';
# Multiple attributes
$redis->parse("|3\r\n+x\r\n,0.5\r\n+y\r\n,-3.4\r\n+z\r\n:42\r\n+OK\r\n");
- is_deeply $redis->get_message,
- {type => '+', data => 'OK', attributes => {
- x => {type => ',', data => '0.5'},
- y => {type => ',', data => '-3.4'},
- z => {type => ':', data => '42'},
- }}, 'message with multiple attributes';
+ is_deeply $redis->get_message, {
+ type => '+',
+ data => 'OK',
+ attributes => {
+ x => {type => ',', data => '0.5'},
+ y => {type => ',', data => '-3.4'},
+ z => {type => ':', data => '42'},
+ }
+ },
+ 'message with multiple attributes';
# Empty attributes
$redis->parse("|0\r\n-ERR no response\r\n");
@@ -608,26 +635,44 @@
$redis->parse("*2\r\n|2\r\n+min\r\n:0\r\n+max\r\n:10\r\n:5\r\n");
$redis->parse("|2\r\n+min\r\n:4\r\n+max\r\n:8\r\n:7\r\n");
- is_deeply $redis->get_message,
- {type => '*', data => [
- {type => ':', data => '5', attributes => {
- min => {type => ':', data => '0'},
- max => {type => ':', data => '10'},
- }},
- {type => ':', data => '7', attributes => {
- min => {type => ':', data => '4'},
- max => {type => ':', data => '8'},
- }},
- ]}, 'message with embedded attributes';
+ is_deeply $redis->get_message, {
+ type => '*',
+ data => [{
+ type => ':',
+ data => '5',
+ attributes => {
+ min => {type => ':', data => '0'},
+ max => {type => ':', data => '10'},
+ }
+ }, {
+ type => ':',
+ data => '7',
+ attributes => {
+ min => {type => ':', data => '4'},
+ max => {type => ':', data => '8'},
+ }
+ },
+ ]
+ },
+ 'message with embedded attributes';
# Aggregate attributes
$redis->parse("|1\r\n+array\r\n*2\r\n+test1\r\n+test2\r\n+test\r\n");
- is_deeply $redis->get_message,
- {type => '+', data => 'test', attributes => {array => {type => '*', data
=> [
- {type => '+', data => 'test1'},
- {type => '+', data => 'test2'},
- ]}}}, 'message with aggregate attribute values';
+ is_deeply $redis->get_message, {
+ type => '+',
+ data => 'test',
+ attributes => {
+ array => {
+ type => '*',
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '+', data => 'test2'},
+ ]
+ }
+ }
+ },
+ 'message with aggregate attribute values';
}
sub _parse_push_ok {
@@ -636,11 +681,11 @@
# Simple push message
$redis->parse(">2\r\n\$5\r\ntest1\r\n:42\r\n");
- is_deeply $redis->get_message,
- {type => '>', data => [
- {type => '$', data => 'test1'},
- {type => ':', data => '42'},
- ]}, 'simple push message';
+ is_deeply $redis->get_message, {
+ type => '>',
+ data => [{type => '$', data => 'test1'}, {type => ':', data => '42'},]
+ },
+ 'simple push message';
# Empty push message
$redis->parse(">0\r\n");
@@ -669,32 +714,39 @@
# Charwise streamed string
$redis->parse("\$?\r\n");
- $redis->parse(";1\r\n$_\r\n") for 'a'..'z';
+ $redis->parse(";1\r\n$_\r\n") for 'a' .. 'z';
$redis->parse(";0\r\n");
is_deeply $redis->get_message,
- {type => '$', data => join('', 'a'..'z')},
+ {type => '$', data => join('', 'a' .. 'z')},
'string streamed by character';
}
sub _parse_streamed_aggregate_ok {
my $redis = shift;
- my $type = shift || '*';
+ my $type = shift || '*';
# Simple streamed aggregate
$redis->parse("${type}?\r\n+test1\r\n+test2\r\n.\r\n");
if ($type eq '%') {
- is_deeply $redis->get_message,
- {type => $type, data => {
- test1 => {type => '+', data => 'test2'},
- }}, "simple $type streamed aggregate message";
- } else {
- is_deeply $redis->get_message,
- {type => $type, data => [
- {type => '+', data => 'test1'},
- {type => '+', data => 'test2'},
- ]}, "simple $type streamed aggregate message";
+ is_deeply $redis->get_message, {
+ type => $type,
+ data => {
+ test1 => {type => '+', data => 'test2'},
+ }
+ },
+ "simple $type streamed aggregate message";
+ }
+ else {
+ is_deeply $redis->get_message, {
+ type => $type,
+ data => [
+ {type => '+', data => 'test1'},
+ {type => '+', data => 'test2'},
+ ]
+ },
+ "simple $type streamed aggregate message";
}
# Empty streamed aggregate
@@ -707,32 +759,44 @@
# Complex streamed aggregate
$redis->parse("${type}?\r\n");
$redis->parse("\$?\r\n;4\r\ntest\r\n;1\r\n1\r\n;0\r\n");
- $redis->parse("\$5\r\ntest$_\r\n") for 2..9;
+ $redis->parse("\$5\r\ntest$_\r\n") for 2 .. 9;
$redis->parse("*?\r\n:10\r\n,11\r\n.\r\n");
$redis->parse(".\r\n");
if ($type eq '%') {
- is_deeply $redis->get_message,
- {type => $type, data => {
- test1 => {type => '$', data => 'test2'},
- test3 => {type => '$', data => 'test4'},
- test5 => {type => '$', data => 'test6'},
- test7 => {type => '$', data => 'test8'},
- test9 => {type => '*', data => [
- {type => ':', data => '10'},
- {type => ',', data => '11'},
- ]},
- }}, "complex $type streamed aggregate message";
- } else {
- is_deeply $redis->get_message,
- {type => $type, data => [
- {type => '$', data => 'test1'},
- (map {+{type => '$', data => "test$_"}} 2..9),
- {type => '*', data => [
- {type => ':', data => '10'},
- {type => ',', data => '11'},
- ]},
- ]}, "complex $type streamed aggregate message";
+ is_deeply $redis->get_message, {
+ type => $type,
+ data => {
+ test1 => {type => '$', data => 'test2'},
+ test3 => {type => '$', data => 'test4'},
+ test5 => {type => '$', data => 'test6'},
+ test7 => {type => '$', data => 'test8'},
+ test9 => {
+ type => '*',
+ data => [
+ {type => ':', data => '10'},
+ {type => ',', data => '11'},
+ ]
+ },
+ }
+ },
+ "complex $type streamed aggregate message";
+ }
+ else {
+ is_deeply $redis->get_message, {
+ type => $type,
+ data => [
+ {type => '$', data => 'test1'},
+ (map { +{type => '$', data => "test$_"} } 2 .. 9), {
+ type => '*',
+ data => [
+ {type => ':', data => '10'},
+ {type => ',', data => '11'},
+ ]
+ },
+ ]
+ },
+ "complex $type streamed aggregate message";
}
}
@@ -827,8 +891,7 @@
my $redis = shift;
# Encode simple RESP3 types
- is $redis->encode({type => '_', data => undef}), "_\r\n",
- 'encode null';
+ is $redis->encode({type => '_', data => undef}), "_\r\n", 'encode null';
is $redis->encode({type => '#', data => 1}), "#t\r\n",
'encode boolean true';
@@ -850,13 +913,20 @@
is $redis->encode({type => ',', data => -sin 9**9**9}), ",nan\r\n",
'encode nan';
- is $redis->encode({type => '(',
- data => '3492890328409238509324850943850943825024385'}),
+ is $redis->encode({
+ type => '(',
+ data => '3492890328409238509324850943850943825024385'
+ }
+ ),
"(3492890328409238509324850943850943825024385\r\n",
'encode big number';
require Math::BigInt;
- is $redis->encode({type => '(',
- data =>
Math::BigInt->new('-3492890328409238509324850943850943825024385')}),
+ is $redis->encode({
+ type => '(',
+ data => Math::BigInt->new(
+ '-3492890328409238509324850943850943825024385')
+ }
+ ),
"(-3492890328409238509324850943850943825024385\r\n",
'encode bigint as big number';
is $redis->encode({type => '(', data => '0'}), "(0\r\n",
@@ -876,34 +946,67 @@
"=7\r\ntxt:\0\r\n\r\n", 'encode binary verbatim string';
# Encode aggregate RESP3 types
- is $redis->encode({type => '%', data => {foo => {type => '+', data =>
'bar'}}}),
+ is $redis->encode(
+ {type => '%', data => {foo => {type => '+', data => 'bar'}}}),
join("\r\n", '%1', '$3', 'foo', '+bar', ''),
'encode map';
- is $redis->encode({type => '~', data => [{type => ':', data => 5},
- {type => '+', data => 'test'}]}),
+ is $redis->encode({
+ type => '~',
+ data => [{type => ':', data => 5}, {type => '+', data => 'test'}]
+ }
+ ),
join("\r\n", '~2', ':5', '+test', ''),
'encode set';
- is $redis->encode({type => '>', data => [{type => '+', data => 'test'},
- {type => ',', data => '4.2'}]}),
+ is $redis->encode({
+ type => '>',
+ data =>
+ [{type => '+', data => 'test'}, {type => ',', data => '4.2'}]
+ }
+ ),
join("\r\n", '>2', '+test', ',4.2', ''),
'encode push';
# Encode attributes
- is $redis->encode({type => '+', data => 'test',
- attributes => {foo => {type => '+', data => 'bar'}}}),
+ is $redis->encode({
+ type => '+',
+ data => 'test',
+ attributes => {foo => {type => '+', data => 'bar'}}
+ }
+ ),
join("\r\n", '|1', '$3', 'foo', '+bar', '+test', ''),
'encode simple string with attributes';
- is $redis->encode({type => '*', data => [{type => '_', data => undef}],
- attributes => {test => {type => '#', data => 1}}}),
+ is $redis->encode({
+ type => '*',
+ data => [{type => '_', data => undef}],
+ attributes => {test => {type => '#', data => 1}}
+ }
+ ),
join("\r\n", '|1', '$4', 'test', '#t', '*1', '_', ''),
'encode array with attributes';
- is $redis->encode({type => '~', data => [{type => ',', data => '-5.5',
- attributes => {precision => {type => ':', data => 1}}}]}),
+ is $redis->encode({
+ type => '~',
+ data => [{
+ type => ',',
+ data => '-5.5',
+ attributes => {precision => {type => ':', data => 1}}
+ }
+ ]
+ }
+ ),
join("\r\n", '~1', '|1', '$9', 'precision', ':1', ',-5.5', ''),
'encode set with embedded attributes';
- is $redis->encode({type => '+', data => 'test',
- attributes => {array => {type => '*',
- data => [{type => ':', data => 1}, {type => ':', data => 2}]}}}),
+ is $redis->encode({
+ type => '+',
+ data => 'test',
+ attributes => {
+ array => {
+ type => '*',
+ data =>
+ [{type => ':', data => 1}, {type => ':', data => 2}]
+ }
+ }
+ }
+ ),
join("\r\n", '|1', '$5', 'array', '*2', ':1', ':2', '+test', ''),
'encode array attributes';
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Protocol-Redis-2.0001/lib/Protocol/Redis.pm
new/Protocol-Redis-2.0002/lib/Protocol/Redis.pm
--- old/Protocol-Redis-2.0001/lib/Protocol/Redis.pm 2026-02-04
21:07:03.000000000 +0100
+++ new/Protocol-Redis-2.0002/lib/Protocol/Redis.pm 2026-02-11
21:40:55.000000000 +0100
@@ -4,7 +4,7 @@
use warnings;
use 5.008_001;
-our $VERSION = '2.0001';
+our $VERSION = '2.0002';
require Carp;
@@ -15,7 +15,9 @@
my $self = {@_};
Carp::croak(qq/Unknown Protocol::Redis API version $self->{api}/)
- unless $self->{api} == 1 or $self->{api} == 2 or $self->{api} == 3;
+ unless $self->{api} == 1
+ or $self->{api} == 2
+ or $self->{api} == 3;
bless $self, $class;
@@ -66,22 +68,28 @@
# Bulk string
if ($message->{type} eq '$') {
if (defined $message->{data}) {
- $encoded_message .= '$' . length($message->{data}) . "\r\n" .
$message->{data} . "\r\n";
+ $encoded_message
+ .= '$'
+ . length($message->{data}) . "\r\n"
+ . $message->{data} . "\r\n";
}
else {
$encoded_message .= "\$-1\r\n";
}
}
+
# Array (multi bulk)
elsif ($message->{type} eq '*') {
if (defined $message->{data}) {
- $encoded_message .= '*' . scalar(@{$message->{data}}) . "\r\n";
+ $encoded_message
+ .= '*' . scalar(@{$message->{data}}) . "\r\n";
unshift @_, @{$message->{data}};
}
else {
$encoded_message .= "*-1\r\n";
}
}
+
# String, error, integer
elsif (exists $simple_types{$message->{type}}) {
$encoded_message .= $message->{type} . $message->{data} . "\r\n";
@@ -95,47 +103,52 @@
}
sub _parse_resp2 {
- my $self = shift;
- $self->{_buffer}.= shift;
+ my $self = shift;
+ $self->{_buffer} .= shift;
my $message = $self->{_message} ||= {};
my $buffer = \$self->{_buffer};
- CHUNK:
+ CHUNK:
while ((my $pos = index($$buffer, "\r\n")) != -1) {
+
# Check our state: are we parsing new message or completing existing
if (!$message->{type}) {
if ($pos < 1) {
Carp::croak(qq/Unexpected input "$$buffer"/);
}
- $message->{type} = substr $$buffer, 0, 1;
- $message->{_argument} = substr $$buffer, 1, $pos - 1;
- substr $$buffer, 0, $pos + 2, ''; # Remove type + argument + \r\n
+ $message->{type} = substr $$buffer, 0, 1;
+ $message->{_argument} = substr $$buffer, 1, $pos - 1;
+ substr $$buffer, 0, $pos + 2, ''; # Remove type + argument + \r\n
}
# Simple Strings, Errors, Integers
if (exists $simple_types{$message->{type}}) {
$message->{data} = delete $message->{_argument};
}
+
# Bulk Strings
elsif ($message->{type} eq '$') {
if ($message->{_argument} eq '-1') {
$message->{data} = undef;
}
elsif (length($$buffer) >= $message->{_argument} + 2) {
- $message->{data} = substr $$buffer, 0, $message->{_argument},
'';
- substr $$buffer, 0, 2, ''; # Remove \r\n
+ $message->{data} = substr $$buffer, 0, $message->{_argument},
+ '';
+ substr $$buffer, 0, 2, ''; # Remove \r\n
}
else {
- return # Wait more data
+ return # Wait more data
}
}
+
# Arrays
elsif ($message->{type} eq '*') {
if ($message->{_argument} eq '-1') {
$message->{data} = undef;
- } else {
+ }
+ else {
$message->{data} = [];
if ($message->{_argument} > 0) {
$message = $self->{_message} = {_parent => $message};
@@ -143,6 +156,7 @@
}
}
}
+
# Invalid input
else {
Carp::croak(qq/Unexpected input "$self->{_message}{type}"/);
@@ -170,7 +184,7 @@
}
}
-my %blob_types = ('$' => 1, '!' => 1, '=' => 1);
+my %blob_types = ('$' => 1, '!' => 1, '=' => 1);
my %aggregate_types = ('*' => 1, '%' => 1, '~' => 1, '|' => 1, '>' => 1);
sub _encode_resp3 {
@@ -183,59 +197,86 @@
# Attributes
if (defined $message->{attributes}) {
my %append_message = %$message;
- my $attributes = delete $append_message{attributes};
+ my $attributes = delete $append_message{attributes};
$encoded_message .= '|' . keys(%$attributes) . "\r\n";
- unshift @_, (map { ({type => '$', data => $_}, $attributes->{$_}) }
- sort keys %$attributes), \%append_message;
+ unshift @_, (
+ map { ({type => '$', data => $_}, $attributes->{$_}) }
+ sort keys %$attributes
+ ),
+ \%append_message;
}
# Bulk string, Blob error, Verbatim string
elsif (exists $blob_types{$message->{type}}) {
my $text = $message->{data};
if ($message->{type} eq '=') {
- my $format = defined $message->{format} ? $message->{format} :
'txt';
+ my $format =
+ defined $message->{format} ? $message->{format} : 'txt';
$text = "$format:$text";
}
- $encoded_message .= $message->{type} . length($text) . "\r\n" .
$text . "\r\n";
+ $encoded_message
+ .= $message->{type} . length($text) . "\r\n" . $text . "\r\n";
}
+
# Array, Set, Push
- elsif ($message->{type} eq '*' or $message->{type} eq '~' or
$message->{type} eq '>') {
- $encoded_message .= $message->{type} . scalar(@{$message->{data}})
. "\r\n";
+ elsif ($message->{type} eq '*'
+ or $message->{type} eq '~'
+ or $message->{type} eq '>')
+ {
+ $encoded_message
+ .= $message->{type} . scalar(@{$message->{data}}) . "\r\n";
unshift @_, @{$message->{data}};
}
+
# Map
elsif ($message->{type} eq '%') {
if (ref $message->{data} eq 'ARRAY') {
- $encoded_message .= $message->{type} . int(@{$message->{data}}
/ 2) . "\r\n";
+ $encoded_message
+ .= $message->{type} . int(@{$message->{data}} / 2) . "\r\n";
unshift @_, @{$message->{data}};
- } else {
- $encoded_message .= $message->{type} .
keys(%{$message->{data}}) . "\r\n";
- unshift @_, map { ({type => '$', data => $_},
$message->{data}{$_}) }
- sort keys %{$message->{data}};
+ }
+ else {
+ $encoded_message
+ .= $message->{type} . keys(%{$message->{data}}) . "\r\n";
+ unshift @_,
+ map { ({type => '$', data => $_}, $message->{data}{$_}) }
+ sort keys %{$message->{data}};
}
}
+
# String, error, integer, big number
- elsif (exists $simple_types{$message->{type}} or $message->{type} eq
'(') {
+ elsif (exists $simple_types{$message->{type}}
+ or $message->{type} eq '(')
+ {
$encoded_message .= $message->{type} . $message->{data} . "\r\n";
}
+
# Double
elsif ($message->{type} eq ',') {
+
# inf
- if ($message->{data} != 0 and $message->{data} == $message->{data}
* 2) {
- $encoded_message .= ',' . ($message->{data} > 0 ? '' : '-') .
"inf\r\n";
+ if ( $message->{data} != 0
+ and $message->{data} == $message->{data} * 2)
+ {
+ $encoded_message
+ .= ',' . ($message->{data} > 0 ? '' : '-') . "inf\r\n";
}
+
# nan
elsif ($message->{data} != $message->{data}) {
$encoded_message .= ",nan\r\n";
}
else {
- $encoded_message .= $message->{type} . $message->{data} .
"\r\n";
+ $encoded_message
+ .= $message->{type} . $message->{data} . "\r\n";
}
}
+
# Null
elsif ($message->{type} eq '_') {
$encoded_message .= "_\r\n";
}
+
# Boolean
elsif ($message->{type} eq '#') {
$encoded_message .= '#' . ($message->{data} ? 't' : 'f') . "\r\n";
@@ -249,23 +290,24 @@
}
sub _parse_resp3 {
- my $self = shift;
- $self->{_buffer}.= shift;
+ my $self = shift;
+ $self->{_buffer} .= shift;
my $message = $self->{_message} ||= {};
my $buffer = \$self->{_buffer};
- CHUNK:
+ CHUNK:
while ((my $pos = index($$buffer, "\r\n")) != -1) {
+
# Check our state: are we parsing new message or completing existing
if (!$message->{type}) {
if ($pos < 1) {
Carp::croak(qq/Unexpected input "$$buffer"/);
}
- $message->{type} = substr $$buffer, 0, 1;
- $message->{_argument} = substr $$buffer, 1, $pos - 1;
- substr $$buffer, 0, $pos + 2, ''; # Remove type + argument + \r\n
+ $message->{type} = substr $$buffer, 0, 1;
+ $message->{_argument} = substr $$buffer, 1, $pos - 1;
+ substr $$buffer, 0, $pos + 2, ''; # Remove type + argument + \r\n
}
# Streamed String Parts - must be checked for first
@@ -279,38 +321,46 @@
}
elsif (length($$buffer) >= $message->{_argument} + 2) {
my $streaming = delete $message->{_streaming};
- $streaming->{data} .= substr $$buffer, 0,
$message->{_argument}, '';
- substr $$buffer, 0, 2, ''; # Remove \r\n
+ $streaming->{data} .= substr $$buffer, 0,
+ $message->{_argument}, '';
+ substr $$buffer, 0, 2, ''; # Remove \r\n
$message = $self->{_message} = {_streaming => $streaming};
next;
}
else {
- return # Wait more data
+ return # Wait more data
}
}
+
# Simple Strings, Errors, Integers
elsif (exists $simple_types{$message->{type}}) {
$message->{data} = delete $message->{_argument};
}
+
# Null
elsif ($message->{type} eq '_') {
delete $message->{_argument};
$message->{data} = undef;
}
+
# Booleans
elsif ($message->{type} eq '#') {
$message->{data} = !!(delete($message->{_argument}) eq 't');
}
+
# Doubles
elsif ($message->{type} eq ',') {
$message->{data} = delete $message->{_argument};
$message->{data} = 'nan' if $message->{data} =~ m/^[-+]?nan/i;
}
+
# Big Numbers
elsif ($message->{type} eq '(') {
require Math::BigInt;
- $message->{data} = Math::BigInt->new(delete $message->{_argument});
+ $message->{data} =
+ Math::BigInt->new(delete $message->{_argument});
}
+
# Bulk/Blob Strings, Blob Errors, Verbatim Strings
elsif (exists $blob_types{$message->{type}}) {
if ($message->{type} eq '$' and $message->{_argument} eq '?') {
@@ -319,21 +369,26 @@
next;
}
elsif (length($$buffer) >= $message->{_argument} + 2) {
- $message->{data} = substr $$buffer, 0, $message->{_argument},
'';
- if ($message->{type} eq '=' and $message->{data} =~
s/^(.{3})://s) {
+ $message->{data} = substr $$buffer, 0, $message->{_argument},
+ '';
+ if ( $message->{type} eq '='
+ and $message->{data} =~ s/^(.{3})://s)
+ {
$message->{format} = $1;
}
- substr $$buffer, 0, 2, ''; # Remove \r\n
+ substr $$buffer, 0, 2, ''; # Remove \r\n
}
else {
- return # Wait more data
+ return # Wait more data
}
}
+
# Arrays, Maps, Sets, Attributes, Push
elsif (exists $aggregate_types{$message->{type}}) {
if ($message->{type} eq '%' or $message->{type} eq '|') {
$message->{data} = {};
- } else {
+ }
+ else {
$message->{data} = [];
}
@@ -341,6 +396,7 @@
$message = $self->{_message} = {_parent => $message};
next;
}
+
# Populate empty attributes for next message if we reach here
if ($message->{type} eq '|') {
$message->{attributes} = {};
@@ -350,11 +406,16 @@
next;
}
}
+
# Streamed Aggregate End
- elsif ($message->{type} eq '.' and $message->{_parent} and
$message->{_parent}{_argument} eq '?') {
+ elsif ( $message->{type} eq '.'
+ and $message->{_parent}
+ and $message->{_parent}{_argument} eq '?')
+ {
$message = delete $message->{_parent};
delete $message->{_elements};
}
+
# Invalid input
else {
Carp::croak(qq/Unexpected input "$self->{_message}{type}"/);
@@ -365,15 +426,18 @@
# Fill parents with data
while (my $parent = delete $message->{_parent}) {
+
# Map key or value
if ($parent->{type} eq '%' or $parent->{type} eq '|') {
if (exists $parent->{_key}) {
$parent->{_elements}++;
$parent->{data}{delete $parent->{_key}} = $message;
- } else {
+ }
+ else {
$parent->{_key} = $message->{data};
}
}
+
# Array or set element
else {
$parent->{_elements}++;
@@ -381,7 +445,9 @@
}
# Do we need more elements?
- if ($parent->{_argument} eq '?' or ($parent->{_elements} || 0) <
$parent->{_argument}) {
+ if ($parent->{_argument} eq '?'
+ or ($parent->{_elements} || 0) < $parent->{_argument})
+ {
$message = $self->{_message} = {_parent => $parent};
next CHUNK;
}
@@ -394,7 +460,7 @@
# Attributes apply to the following message
if ($message->{type} eq '|') {
- $self->{_message} = $message;
+ $self->{_message} = $message;
$message->{attributes} = delete $message->{data};
delete $message->{type};
next CHUNK;
++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.3l6Rse/_old 2026-03-11 20:52:56.608068909 +0100
+++ /var/tmp/diff_new_pack.3l6Rse/_new 2026-03-11 20:52:56.624069569 +0100
@@ -1,6 +1,6 @@
-mtime: 1770272161
-commit: 4559e8716e6d392f2cc84a7aadb7c7bb51a7e13b1d9ca7e87537d96bff261def
+mtime: 1770877044
+commit: fbb6e2aecf56009607e7698ab2856be953d95e042b4e30256718b64ece046575
url: https://src.opensuse.org/perl/perl-Protocol-Redis.git
-revision: 4559e8716e6d392f2cc84a7aadb7c7bb51a7e13b1d9ca7e87537d96bff261def
+revision: fbb6e2aecf56009607e7698ab2856be953d95e042b4e30256718b64ece046575
projectscmsync: https://src.opensuse.org/perl/_ObsPrj
++++++ build.specials.obscpio ++++++
++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore 1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore 2026-03-09 19:30:36.000000000 +0100
@@ -0,0 +1 @@
+.osc