RESP
is a wrapper around the Redis Serialization
Protocol. You can create all types,
stringify the built types into strings using str, decode single
values with from-string, and decode multiple concatenated
values with decode-n. Arrays are fully supported, including
nested arrays.
; decoding
(RESP.from-string "+OK\r\n") ; => (Success (Str @"OK"))
(RESP.from-string ":42\r\n") ; => (Success (Integer 42))
(RESP.from-string "$-1\r\n") ; => (Success (Null))
; encoding
(str &(RESP.Str @"hi")) ; => "$2\r\nhi\r\n"
(str &(RESP.Integer 42)) ; => ":42\r\n"
; pattern matching on responses
(match (Redis.get &r @"key")
(Result.Success resp)
(match resp
(RESP.Str s) (println* "got: " &s)
(RESP.Null) (println* "not found")
(RESP.Arr items) (println* "array of " &(Int.str (Array.length &items)))
_ (println* "other"))
(Result.Error e) (println* "error: " &e))
If you want your types to be supported when encoding, you’ll have to implement
the interface to-redis, the signature of which is (Fn [a] RESP)).
bulk-fill-target
(Fn [(Ref String a), Int, Int] (Maybe Int))
(bulk-fill-target s start slen)
the buffer length the partial bulk string at start needs before it decodes, when its header has arrived but its payload has not; else Nothing.
decode-available
(Fn [(Ref String a), Int, Int] (Pair (Array RESP) Int))
(decode-available s start n)
decodes up to n complete RESP values from s,
starting at byte offset start.
Returns a Pair of the decoded values and the byte offset just past the last
one — where a streaming caller should resume once more bytes arrive. Decoding
stops at the first incomplete or malformed value, so the array may hold fewer
than n values and the offset then marks the start of the still-unconsumed
tail. Unlike decode-first it consumes many values in a single
left-to-right pass without re-slicing between them, which is what lets a
buffered reader stay linear instead of quadratic.
decode-first
(Fn [(Ref String a)] (Result (Pair RESP String) String))
(decode-first s)
decodes the first complete RESP value from s.
Returns that value paired with the remaining, still-unconsumed suffix of s.
Unlike decode-n, it reports the leftover bytes, so a caller
streaming from a socket can keep a partial trailing value — or a whole value
that coalesced into the same read — buffered until it is needed. Returns an
Error if s does not begin with a complete RESP value, either because the
input is malformed or because a value is truncated mid-way.
decode-n
(Fn [(Ref String a), Int] (Array RESP))
(decode-n s n)
decodes up to n RESP values from string s.
Returns an array of the values that could be successfully decoded. If the
array has fewer than n elements, the string did not contain enough
complete RESP data.
encode-command
(Fn [(Ref String a), (Ref (Array RESP) b)] String)
(encode-command cmd args)
encodes command name cmd and its already-encoded args into a RESP
multi-bulk wire string. Sub-commands in cmd are separated by spaces (e.g.
@"CLIENT ID").
fatal-error-at
(Fn [(Ref String a), Int, Int] (Maybe String))
(fatal-error-at s start slen)
the decoder error for the value at start in s, if no amount of further
input could ever make it decode; else Nothing.
from-string
(Fn [(Ref String a)] (Result RESP String))
(from-string s)
converts a RESP string into a RESP data structure.
Arrays nested deeper than max-depth are rejected as malformed.
max-depth
Int
the deepest array nesting the decoders accept; deeper input is rejected as malformed.