NURLNURL registrynurl-lang.org →

← redis

redis 0.1.1 API

resp.nu

packages/redis/src/resp.nu — RESP (REdis Serialization Protocol, RESP2) codec, pure and I/O-free so it can be unit-tested without a server.

A request is an array of bulk strings: *<n>\r\n ( $<len>\r\n<arg>\r\n ) x n

A reply is one of: simple string (+), error (-), integer (:), bulk string ($, with $-1 = nil) or array (, with -1 = nil). Arrays nest arbitrarily (pub/sub, XRANGE, COMMAND, …), so a reply is decoded into a flat node arena — a Vec RNode where array nodes hold the pool indices of their children. One Vec plus one String per node: no nested Vecs in structs beyond the child-index list, and a single linear free.

( resp_encode args ) → ( Vec u ) request bytes ( resp_parse buf start ) → RespParse one reply (or Incomplete) ( resp_reply_free reply ) → v free a parsed reply

Node walking (power users): resp_reply_root / resp_node_kind / resp_node_int / resp_node_str / resp_node_is_nil / resp_node_arr_len / resp_node_arr_at

API

: RNode

: RNode {
    i kind
    i ival          // integer value; for arrays, the element count
    String sval     // string / error text (empty otherwise)
    ( Vec i ) kids   // child node indices (only populated for arrays)
}

RNode.kind: 0 nil · 1 integer · 2 string (simple or bulk) · 3 error · 4 array

: RedisReply

: RedisReply {
    ( Vec RNode ) nodes
    i root
}

A decoded reply: the node arena plus the index of the root node.

: RespParse

: RespParse {
    i status
    RedisReply reply
    i consumed
}

Result of one parse attempt over a byte buffer. status: 0 ok · 1 incomplete (need more bytes) · 2 malformed consumed: bytes consumed from start when status == 0

: RespBuilder

: RespBuilder {
    ( Vec RNode ) nodes
    i status
    i cur
}

Mutable parse state threaded through the recursive descent (heap so the recursion shares one cursor / status / arena).

@ resp_encode ( Vec String ) args → ( Vec u )

Encode a command — an array of bulk strings — into RESP request bytes.

@ resp_parse ( Vec u ) buf i start → RespParse

Parse one reply from buf starting at start. On Incomplete (status 1) the returned reply still owns a (partial) arena and must be freed by the caller before retrying with more bytes.

@ resp_reply_free RedisReply r → v

@ resp_reply_root RedisReply r → i

@ resp_node_kind RedisReply r i node → i

@ resp_node_int RedisReply r i node → i

@ resp_node_str RedisReply r i node → s

Borrowed view of a string/error node's text (lifetime tied to r).

@ resp_node_is_nil RedisReply r i node → b

@ resp_node_arr_len RedisReply r i node → i

@ resp_node_arr_at RedisReply r i node i k → i


redis.nu

packages/redis/src/redis.nu — a pure-NURL Redis client. Speaks RESP2 over a plain libc TCP socket, or over the pure-NURL TLS client (rediss://) with no OpenSSL on the target. The RESP wire format lives in resp.nu; this file owns the connection, the request/reply round-trip and an ergonomic command surface (GET / SET / INCR / lists / hashes / sets / pub-sub …).

( redis_connect host port ) → !RedisConn RedisErr ( redis_connect_tls host port sni verify ) → !RedisConn RedisErr ( redis_auth conn user password ) → !v RedisErr ( redis_command conn args ) → !RedisReply RedisErr (raw) ( redis_get conn key ) / ( redis_set … ) … → typed helpers ( redis_close conn ) → v

Build arbitrary commands with the arg builder: : ( Vec String ) a ( redis_args ) ( redis_arg a SET ) ( redis_arg a key ) ( redis_arg a val ) : !RedisReply RedisErr r ( redis_command c a ) ( redis_args_free a )

API

: | RedisErr

: | RedisErr {
    RedisConnFail  // could not open the TCP socket
    RedisTls  // TLS upgrade failed (handshake / cert error)
    RedisProtocol  // malformed RESP from the server
    RedisIo  // socket read/write failure or unexpected EOF
    RedisServerError  // server returned a RESP error — see conn.lasterr
    RedisType  // reply was not the type the helper expected
}

@ redis_err_name RedisErr e → s

: RedisStr

: RedisStr {
    i found
    String val
}

Optional bulk-string reply. found == 0 means the server answered nil (e.g. GET on a missing key); val is owned and empty in that case. A named struct rather than ?String so it round-trips through !T E.

@ redis_str_is_nil RedisStr s → b

@ redis_str_val RedisStr s → s

@ redis_str_free RedisStr s → v

: RedisMessage

: RedisMessage {
    i kind
    String channel
    String pattern
    String payload
    i count
}

A pub/sub frame. kind: 0 message · 1 subscribe · 2 unsubscribe · 3 pmessage · 4 psubscribe · 5 punsubscribe · -1 unrecognised. pattern is set only for the p* variants; count is the live subscription count carried by (un)subscribe confirmations.

@ redis_message_kind RedisMessage m → i

@ redis_message_channel RedisMessage m → s

@ redis_message_pattern RedisMessage m → s

@ redis_message_payload RedisMessage m → s

@ redis_message_count RedisMessage m → i

@ redis_message_is_payload RedisMessage m → b

True for an actual published message (message / pmessage), false for a subscribe/unsubscribe control frame.

@ redis_message_free RedisMessage m → v

: RedisConn

: RedisConn {
    i tls  // 0 plaintext, 1 TLS
    i raw  // raw socket fd (plaintext reads / fd the TLS layer took over)
    TcpConn tcp  // plaintext transport (writes via tcp_write_all)
    * TlsConn tc  // TLS transport (when tls = 1)
    ( Vec u ) rxbuf  // bytes read but not yet parsed into a reply
    String lasterr  // last server error text
    String host_name
    i port_num
    i db_index
}

@ redis_command * RedisConn c ( Vec String ) args → !RedisReply RedisErr

Send a command (array of bulk strings) and return its reply. A RESP error reply is surfaced as RedisServerError with the text in conn.lasterr. The caller still owns args (free with redis_args_free) and owns the returned reply (free with resp_reply_free).

@ redis_args → ( Vec String )

@ redis_arg ( Vec String ) v s a → v

@ redis_arg_i ( Vec String ) v i n → v

@ redis_args_free ( Vec String ) v → v

@ redis_connect s host i port → !*RedisConn RedisErr

@ redis_connect_tls s host i port s server_name i verify → !*RedisConn RedisErr

verify != 0 → verify-full (chain + hostname); verify == 0 → encrypt only.

@ redis_close * RedisConn c → v

@ redis_last_error * RedisConn c → s

@ redis_is_tls * RedisConn c → b

@ redis_auth * RedisConn c s user s password → !v RedisErr

AUTH: one-arg (password only) or two-arg (ACL user + password). Pass an empty user for the legacy single-argument form.

@ redis_select * RedisConn c i db → !v RedisErr

@ redis_ping * RedisConn c → !b RedisErr

@ redis_echo * RedisConn c s msg → !RedisStr RedisErr

@ redis_set * RedisConn c s key s val → !v RedisErr

@ redis_get * RedisConn c s key → !RedisStr RedisErr

@ redis_del * RedisConn c s key → !i RedisErr

@ redis_exists * RedisConn c s key → !b RedisErr

@ redis_incr * RedisConn c s key → !i RedisErr

@ redis_decr * RedisConn c s key → !i RedisErr

@ redis_incrby * RedisConn c s key i n → !i RedisErr

@ redis_expire * RedisConn c s key i secs → !b RedisErr

@ redis_ttl * RedisConn c s key → !i RedisErr

@ redis_keys * RedisConn c s pattern → !( Vec String ) RedisErr

@ redis_lpush * RedisConn c s key s val → !i RedisErr

@ redis_rpush * RedisConn c s key s val → !i RedisErr

@ redis_llen * RedisConn c s key → !i RedisErr

@ redis_lrange * RedisConn c s key i start i stop → !( Vec String ) RedisErr

@ redis_hset * RedisConn c s key s field s val → !i RedisErr

@ redis_hget * RedisConn c s key s field → !RedisStr RedisErr

@ redis_hgetall * RedisConn c s key → !( Vec String ) RedisErr

Flat [field, value, field, value, …] of the whole hash.

@ redis_sadd * RedisConn c s key s member → !i RedisErr

@ redis_smembers * RedisConn c s key → !( Vec String ) RedisErr

@ redis_publish * RedisConn c s channel s msg → !i RedisErr

@ redis_subscribe * RedisConn c s channel → !RedisMessage RedisErr

Subscribe to a channel (or pattern). Returns the subscription confirmation; thereafter call redis_next_message to receive published messages. While subscribed only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING are valid commands.

@ redis_unsubscribe * RedisConn c s channel → !RedisMessage RedisErr

@ redis_psubscribe * RedisConn c s pattern → !RedisMessage RedisErr

@ redis_punsubscribe * RedisConn c s pattern → !RedisMessage RedisErr

@ redis_next_message * RedisConn c → !RedisMessage RedisErr

Block until the next pub/sub frame arrives, then decode it. Returns a message / pmessage for delivered payloads, or a (un)subscribe control frame; RedisIo on a closed connection.

@ redis_flushdb * RedisConn c → !v RedisErr


main.nu

packages/redis/src/main.nu — the redis command: a small redis-cli-style client built on the pure-NURL Redis client. Connects over RESP2 with an optional pure-NURL TLS upgrade (rediss://, no OpenSSL on the target), authenticates with AUTH, runs one command with -c or starts a REPL.

redis [flags] ["redis://[user:pass@]host:port/db"] -h HOST host (default $REDIS_HOST or 127.0.0.1) -p PORT port (default $REDIS_PORT or 6379) -a PASSWORD AUTH password (default $REDIS_PASSWORD) --user USER ACL username for AUTH (Redis 6+) -n DB SELECT database index (default 0) --tls connect over TLS (verify-full) --insecure with --tls / rediss://, skip certificate verification -c "CMD ARGS" run one command and exit; otherwise start a REPL A rediss:// URL implies --tls.

API

& c @ isatty i32 fd → i32

: ConnInfo

: ConnInfo {
    String host
    i port
    String user
    String password
    i db
    i tlsmode    // 0 plain, 1 tls insecure, 2 tls verify-full
}

@ main → i