///|
fn network_request(
  op : String,
  fields : Map[String, Json],
  result : Map[String, Json],
) -> Unit raise QueueError {
  match op {
    "birth_death" => {
      known(fields, ["op", "birth", "death"])
      let birth : Array[Double] = decode(field(fields, "birth"))
      let death : Array[Double] = decode(field(fields, "death"))
      let law = stationary_birth_death(birth, death)
      result["states"] = @json.to_json(law)
      result["summary"] = @json.to_json(summarize_states(law))
      result["residual"] = @json.to_json(balance_residual(law, birth, death))
    }
    "closed" => {
      known(fields, [
        "op", "kinds", "service_times", "visits", "think_time", "population",
      ])
      let kinds : Array[String] = decode(field(fields, "kinds"))
      let times : Array[Double] = decode(field(fields, "service_times"))
      let visits : Array[Double] = decode(field(fields, "visits"))
      if kinds.length() != times.length() || kinds.length() > 128 {
        raise Invalid("closed center shape")
      }
      let centers = []
      for i in 0.. centers.push(Fcfs(times[i]))
          "delay" => centers.push(Delay(times[i]))
          _ => raise Invalid("unknown closed center kind")
        }
      }
      let network : ClosedNetwork = {
        centers,
        visits,
        think_time: number(fields, "think_time"),
      }
      result["curve"] = @json.to_json(
        network.population_curve(count(fields, "population")),
      )
    }
    "jackson" => {
      known(fields, [
        "op", "services", "servers", "external", "routing", "maximum_utilization",
      ])
      let services : Array[Double] = decode(field(fields, "services"))
      let counts : Array[Json] = decode(field(fields, "servers"))
      if services.length() != counts.length() || services.length() > 128 {
        raise Invalid("Jackson node shape")
      }
      let nodes = []
      for i in 0.. {
      known(fields, ["op", "nodes", "budget"])
      let values : Array[Json] = decode(field(fields, "nodes"))
      if values.length() > 64 {
        raise Limit("allocation node limit")
      }
      let nodes = []
      for value in values {
        guard value is Object(node) else {
          raise Invalid("allocation node must be object")
        }
        known(node, ["arrival", "service", "minimum", "maximum"])
        nodes.push({
          arrival: number(node, "arrival"),
          service: number(node, "service"),
          minimum_servers: count(node, "minimum"),
          maximum_servers: count(node, "maximum"),
        })
      }
      result["allocation"] = @json.to_json(
        allocate_server_budget(nodes, count(fields, "budget")),
      )
    }
    _ => raise Invalid("unknown operation")
  }
}