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

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

///|
fn Command::hmset(
  key : String,
  fields : ArrayView[(String, String)],
) -> Command[Unit] {
  Command(ArgsBuilder(b"HMSET")..push_string(key)..push_pairs(fields).build(), value => {
    value.expect_ok()
  })
}

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

///|
fn Command::hexists(key : String, field : String) -> Command[Bool] {
  Command(
    ArgsBuilder(b"HEXISTS")..push_string(key)..push_string(field).build(),
    value => value.as_bool_int(),
  )
}

///|
fn Command::hgetall(key : String) -> Command[Map[String, String]] {
  Command(ArgsBuilder(b"HGETALL")..push_string(key).build(), value => {
    value.as_string_map()
  })
}

///|
fn Command::hkeys(key : String) -> Command[Array[String]] {
  Command(ArgsBuilder(b"HKEYS")..push_string(key).build(), value => {
    value.as_array(value => value.as_string())
  })
}

///|
fn Command::hvals(key : String) -> Command[Array[String]] {
  Command(ArgsBuilder(b"HVALS")..push_string(key).build(), value => {
    value.as_array(value => value.as_string())
  })
}

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

///|
fn Command::hmget(
  key : String,
  fields : ArrayView[String],
) -> Command[Array[String?]] {
  Command(
    ArgsBuilder(b"HMGET")..push_string(key)..push_strings(fields).build(),
    value => value.as_array(value => value.as_option(item => item.as_string())),
  )
}

///|
fn Command::hincrby(
  key : String,
  field : String,
  increment : Int,
) -> Command[Int] {
  Command(
    ArgsBuilder(b"HINCRBY")
    ..push_string(key)
    ..push_string(field)
    ..push_int(increment)
    .build(),
    value => value.as_int(),
  )
}

///|
fn Command::hincrbyfloat(
  key : String,
  field : String,
  increment : Double,
) -> Command[Double] {
  Command(
    ArgsBuilder(b"HINCRBYFLOAT")
    ..push_string(key)
    ..push_string(field)
    ..push_double(increment)
    .build(),
    value => value.as_double(),
  )
}

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

///|
fn Command::hscan(
  key : String,
  cursor : String,
  pattern? : String,
  count? : Int,
) -> Command[(String, Map[String, String])] {
  Command(
    ArgsBuilder(b"HSCAN")
    ..push_string(key)
    ..push_string(cursor)
    ..push_scan_options(pattern, count)
    .build(),
    value => value.as_scan_map(),
  )
}