resp-2.0.0: A fast, non-backtracking parser for the redis RESP3 protocol
Safe HaskellSafe-Inferred
LanguageHaskell98

Data.RESP

Description

RESP is the wire protocol that Redis uses. The latest version is RESP3, which at time of writing seems relatively complete, but may still be evolving.

This module parses the entire RESP3 spec (as of 2024-01-26), but also parses some invalid RESP forms that Redis may return, eg `-nan`, and parses RESP2 forms that have been removed from the spec (eg `$-1\r\n`).

Synopsis

Documentation

data RespMessage Source #

A message from the server (eg. Redis) to the client. This can be a push message (for pub/sub), or a reply to a command issued by the client.

Instances

Instances details
Generic RespMessage Source # 
Instance details

Defined in Data.RESP

Associated Types

type Rep RespMessage :: Type -> Type #

Show RespMessage Source # 
Instance details

Defined in Data.RESP

Eq RespMessage Source # 
Instance details

Defined in Data.RESP

Ord RespMessage Source # 
Instance details

Defined in Data.RESP

type Rep RespMessage Source # 
Instance details

Defined in Data.RESP

data RespExpr Source #

RESP3 Expression.

This descriminates the difference between RespString and RespBlob, even though both contain bytestrings, in order to not throw away information. A caller might care whether the response was delivered with "+", or "$".

We do not, however descriminate between the different encodings of null. As far as I can tell, these are considered a mistake in the previous versions of the RESP spec, and clients should treat the different encodings the same.

Why don't we parse RespString into Text? Well, the caller might not actually need to decode it into text, and so we let the caller decide. This way, we don't have to deal with encoding errors.

Similarly, we don't parse a RespMap into a HashMap, because that would involve imposing our choice of data structure on the caller. The caller might want to use HashMap, Map, iterate over the elements, or just use the lookup function.

Instances

Instances details
Generic RespExpr Source # 
Instance details

Defined in Data.RESP

Associated Types

type Rep RespExpr :: Type -> Type #

Methods

from :: RespExpr -> Rep RespExpr x #

to :: Rep RespExpr x -> RespExpr #

Show RespExpr Source # 
Instance details

Defined in Data.RESP

Eq RespExpr Source # 
Instance details

Defined in Data.RESP

Ord RespExpr Source # 
Instance details

Defined in Data.RESP

type Rep RespExpr Source # 
Instance details

Defined in Data.RESP

type Rep RespExpr = D1 ('MetaData "RespExpr" "Data.RESP" "resp-2.0.0-inplace" 'False) ((((C1 ('MetaCons "RespString" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)) :+: C1 ('MetaCons "RespBlob" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString))) :+: (C1 ('MetaCons "RespStreamingBlob" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)) :+: C1 ('MetaCons "RespStringError" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)))) :+: ((C1 ('MetaCons "RespBlobError" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)) :+: C1 ('MetaCons "RespArray" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [RespExpr]))) :+: (C1 ('MetaCons "RespInteger" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int64)) :+: C1 ('MetaCons "RespNull" 'PrefixI 'False) (U1 :: Type -> Type)))) :+: (((C1 ('MetaCons "RespBool" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Bool)) :+: C1 ('MetaCons "RespDouble" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Double))) :+: (C1 ('MetaCons "RespVerbatimString" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)) :+: C1 ('MetaCons "RespVerbatimMarkdown" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ByteString)))) :+: ((C1 ('MetaCons "RespBigInteger" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Integer)) :+: C1 ('MetaCons "RespMap" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [(RespExpr, RespExpr)]))) :+: (C1 ('MetaCons "RespSet" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [RespExpr])) :+: C1 ('MetaCons "RespAttribute" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [(RespExpr, RespExpr)]) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 RespExpr))))))

parseMessage :: Scanner RespMessage Source #

Parse a RESP3 message

parseExpression :: Scanner RespExpr Source #

Parse a RESP3 expression