// The list commands, named as in redis-py. A redis list is a sequence of strings; these
// expose the head/tail push-pop and range operations as MoonBit arrays and byte values.
///|
/// `LPUSH key value...`: prepend each value, returning the new length.
pub async fn Client::lpush(
self : Client,
key : String,
values : Array[String],
) -> Int64 raise RedisError {
let args : Array[Bytes] = [b"LPUSH", arg_string(key)]
for v in values {
args.push(arg_string(v))
}
expect_int64(self.command(args))
}
///|
/// `RPUSH key value...`: append each value, returning the new length.
pub async fn Client::rpush(
self : Client,
key : String,
values : Array[String],
) -> Int64 raise RedisError {
let args : Array[Bytes] = [b"RPUSH", arg_string(key)]
for v in values {
args.push(arg_string(v))
}
expect_int64(self.command(args))
}
///|
/// `LPUSHX key value...`: prepend only if `key` already exists, returning the length.
pub async fn Client::lpushx(
self : Client,
key : String,
values : Array[String],
) -> Int64 raise RedisError {
let args : Array[Bytes] = [b"LPUSHX", arg_string(key)]
for v in values {
args.push(arg_string(v))
}
expect_int64(self.command(args))
}
///|
/// `RPUSHX key value...`: append only if `key` already exists, returning the length.
pub async fn Client::rpushx(
self : Client,
key : String,
values : Array[String],
) -> Int64 raise RedisError {
let args : Array[Bytes] = [b"RPUSHX", arg_string(key)]
for v in values {
args.push(arg_string(v))
}
expect_int64(self.command(args))
}
///|
/// `LPOP key`: remove and return the head element, or `None` when the list is empty.
pub async fn Client::lpop(
self : Client,
key : String,
) -> Bytes? raise RedisError {
expect_bytes(self.command([b"LPOP", arg_string(key)]))
}
///|
/// `LPOP key count`: remove and return up to `count` head elements.
pub async fn Client::lpopn(
self : Client,
key : String,
count : Int32,
) -> Array[Bytes] raise RedisError {
let items = expect_array(
self.command([b"LPOP", arg_string(key), arg_int(count)]),
)
items.map(x => expect_bytes(x).unwrap())
}
///|
/// `RPOP key`: remove and return the tail element, or `None` when the list is empty.
pub async fn Client::rpop(
self : Client,
key : String,
) -> Bytes? raise RedisError {
expect_bytes(self.command([b"RPOP", arg_string(key)]))
}
///|
/// `RPOP key count`: remove and return up to `count` tail elements.
pub async fn Client::rpopn(
self : Client,
key : String,
count : Int32,
) -> Array[Bytes] raise RedisError {
let items = expect_array(
self.command([b"RPOP", arg_string(key), arg_int(count)]),
)
items.map(x => expect_bytes(x).unwrap())
}
///|
/// `LLEN key`: the length of the list.
pub async fn Client::llen(
self : Client,
key : String,
) -> Int64 raise RedisError {
expect_int64(self.command([b"LLEN", arg_string(key)]))
}
///|
/// `LINDEX key index`: the element at `index`, or `None` if out of range.
pub async fn Client::lindex(
self : Client,
key : String,
index : Int32,
) -> Bytes? raise RedisError {
expect_bytes(self.command([b"LINDEX", arg_string(key), arg_int(index)]))
}
///|
/// `LRANGE key start stop`: the elements from `start` to `stop` (inclusive, negative
/// from the tail).
pub async fn Client::lrange(
self : Client,
key : String,
start : Int32,
stop : Int32,
) -> Array[Bytes] raise RedisError {
let items = expect_array(
self.command([b"LRANGE", arg_string(key), arg_int(start), arg_int(stop)]),
)
items.map(x => expect_bytes(x).unwrap())
}
///|
/// `LSET key index value`: set the element at `index`. Raises `Reply` on a bad index.
pub async fn Client::lset(
self : Client,
key : String,
index : Int32,
value : String,
) -> Unit raise RedisError {
status_ok(
self.command([b"LSET", arg_string(key), arg_int(index), arg_string(value)]),
)
}
///|
/// `LREM key count value`: remove the first `count` elements equal to `value`. When
/// `count` is negative, remove from the tail; when 0, remove all. Returns the removed.
pub async fn Client::lrem(
self : Client,
key : String,
count : Int32,
value : String,
) -> Int64 raise RedisError {
expect_int64(
self.command([b"LREM", arg_string(key), arg_int(count), arg_string(value)]),
)
}
///|
/// `LINSERT key where pivot value`: insert `value` before (`BEFORE`) or after (`AFTER`)
/// `pivot`. Returns the new length, or `-1` when `pivot` is absent.
pub async fn Client::linsert(
self : Client,
key : String,
where_ : String,
pivot : String,
value : String,
) -> Int64 raise RedisError {
expect_int64(
self.command([
b"LINSERT",
arg_string(key),
arg_string(where_),
arg_string(pivot),
arg_string(value),
]),
)
}
///|
/// `LTRIM key start stop`: keep only the elements from `start` to `stop`.
pub async fn Client::ltrim(
self : Client,
key : String,
start : Int32,
stop : Int32,
) -> Unit raise RedisError {
status_ok(
self.command([b"LTRIM", arg_string(key), arg_int(start), arg_int(stop)]),
)
}
///|
/// `RPOPLPUSH source destination`: pop the tail of `source` and push it to the head of
/// `destination`, returning the element, or `None` when `source` is empty.
pub async fn Client::rpoplpush(
self : Client,
source : String,
destination : String,
) -> Bytes? raise RedisError {
expect_bytes(
self.command([b"RPOPLPUSH", arg_string(source), arg_string(destination)]),
)
}
///|
/// `LMOVE source destination LEFT|RIGHT LEFT|RIGHT`: pop from one end of `source` and
/// push to one end of `destination`, returning the element, or `None` when empty.
pub async fn Client::lmove(
self : Client,
source : String,
destination : String,
wherefrom : String,
whereto : String,
) -> Bytes? raise RedisError {
expect_bytes(
self.command([
b"LMOVE",
arg_string(source),
arg_string(destination),
arg_string(wherefrom),
arg_string(whereto),
]),
)
}
///|
/// `BLPOP key... timeout`: blocking pop of the first available head element across the
/// given keys, waiting up to `timeout` seconds (0 = forever). Returns the key and value,
/// or `None` on timeout.
pub async fn Client::blpop(
self : Client,
keys : Array[String],
timeout : Int32,
) -> (String, Bytes)? raise RedisError {
let args : Array[Bytes] = [b"BLPOP"]
for k in keys {
args.push(arg_string(k))
}
args.push(arg_int(timeout))
decode_key_value(self.command(args))
}
///|
/// `BRPOP key... timeout`: blocking pop of the first available tail element across the
/// given keys. Returns the key and value, or `None` on timeout.
pub async fn Client::brpop(
self : Client,
keys : Array[String],
timeout : Int32,
) -> (String, Bytes)? raise RedisError {
let args : Array[Bytes] = [b"BRPOP"]
for k in keys {
args.push(arg_string(k))
}
args.push(arg_int(timeout))
decode_key_value(self.command(args))
}
///|
/// `BRPOPLPUSH source destination timeout`: blocking `RPOPLPUSH`.
pub async fn Client::brpoplpush(
self : Client,
source : String,
destination : String,
timeout : Int32,
) -> Bytes? raise RedisError {
expect_bytes(
self.command([
b"BRPOPLPUSH",
arg_string(source),
arg_string(destination),
arg_int(timeout),
]),
)
}
///|
/// `BLMOVE source destination wherefrom whereto timeout`: blocking `LMOVE`.
pub async fn Client::blmove(
self : Client,
source : String,
destination : String,
wherefrom : String,
whereto : String,
timeout : Int32,
) -> Bytes? raise RedisError {
expect_bytes(
self.command([
b"BLMOVE",
arg_string(source),
arg_string(destination),
arg_string(wherefrom),
arg_string(whereto),
arg_int(timeout),
]),
)
}
///|
/// Decode a `[key, value]` pair reply into a key/value tuple, `None` for a null reply.
fn decode_key_value(
reply : @resp.RespValue,
) -> (String, Bytes)? raise RedisError {
match reply {
@resp.Null => None
@resp.Array(items) => {
guard items.length() == 2 else {
raise Protocol("unexpected key/value reply")
}
let key = @utf8.decode_lossy(expect_bytes(items[0]).unwrap())
let value = expect_bytes(items[1]).unwrap()
Some((key, value))
}
other => raise Protocol("expected key/value, got " + @resp.resp_kind(other))
}
}