///|
/// Data packing and serialization utilities for Dilithium keys and signatures.
///
/// This module provides functions for serializing and deserializing the various
/// data structures used in the Dilithium signature scheme, including public keys,
/// secret keys, and signatures. The packing formats follow the NIST FIPS 204
/// standard specification.
///
/// # Packing Formats
///
/// The module implements efficient bit-packing techniques to minimize the size
/// of keys and signatures while maintaining security properties. Different
/// polynomial representations use specialized packing schemes optimized for
/// their specific coefficient distributions.
///
/// # Error Handling
///
/// All unpacking operations include comprehensive validation to detect malformed
/// input and prevent security vulnerabilities.
///
/// # Examples
///
/// ```moonbit
/// // Pack public key
/// let pk = @ruifeng/moondsa.pack_pk(rho, t1)
/// 
/// // Pack signature
/// let sig = @ruifeng/moondsa.pack_sig(sig, None, z, h)
/// 
/// // Unpack signature components
/// match @ruifeng/moondsa.unpack_sig(signature) {
///   Ok((z, h, c)) => println("Valid signature format")
///   Err(e) => println("Invalid signature: \(e)")
/// }
/// ```

///|
/// Signature verification or validation error with descriptive message.
///
/// This error type is returned when signature verification fails or when
/// signature/key unpacking encounters invalid data. The error message provides
/// specific information about what validation failed.
suberror SignError String

///|
/// Serializes a public key into its binary representation by concatenating the
/// seed `rho` and packed polynomial vector `t1`.
///
/// Parameters:
///
/// * `rho` : The random seed used in key generation, typically 32 bytes.
/// * `t1` : The polynomial vector representing the public component of the key.
///
/// Returns a byte array containing the packed public key data.
pub fn pack_pk(rho : Array[Byte], t1 : Polyveck) -> Array[Byte] {
  let k = dilithium_context.get_params_set().k
  let pk : Array[Byte] = Array::new()
  pk.append(rho)
  for i in 0.. (Array[Byte], Polyveck) {
  let k = dilithium_context.get_params_set().k
  let rho = pk[0:SEEDBYTES].to_array()
  let t1 : Polyveck = Polyveck::default()
  for i in 0.. Array[Byte] {
  let k = dilithium_context.get_params_set().k
  let l = dilithium_context.get_params_set().l
  let sk : Array[Byte] = Array::new()
  sk.append(rho)
  sk.append(key)
  sk.append(tr)
  for i in 0.. (Array[Byte], Array[Byte], Array[Byte], Polyveck, Polyvecl, Polyveck) {
  let k = dilithium_context.get_params_set().k
  let l = dilithium_context.get_params_set().l
  let polyeta_packedbytes = dilithium_context.get_params_set().polyeta_packedbytes
  let mut idx = 0
  let rho = sk[0:SEEDBYTES].to_array()
  idx += SEEDBYTES
  let key = sk[idx:idx + SEEDBYTES].to_array()
  idx += SEEDBYTES
  let tr = sk[idx:idx + SEEDBYTES].to_array()
  idx += SEEDBYTES
  let s1 : Polyvecl = Polyvecl::default()
  for i in 0.. Array[Byte] {
  let k = dilithium_context.get_params_set().k
  let l = dilithium_context.get_params_set().l
  let omega = dilithium_context.get_params_set().omega
  let polyz_packed_bytes = dilithium_context.get_params_set().polyz_packed_bytes
  let mut idx = 0
  match c {
    Some(challenge) =>
      for i in 0.. ()
  }
  idx += SEEDBYTES
  for i in 0.. Result[(Polyvecl, Polyveck, Array[Byte]), SignError] {
  let k = dilithium_context.get_params_set().k
  let l = dilithium_context.get_params_set().l
  let omega = dilithium_context.get_params_set().omega
  let polyz_packed_bytes = dilithium_context.get_params_set().polyz_packed_bytes
  let z = Polyvecl::default()
  let h = Polyveck::default()
  let c = Array::new()
  let mut idx = 0
  c.append(sig[0:SEEDBYTES].to_array())
  idx += SEEDBYTES
  for i in 0.. omega.to_byte() {
      return Err(SignError("Invalid signature"))
    }
    for j in cnt.. cnt && sig[idx + j] <= sig[idx + j - 1] {
        return Err(SignError("Invalid signature"))
      }
      h.vec[i].coeffs[sig[idx + j].to_int()] = 1
    }
    cnt = sig[idx + omega + i].to_int()
  }

  // Extra indices are zero for strong unforgeability
  for j in cnt.. 0 {
      return Err(SignError("Invalid signature"))
    }
  }
  Ok((z, h, c))
}