///|
/// The CLR header (data-directory slot 14) and the metadata root it points at.
///
/// This is enough to answer "is this a managed assembly, and which runtime was
/// it built for" without decoding the full .NET metadata tables.

///|
pub(all) struct ClrInfo {
  runtime_version : String
  metadata_size : Int32
  flags : Int32
  entry_point_token : Int32
} derive(@debug.Debug)

///|
/// Read the CLR header, or `None` for a native image.
pub fn Pe::clr(self : Pe) -> ClrInfo? raise PeError {
  let directory = match self.directory(14) {
    None => return None
    Some(directory) => directory
  }
  if directory.virtual_address == 0 || directory.size == 0 {
    return None
  }
  let header = match self.reader_at_rva(directory.virtual_address) {
    Some(reader) => reader
    None =>
      raise PeError::Malformed(
        "CLR header RVA " +
        hex(directory.virtual_address) +
        " is not backed by file bytes",
        0,
      )
  }
  header.skip(4)
  header.skip(4)
  let metadata_rva = header.u32()
  let metadata_size = header.u32()
  let flags = header.u32()
  let entry_point_token = header.u32()
  let metadata = match self.reader_at_rva(metadata_rva) {
    Some(reader) => reader
    None => return None
  }
  let signature = metadata.u32_raw()
  if signature != 0x424A5342 {
    return None
  }
  metadata.skip(4)
  metadata.skip(4)
  let version_length = metadata.u32()
  if version_length > 255 {
    return None
  }
  let runtime_version = metadata.ascii(version_length)
  Some({ runtime_version, metadata_size, flags, entry_point_token, })
}