///|
fn parse_allocation_query(
  data : Bytes,
  disk : ExportBackend,
) -> Result[Bool, UInt32] {
  if data.length() < 8 {
    return Err(0x80000003U)
  }
  let name_len = get32(data, 0)
  if name_len > (data.length() - 8).reinterpret_as_uint() {
    return Err(0x80000003U)
  }
  let after_name = 4 + name_len.reinterpret_as_int()
  if !disk.matches_name(data[4:after_name].to_owned()) {
    return Err(0x80000006U)
  }
  let count = get32(data, after_name)
  if count > 1024U {
    return Err(0x80000009U)
  }
  let mut at = after_name + 4
  let mut found = false
  for _ in 0.. data.length() - 4 {
      return Err(0x80000003U)
    }
    let len = get32(data, at)
    at += 4
    if len > 4096U || len > (data.length() - at).reinterpret_as_uint() {
      return Err(0x80000003U)
    }
    let end = at + len.reinterpret_as_int()
    if data[at:end].to_owned() == b"base:allocation" {
      found = true
    }
    at = end
  }
  if at != data.length() {
    return Err(0x80000003U)
  }
  Ok(found)
}

///|
async fn send_structured(
  tcp : @socket.Tcp,
  cookie : UInt64,
  kind : UInt32,
  data : Bytes,
) -> Unit {
  let reply : Array[Byte] = []
  put32(reply, 0x668e33efU)
  put16(reply, 1U)
  put16(reply, kind)
  put64(reply, cookie)
  put32(reply, data.length().reinterpret_as_uint())
  for b in data {
    reply.push(b)
  }
  tcp.write(Bytes::from_array(reply))
}