///|
fn option_value(args : Array[String], name : String) -> String? {
  for i = 0; i < args.length(); i = i + 1 {
    if args[i] == name && i + 1 < args.length() {
      return Some(args[i + 1])
    }
  }
  None
}

///|
fn required(args : Array[String], name : String) -> Result[String, String] {
  match option_value(args, name) {
    Some(value) => Ok(value)
    None => Err("missing option \{name}")
  }
}

///|
fn parse_i64(value : String) -> Result[Int64, String] {
  Ok(@string.parse_int64(value)) catch {
    _ => Err("invalid Int64: \{value}")
  }
}

///|
fn q(value : String) -> String {
  Json::string(value).stringify()
}

///|
fn print_error(kind : String, message : String) -> Unit {
  println(
    "{\"ok\":false,\"error\":{\"kind\":\{q(kind)},\"message\":\{q(message)}}}",
  )
}

///|
fn print_range_error(error : @range.RangeError) -> Unit {
  print_error(error.kind().name(), error.context())
}

///|
fn range_input(args : Array[String]) -> Result[String, String] {
  required(args, "--range")
}

///|
fn length_input(args : Array[String]) -> Result[Int64, String] {
  match required(args, "--length") {
    Ok(value) => parse_i64(value)
    Err(error) => Err(error)
  }
}