// The QPACK Encoded Field Section Prefix (RFC 9204 §4.5.1): every field section opens with
// a Required Insert Count and a Base. The Required Insert Count states how many dynamic
// inserts the section depends on; it is transmitted modulo 2*MaxEntries (§4.5.1) and the
// decoder reconstructs the absolute value from the number of inserts it has already seen
// (§4.5.1.1), which lets a fixed-width field survive the dynamic table wrapping around. The
// Base anchors the section's relative indices and is carried as a sign bit plus a delta from
// the Required Insert Count. This prefix is what a field-line decoder reads before it can
// resolve any dynamic-table reference.

///|
/// The number of entries that fit in a table of `max_capacity` bytes at the 32-byte minimum
/// entry size — `MaxEntries` in RFC 9204 §4.5.1.1.
pub fn qpack_max_entries(max_capacity : Int) -> Int {
  max_capacity / 32
}

///|
/// Encode a field-section prefix (RFC 9204 §4.5.1): the Required Insert Count transmitted
/// modulo `2*max_entries`, then the Base as a sign bit (0 when `base >= req_insert_count`)
/// plus the delta.
pub fn qpack_encode_section_prefix(
  req_insert_count : Int,
  base : Int,
  max_entries : Int,
) -> Bytes {
  let enc_ric = if req_insert_count == 0 {
    0
  } else {
    req_insert_count % (2 * max_entries) + 1
  }
  let buf = Buffer()
  buf.write_bytes(qpack_int_encode(enc_ric, 8, 0))
  if base >= req_insert_count {
    buf.write_bytes(qpack_int_encode(base - req_insert_count, 7, 0))
  } else {
    buf.write_bytes(qpack_int_encode(req_insert_count - base - 1, 7, 0x80))
  }
  buf.to_bytes()
}

///|
/// Reconstruct the absolute Required Insert Count from its encoded form, `max_entries`, and
/// the number of inserts the decoder has processed (RFC 9204 §4.5.1.1).
pub fn qpack_decode_required_insert_count(
  encoded : Int,
  max_entries : Int,
  total_inserts : Int,
) -> Int raise QpackError {
  if encoded == 0 {
    return 0
  }
  let full_range = 2 * max_entries
  if encoded > full_range {
    raise QpackError("QPACK encoded Required Insert Count exceeds 2*MaxEntries")
  }
  let max_value = total_inserts + max_entries
  let max_wrapped = max_value / full_range * full_range
  let mut ric = max_wrapped + encoded - 1
  if ric > max_value {
    if ric <= full_range {
      raise QpackError("QPACK Required Insert Count decode underflow")
    }
    ric = ric - full_range
  }
  if ric == 0 {
    raise QpackError("QPACK Required Insert Count of 0 encoded as non-zero")
  }
  ric
}

///|
/// Decode a field-section prefix (RFC 9204 §4.5.1), given `max_entries` and the decoder's
/// total inserts so far. Returns `(req_insert_count, base, bytes-consumed)`, or `None` on a
/// partial read.
pub fn qpack_decode_section_prefix(
  input : BytesView,
  max_entries : Int,
  total_inserts : Int,
) -> (Int, Int, Int)? raise QpackError {
  let (enc_ric, ric_len) = match qpack_int_decode(input, 8) {
    Some(v) => v
    None => return None
  }
  let req_insert_count = qpack_decode_required_insert_count(
    enc_ric, max_entries, total_inserts,
  )
  if input.length() <= ric_len {
    return None
  }
  let sign = (input[ric_len].to_int() & 0x80) != 0
  let (delta_base, base_len) = match qpack_int_decode(input[ric_len:], 7) {
    Some(v) => v
    None => return None
  }
  let base = if sign {
    req_insert_count - delta_base - 1
  } else {
    req_insert_count + delta_base
  }
  Some((req_insert_count, base, ric_len + base_len))
}