use crate::abi::{Header, Side, Str};
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, bytemuck::Zeroable)]
pub struct Fingerprint {
pub guid: [u8; 16],
pub age: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, bytemuck::Zeroable)]
pub struct BuildInfo {
pub header: Header,
pub side: Side,
pub base: u64,
pub fingerprint: Fingerprint,
pub table: BuildTable,
}
impl_headed!(BuildInfo);
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, bytemuck::Zeroable)]
pub struct BuildTable(pub u8);
impl BuildTable {
pub const EXACT: Self = Self(0);
pub const PATTERNS: Self = Self(1);
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Symbol {
pub name: Str,
pub rva: u64,
}
#[must_use]
pub const fn guid(hex: &str) -> [u8; 16] {
let bytes = hex.as_bytes();
assert!(bytes.len() == 32, "a GUID is 32 hex digits");
let mut out = [0u8; 16];
let mut i = 0;
while i < 16 {
out[i] = (digit(bytes[2 * i]) << 4) | digit(bytes[2 * i + 1]);
i += 1;
}
out
}
#[expect(
clippy::panic,
reason = "used in const evaluation, where a bad literal fails the build"
)]
const fn digit(c: u8) -> u8 {
match c {
b'0'..=b'9' => c - b'0',
b'a'..=b'f' => c - b'a' + 10,
_ => panic!("a GUID is lowercase hex"),
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct BuildRow {
pub side: Side,
pub fingerprint: Fingerprint,
pub symbols: *const Symbol,
pub symbol_count: usize,
pub constants: *const Symbol,
pub constant_count: usize,
}
unsafe impl Sync for BuildRow {}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Relation(pub u8);
impl Relation {
pub const REQUIRES: Self = Self(0);
pub const AFTER: Self = Self(1);
pub const BREAKS: Self = Self(2);
pub const RECOMMENDS: Self = Self(3);
pub const REPLACES: Self = Self(4);
pub const WAS: Self = Self(5);
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Dependency {
pub id: Str,
pub range: Str,
pub relation: Relation,
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, bytemuck::Zeroable)]
pub struct ManifestFlags(pub u32);
impl ManifestFlags {
pub const NONE: Self = Self(0);
pub const JOIN: Self = Self(1);
pub const RELOAD: Self = Self(2);
#[must_use]
pub const fn contains(self, other: Self) -> bool {
self.0 & other.0 == other.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, bytemuck::Zeroable)]
pub struct Manifest {
pub header: Header,
pub id: Str,
pub version: Str,
pub side: Side,
pub flags: ManifestFlags,
pub dependencies: *const Dependency,
pub dependency_count: usize,
pub builds: *const BuildRow,
pub build_count: usize,
pub name: Str,
pub description: Str,
pub authors: *const Str,
pub author_count: usize,
pub license: Str,
pub homepage: Str,
pub points: Str,
}
impl_headed!(Manifest);
unsafe impl Sync for Manifest {}