// Parsing implementations for HelloRequest, HelloVerifyRequest, CertificateRequest, CertificateVerify, and Finished

///|

///|
pub fn parse_hello_request(
  data : BytesView,
) -> Result[HelloRequest, ParseError] {
  if data.length() < 5 {
    return Err(IncompleteRecord(expected=5, available=data.length()))
  }
  if data[0].to_int() != 0x16 {
    return Err(NotTlsHandshake)
  }
  guard read_u16_int(data, 3) is Some(record_len) else {
    return Err(BadLength(field="record.length", offset=3))
  }
  if record_len < 4 {
    return Err(BadLength(field="handshake.header", offset=5))
  }
  let record_end = 5 + record_len
  if record_end < 5 || data.length() < record_end {
    return Err(IncompleteRecord(expected=record_end, available=data.length()))
  }
  if data[5].to_int() != 0 {
    return Err(BadHandshakeType(data[5].to_int()))
  }
  guard read_u24_int(data, 6) is Some(handshake_len) else {
    return Err(BadLength(field="handshake.length", offset=6))
  }
  let body_end = 9 + handshake_len
  if handshake_len != 0 || body_end > record_end {
    return Err(BadLength(field="hello_request.body", offset=9))
  }
  Ok({ dummy: 0 })
}

///|
pub fn parse_hello_verify_request(
  data : BytesView,
) -> Result[HelloVerifyRequest, ParseError] {
  if data.length() < 5 {
    return Err(IncompleteRecord(expected=5, available=data.length()))
  }
  if data[0].to_int() != 0x16 {
    return Err(NotTlsHandshake)
  }
  guard read_u16_int(data, 3) is Some(record_len) else {
    return Err(BadLength(field="record.length", offset=3))
  }
  if record_len < 4 {
    return Err(BadLength(field="handshake.header", offset=5))
  }
  let record_end = 5 + record_len
  if record_end < 5 || data.length() < record_end {
    return Err(IncompleteRecord(expected=record_end, available=data.length()))
  }
  if data[5].to_int() != 3 {
    return Err(BadHandshakeType(data[5].to_int()))
  }
  guard read_u24_int(data, 6) is Some(handshake_len) else {
    return Err(BadLength(field="handshake.length", offset=6))
  }
  let body_offset = 9
  if handshake_len < 0 || body_offset + handshake_len > record_end {
    return Err(BadLength(field="handshake.body", offset=body_offset))
  }

  // HelloVerifyRequest: Version (2 bytes) + Cookie Length (1 byte) + Cookie
  if handshake_len < 3 {
    return Err(BadLength(field="hello_verify.header", offset=body_offset))
  }

  guard read_u16(data, body_offset) is Some(version) else {
    return Err(BadLength(field="hello_verify.version", offset=body_offset))
  }

  let cookie_len = data[body_offset + 2].to_int()
  if cookie_len < 0 ||
    body_offset + 3 + cookie_len > body_offset + handshake_len ||
    !has_range(data, body_offset + 3, cookie_len) {
    return Err(BadLength(field="hello_verify.cookie", offset=body_offset + 3))
  }

  let cookie_arr = Array::new(capacity=cookie_len)
  for i in 0.. Result[CertificateRequest, ParseError] {
  if data.length() < 5 {
    return Err(IncompleteRecord(expected=5, available=data.length()))
  }
  if data[0].to_int() != 0x16 {
    return Err(NotTlsHandshake)
  }
  guard read_u16_int(data, 3) is Some(record_len) else {
    return Err(BadLength(field="record.length", offset=3))
  }
  if record_len < 4 {
    return Err(BadLength(field="handshake.header", offset=5))
  }
  let record_end = 5 + record_len
  if record_end < 5 || data.length() < record_end {
    return Err(IncompleteRecord(expected=record_end, available=data.length()))
  }
  if data[5].to_int() != 13 {
    return Err(BadHandshakeType(data[5].to_int()))
  }
  guard read_u24_int(data, 6) is Some(handshake_len) else {
    return Err(BadLength(field="handshake.length", offset=6))
  }
  let body_offset = 9
  let body_end = body_offset + handshake_len
  if handshake_len < 0 || body_end < body_offset || body_end > record_end {
    return Err(BadLength(field="handshake.body", offset=body_offset))
  }

  // CertificateRequest:
  // Certificate Types Length (1 byte) + Types +
  // [TLS 1.2] Supported Signature Algorithms Length (2 bytes) + Algorithms
  if handshake_len < 1 {
    return Err(BadLength(field="cert_request.header", offset=body_offset))
  }

  let types_len = data[body_offset].to_int()
  if types_len < 0 ||
    body_offset + 1 + types_len > body_end ||
    !has_range(data, body_offset + 1, types_len) {
    return Err(BadLength(field="cert_request.types", offset=body_offset + 1))
  }

  let certificate_types = Array::new(capacity=types_len)
  for i in 0.. body_end {
      return Err(BadLength(field="cert_request.sig_algs_body", offset=cursor))
    }
    let end_sig = cursor + sig_algs_len
    while cursor + 2 <= end_sig {
      guard read_u16(data, cursor) is Some(alg) else {
        return Err(BadLength(field="cert_request.alg", offset=cursor))
      }
      sig_algs.push(alg)
      cursor = cursor + 2
    }
    if cursor != end_sig {
      return Err(
        BadLength(field="cert_request.sig_algs_trailing", offset=cursor),
      )
    }
  }

  if cursor != body_end {
    return Err(BadLength(field="cert_request.trailing", offset=cursor))
  }

  Ok({ certificate_types, supported_signature_algorithms: sig_algs })
}

///|
pub fn parse_certificate_verify(
  data : BytesView,
) -> Result[CertificateVerify, ParseError] {
  if data.length() < 5 {
    return Err(IncompleteRecord(expected=5, available=data.length()))
  }
  if data[0].to_int() != 0x16 {
    return Err(NotTlsHandshake)
  }
  guard read_u16_int(data, 3) is Some(record_len) else {
    return Err(BadLength(field="record.length", offset=3))
  }
  if record_len < 4 {
    return Err(BadLength(field="handshake.header", offset=5))
  }
  let record_end = 5 + record_len
  if record_end < 5 || data.length() < record_end {
    return Err(IncompleteRecord(expected=record_end, available=data.length()))
  }
  if data[5].to_int() != 15 {
    return Err(BadHandshakeType(data[5].to_int()))
  }
  guard read_u24_int(data, 6) is Some(handshake_len) else {
    return Err(BadLength(field="handshake.length", offset=6))
  }
  let body_offset = 9
  let body_end = body_offset + handshake_len
  if handshake_len < 0 || body_end < body_offset || body_end > record_end {
    return Err(BadLength(field="handshake.body", offset=body_offset))
  }

  // CertificateVerify: Signature Algorithm (2 bytes) + Signature Length (2 bytes) + Signature
  if handshake_len < 4 {
    return Err(BadLength(field="cert_verify.header", offset=body_offset))
  }

  guard read_u16(data, body_offset) is Some(signature_algorithm) else {
    return Err(BadLength(field="cert_verify.sig_alg", offset=body_offset))
  }

  guard read_u16_int(data, body_offset + 2) is Some(sig_len) else {
    return Err(BadLength(field="cert_verify.sig_len", offset=body_offset + 2))
  }

  if sig_len < 0 ||
    body_offset + 4 + sig_len > body_end ||
    !has_range(data, body_offset + 4, sig_len) {
    return Err(BadLength(field="cert_verify.signature", offset=body_offset + 4))
  }

  let sig_arr = Array::new(capacity=sig_len)
  for i in 0.. Result[Finished, ParseError] {
  if data.length() < 5 {
    return Err(IncompleteRecord(expected=5, available=data.length()))
  }
  if data[0].to_int() != 0x16 {
    return Err(NotTlsHandshake)
  }
  guard read_u16_int(data, 3) is Some(record_len) else {
    return Err(BadLength(field="record.length", offset=3))
  }
  if record_len < 4 {
    return Err(BadLength(field="handshake.header", offset=5))
  }
  let record_end = 5 + record_len
  if record_end < 5 || data.length() < record_end {
    return Err(IncompleteRecord(expected=record_end, available=data.length()))
  }
  if data[5].to_int() != 20 {
    return Err(BadHandshakeType(data[5].to_int()))
  }
  guard read_u24_int(data, 6) is Some(handshake_len) else {
    return Err(BadLength(field="handshake.length", offset=6))
  }
  let body_offset = 9
  let body_end = body_offset + handshake_len
  if handshake_len < 0 ||
    body_end < body_offset ||
    body_end > record_end ||
    !has_range(data, body_offset, handshake_len) {
    return Err(BadLength(field="handshake.body", offset=body_offset))
  }

  let verify_arr = Array::new(capacity=handshake_len)
  for i in 0..