package Redis::Parser::XS;

use strict;
use warnings;
no  warnings 'uninitialized';

require Exporter;
our @ISA     = qw(Exporter);
our @EXPORT  = qw(
    parse_redis
);

our $VERSION = '0.02';

require XSLoader;
XSLoader::load('Redis::Parser::XS', $VERSION);


1;
__END__

=head1 NAME

Redis::Parser::XS - unified redis protocol parser

=head1 SYNOPSIS

    use Redis::Parser::XS;
    
    my @output;
    
    my $buf = "+OK" . 
              "\x0d\x0a";
    
    my $len = parse_redis $buf, \@output;
    
    if (!defined $len) {
    
        warn "incorrect protocol message\n";
        
    } elsif ($len == 0) {
    
        warn "not enough data to parse, " . 
             "read some more and try again\n";
        
        if (length ($buf) > 16384) {  # 16k and still incomplete ?
                                      # better to just bail
            ...
        }
    } else { # $len > 0
    
        warn "parsed $len bytes\n";
        
        # got status reply:
        #    @output = ( [ '+', 'OK' ] )
        
        $buf = substr $buf, $len; 
    }

=head1 DESCRIPTION

Easy way to parse unified redis protocol. 

Protocol specification L<http://redis.io/topics/protocol>

=head1 FUNCTIONS

=over 4

=item $len = parse_redis $buf, \@output;

Parses redis protocol messages from C<$buf> and pushes each message
into C<@output>. Returns C<undef> on error or total length of parsed
data. Return value of C<0> returned as a "0 but true" string and
indicates, that there isn't enough data to parse even one message.

Parsed messages added to the C<@output> in the following format:

    @output = (
        
        ['+', 'OK'                 ],  # +OK     CRLF
                                       # 
        ['-', 'ERROR'              ],  # -ERROR  CRLF
                                       #
        [':', '123'                ],  # :123    CRLF
                                       # 
        ['$', 'foo'                ],  # $3      CRLF
                                       # foo     CRLF
                                       #
        ['$', undef                ],  # $-1     CRLF
                                       # 
        ['$', ''                   ],  # $0      CRLF
                                       #         CRLF
                                       #
        ['*', []                   ],  # *0      CRLF
                                       #
        ['*', undef                ],  # *-1     CRLF
                                       #
        ['*', [ 'foo',                 # *2      CRLF 
                ['+', 'OK'],           # $3      CRLF
                 ...         ]         # foo     CRLF
                                       # +OK     CRLF
                                       # ...
                                       #
        ['*', ['foo', undef ]      ],  # *2      CRLF 
                                       # $3      CRLF 
                                       # foo     CRLF 
                                       # $-1     CRLF
    )

=back

=head1 EXPORT

Exports only one function:

    parse_redis

=head1 BENCHMARK

Here is a sample benchmark against L<Protocol::Redis::XS>,
generated by F<eg/bench.pl>:

    Status reply
                              Rate
    Protocol::Redis::XS   281098/s
    Redis::Parser::XS     367589/s
    
    Multibulk reply
                              Rate
    Protocol::Redis::XS   127999/s
    Redis::Parser::XS     270490/s

=head1 SEE ALSO

L<Protocol::Redis::XS>

=head1 AUTHOR

Alexandr Gomoliako <zzz@zzz.org.ua>

=head1 LICENSE

Copyright 2011 Alexandr Gomoliako. All rights reserved.

This module is free software. It may be used, redistributed and/or modified 
under the same terms as Perl itself.

=cut

