///| test the Dilithium by KAT files
priv struct KAT {
  id : Int
  seed : Array[Byte]
  mlen : Int // message length
  msg : Array[Byte]
  pk : Array[Byte]
  sk : Array[Byte]
  smlen : Int // signature length
  sm : Array[Byte] // signature
}

///|
fn string_view_to_bytes(s : @string.View) -> Array[Byte] {
  let bytes : Array[Byte] = Array::new()
  let char_length = s.char_length()
  if (char_length & 1) != 0 {
    abort("String length must be even for hex conversion")
  }
  for i in 0..<(char_length / 2) {
    let byte : Byte = (hex_char_to_int(s.get_char(i * 2).unwrap()) * 16 +
    hex_char_to_int(s.get_char(i * 2 + 1).unwrap())).to_byte()
    bytes.push(byte)
  }
  bytes
}

///|
fn load_seed() -> Array[Array[Byte]] {
  let file_path = "kat/SeedBuffer_Dilithium"
  let content = @fs.read_file_to_string(file_path) catch {
    err => abort(err.to_string())
  }
  content
  .split("\n")
  .to_array()
  .map(line => line.to_string())
  .map(hex_str_to_bytes)
}

///|
fn load_kat_file(level : SecurityLevel) -> Array[KAT] {
  let file_name = match level {
    SecurityLevel::Dilithium2 => "PQCsignKAT_Dilithium2.rsp"
    SecurityLevel::Dilithium3 => "PQCsignKAT_Dilithium3.rsp"
    SecurityLevel::Dilithium5 => "PQCsignKAT_Dilithium5.rsp"
  }
  let file_path = "kat/" + file_name
  let content = @fs.read_file_to_string(file_path) catch {
    err => abort(err.to_string())
  }
  fn extract_value_to_bytes(line : String) -> Array[Byte] {
    let value = line.split("=").last().unwrap().to_string()
    let bytes = string_view_to_bytes(value.trim_space())
    bytes
  }

  fn extract_value_to_int(line : String) -> Int {
    let value = line.split("=").last().unwrap().to_string()
    let int_value = try? @strconv.parse_int(value.trim_space().to_string())
    int_value.unwrap()
  }

  let lines = content
    .split("\n")
    .filter(line => not(line.is_empty()))
    .map(line => line.to_string())
  // count, seed, mlen, msg, pk, sk, smlen, sm
  let count = lines
    .filter(line => line.has_prefix("count"))
    .map(line => line.split("=").last().unwrap().to_string())
    .map(extract_value_to_int)
    .collect()
  let seed = lines
    .filter(line => line.has_prefix("seed"))
    .map(extract_value_to_bytes)
    .collect()
  let mlen = lines
    .filter(line => line.has_prefix("mlen"))
    .map(extract_value_to_int)
    .collect()
  let msg = lines
    .filter(line => line.has_prefix("msg"))
    .map(extract_value_to_bytes)
    .collect()
  let pk = lines
    .filter(line => line.has_prefix("pk"))
    .map(extract_value_to_bytes)
    .collect()
  let sk = lines
    .filter(line => line.has_prefix("sk"))
    .map(extract_value_to_bytes)
    .collect()
  let smlen = lines
    .filter(line => line.has_prefix("smlen"))
    .map(extract_value_to_int)
    .collect()
  let sm = lines
    .filter(line => line.has_prefix("sm "))
    .map(extract_value_to_bytes)
    .collect()
  let kats = []
  for i in 0..