// 响应侧:读状态行 + 头块,判定分帧。解析本身全在 httpproto(同步可测),
// 这里只负责「从连接上一行行拿」与 1xx 的跳过。

///|
/// 1xx 临时响应(100 Continue / 103 Early Hints 等)的跳过上限:
/// 我们不发 `Expect`,正常服务器根本不会发 1xx;上限只是防恶意循环。
const MAX_INTERIM_RESPONSES : Int32 = 5

///|
/// 坏连接信号:对端在**响应开始之前**就把连接关了(或写请求时对端已死)。
/// 只在取自池的连接上它才值得重试(docs/17 分期表:取用时坏连接重试一次),
/// 重试资格的裁决在 send_head;新建连接上的同款失败在这里统一翻成
/// `Network`——对端断开是网络失败,不是「收到了坏响应」(ERR_BAD_RESPONSE
/// 应该留给「真的收到了坏字节」)。
priv suberror StaleConnection {
  StaleConnection(String)
}

///|
/// 响应头读取结果。`headers` 保留**协议层的 multimap**——分帧判定要看
/// 全部 `Content-Length`(多条不一致是走私形状),压平成单值是 send 的收尾活。
/// `version` 参与复用判定:1.0 的持久连接要显式确认(docs/21)。
priv struct ResponseHead {
  version : @httpproto.HttpVersion
  code : Int32
  reason : String
  headers : @httpproto.HeaderMap
}

///|
/// 读响应头。1xx 响应(含各自的头块)读掉后继续等最终响应。
/// 解析失败以 `ParseError` 表达(Malformed / Unsupported);
/// 对端在响应开始前关闭以 `StaleConnection` 表达——两者都由 send 统一映射。
async fn read_response_head(conn : Connection) -> ResponseHead {
  let mut interim = 0
  while true {
    // 首个状态行的读取单独兜:干净 EOF 与读取失败(对端 RST 等)都意味着
    // 一个响应字节都没到——借来的连接早死了是常态,按坏连接表达,
    // 重试资格由 send_head 裁决;从这里起响应已开始,失败一律 Malformed。
    let line = conn.read_until("\r\n") catch {
      error =>
        raise StaleConnection("连接在响应开始前失效:\{error}")
    }
    let line = match line {
      Some(line) => line
      None => raise StaleConnection("连接在响应开始前被对端关闭")
    }
    let status = @httpproto.parse_status_line(line)
    if status.code >= 200 {
      let headers = read_header_block(conn)
      return {
        version: status.version,
        code: status.code,
        reason: status.reason,
        headers,
      }
    }
    // 1xx:读掉它的头块再等真正的响应
    interim += 1
    if interim > MAX_INTERIM_RESPONSES {
      raise @httpproto.ParseError::Malformed(
        "1xx 临时响应超过 \{MAX_INTERIM_RESPONSES} 个",
      )
    }
    discard_head_block(conn)
  }
  // 循环只能从 return / raise 离开;这行只为满足类型检查
  fail("unreachable")
}

///|
/// 读头块直到空行,交给 httpproto 解析(obs-fold、多值、校验都在那)。
/// 从这里起响应已经开始:EOF 一律是 `Malformed`(半截响应不可重试)。
async fn read_header_block(conn : Connection) -> @httpproto.HeaderMap {
  let lines : Array[String] = []
  while true {
    let line = conn.read_until("\r\n")
    if line is None {
      raise @httpproto.ParseError::Malformed("头块被截断")
    }
    if line is Some("") {
      break
    }
    lines.push(line.unwrap())
  }
  @httpproto.parse_header_block(lines)
}