///|
fn Command::lpush(key : String, values : ArrayView[String]) -> Command[Int] {
  Command(
    ArgsBuilder(b"LPUSH")..push_string(key)..push_strings(values).build(),
    value => value.as_int(),
  )
}

///|
fn Command::rpush(key : String, values : ArrayView[String]) -> Command[Int] {
  Command(
    ArgsBuilder(b"RPUSH")..push_string(key)..push_strings(values).build(),
    value => value.as_int(),
  )
}

///|
fn Command::lpop(key : String) -> Command[String?] {
  Command(ArgsBuilder(b"LPOP")..push_string(key).build(), value => {
    value.as_option(value => value.as_string())
  })
}

///|
fn Command::rpop(key : String) -> Command[String?] {
  Command(ArgsBuilder(b"RPOP")..push_string(key).build(), value => {
    value.as_option(value => value.as_string())
  })
}

///|
fn Command::lpop_count(key : String, count : Int) -> Command[Array[String]] {
  Command(ArgsBuilder(b"LPOP")..push_string(key)..push_int(count).build(), value => {
    value.as_string_array_or_empty()
  })
}

///|
fn Command::rpop_count(key : String, count : Int) -> Command[Array[String]] {
  Command(ArgsBuilder(b"RPOP")..push_string(key)..push_int(count).build(), value => {
    value.as_string_array_or_empty()
  })
}

///|
fn Command::llen(key : String) -> Command[Int] {
  Command(ArgsBuilder(b"LLEN")..push_string(key).build(), value => {
    value.as_int()
  })
}

///|
fn Command::lrange(
  key : String,
  start : Int,
  stop : Int,
) -> Command[Array[String]] {
  Command(
    ArgsBuilder(b"LRANGE")
    ..push_string(key)
    ..push_int(start)
    ..push_int(stop)
    .build(),
    value => value.as_array(value => value.as_string()),
  )
}

///|
fn Command::lindex(key : String, index : Int) -> Command[String?] {
  Command(ArgsBuilder(b"LINDEX")..push_string(key)..push_int(index).build(), value => {
    value.as_option(value => value.as_string())
  })
}

///|
fn Command::lset(key : String, index : Int, value : String) -> Command[Unit] {
  Command(
    ArgsBuilder(b"LSET")
    ..push_string(key)
    ..push_int(index)
    ..push_string(value)
    .build(),
    value => value.expect_ok(),
  )
}

///|
fn Command::ltrim(key : String, start : Int, stop : Int) -> Command[Unit] {
  Command(
    ArgsBuilder(b"LTRIM")
    ..push_string(key)
    ..push_int(start)
    ..push_int(stop)
    .build(),
    value => value.expect_ok(),
  )
}

///|
fn Command::lrem(key : String, count : Int, value : String) -> Command[Int] {
  Command(
    ArgsBuilder(b"LREM")
    ..push_string(key)
    ..push_int(count)
    ..push_string(value)
    .build(),
    value => value.as_int(),
  )
}

///|
fn Command::linsert_before(
  key : String,
  pivot : String,
  value : String,
) -> Command[Int] {
  Command(
    ArgsBuilder(b"LINSERT")
    ..push_string(key)
    ..push_bytes(b"BEFORE")
    ..push_string(pivot)
    ..push_string(value)
    .build(),
    value => value.as_int(),
  )
}

///|
fn Command::linsert_after(
  key : String,
  pivot : String,
  value : String,
) -> Command[Int] {
  Command(
    ArgsBuilder(b"LINSERT")
    ..push_string(key)
    ..push_bytes(b"AFTER")
    ..push_string(pivot)
    ..push_string(value)
    .build(),
    value => value.as_int(),
  )
}