// SPDX-License-Identifier: Apache-2.0

///|
/// Decode the optional Rich Header located between the DOS stub and PE header.
pub fn PEImage::rich_header(self : Self) -> RichHeaderInfo? {
  let rich_offset = find_rich_marker(self.data, self.pe_offset)
  if rich_offset < 0 {
    return None
  }
  let key = read_u32(self.data, rich_offset + 4) catch {
    PeError(_, _) => return None
  }
  let dans_value = 0x536e6144UL
  let mut offset = 0x40
  let mut dans_offset = -1
  while offset + 4 <= rich_offset {
    let value = read_u32(self.data, offset) catch {
      PeError(_, _) => return None
    }
    if value.lxor(key) == dans_value {
      dans_offset = offset
      break
    }
    offset = offset + 4
  }
  if dans_offset < 0 || dans_offset + 16 > rich_offset {
    return None
  }
  let entries = []
  let mut index_offset = dans_offset + 16
  while index_offset + 8 <= rich_offset && entries.length() < 256 {
    let combined = (read_u32(self.data, index_offset) catch {
      PeError(_, _) => return None
    }).lxor(key)
    let count = (read_u32(self.data, index_offset + 4) catch {
      PeError(_, _) => return None
    }).lxor(key)
    let product_id = (combined >> 16).to_int()
    let build_id = combined.land(0xffffUL).to_int()
    entries.push({ product_id, build_id, use_count: count.to_int(), })
    index_offset = index_offset + 8
  }
  Some({ xor_key: key, entries, })
}

///|
fn find_rich_marker(data : Bytes, pe_offset : Int32) -> Int32 {
  let mut offset = 0x40
  while offset + 8 <= pe_offset {
    if data[offset] == b'R' &&
      data[offset + 1] == b'i' &&
      data[offset + 2] == b'c' &&
      data[offset + 3] == b'h' {
      return offset
    }
    offset = offset + 4
  }
  -1
}