///|
/// Shannon entropy of a byte range, in bits per byte (0.0 to 8.0).
///
/// This is the cheapest useful signal for "is this section packed or
/// encrypted": compiled code and data usually land between 4 and 6.5, while
/// compressed or encrypted payloads cluster near 8.

///|
pub fn byte_entropy(bytes : Bytes) -> Double? {
  if bytes.length() == 0 {
    return None
  }
  let counts : Array[Int32] = []
  let mut i = 0
  while i < 256 {
    counts.push(0)
    i = i + 1
  }
  let mut j = 0
  while j < bytes.length() {
    let value = bytes[j].to_int()
    if value >= 0 && value < 256 {
      counts[value] = counts[value] + 1
    }
    j = j + 1
  }
  let total = bytes.length().to_double()
  let mut entropy = 0.0
  let mut k = 0
  while k < 256 {
    let count = counts[k]
    if count > 0 {
      let p = count.to_double() / total
      entropy = entropy - p * @math.log2(p)
    }
    k = k + 1
  }
  Some(entropy)
}

///|
/// Entropy of a section's file-backed bytes.
pub fn Pe::section_entropy(self : Pe, section : Section) -> Double? {
  match self.section_bytes(section) {
    Some(bytes) => byte_entropy(bytes)
    None => None
  }
}