1use crate::controls::ConstraintPlatform;
2
3#[must_use]
8pub fn executable_platform(bytes: &[u8]) -> Option<ConstraintPlatform> {
9 elf_platform(bytes)
10 .or_else(|| mach_o_platform(bytes))
11 .or_else(|| pe_platform(bytes))
12}
13
14fn elf_platform(bytes: &[u8]) -> Option<ConstraintPlatform> {
17 if bytes.get(..4) != Some(&[0x7f, b'E', b'L', b'F']) {
18 return None;
19 }
20 if bytes.get(4) != Some(&2) || bytes.get(5) != Some(&1) {
21 return None;
22 }
23 match bytes.get(18..20)? {
24 [0x3e, 0x00] => Some(ConstraintPlatform::LinuxX8664),
25 [0xb7, 0x00] => Some(ConstraintPlatform::LinuxAarch64),
26 _ => None,
27 }
28}
29
30fn mach_o_platform(bytes: &[u8]) -> Option<ConstraintPlatform> {
33 if bytes.get(..4) != Some(&[0xcf, 0xfa, 0xed, 0xfe]) {
34 return None;
35 }
36 match bytes.get(4..8)? {
37 [0x07, 0x00, 0x00, 0x01] => Some(ConstraintPlatform::MacosX8664),
38 [0x0c, 0x00, 0x00, 0x01] => Some(ConstraintPlatform::MacosAarch64),
39 _ => None,
40 }
41}
42
43fn pe_platform(bytes: &[u8]) -> Option<ConstraintPlatform> {
46 if bytes.get(..2) != Some(b"MZ") {
47 return None;
48 }
49 let header = bytes.get(0x3c..0x40)?;
50 let [a, b, c, d] = header else { return None };
51 let offset = usize::try_from(u32::from_le_bytes([*a, *b, *c, *d])).ok()?;
52 if bytes.get(offset..offset.checked_add(4)?) != Some(b"PE\0\0") {
53 return None;
54 }
55 let machine = offset.checked_add(4)?;
56 match bytes.get(machine..machine.checked_add(2)?)? {
57 [0x64, 0x86] => Some(ConstraintPlatform::WindowsX8664),
58 [0x64, 0xaa] => Some(ConstraintPlatform::WindowsAarch64),
59 _ => None,
60 }
61}
62
63#[must_use]
67pub const fn host_platform() -> Option<ConstraintPlatform> {
68 match (
69 cfg!(target_os = "linux"),
70 cfg!(target_os = "macos"),
71 cfg!(target_os = "windows"),
72 ) {
73 (true, _, _) => arch(
74 ConstraintPlatform::LinuxX8664,
75 ConstraintPlatform::LinuxAarch64,
76 ),
77 (_, true, _) => arch(
78 ConstraintPlatform::MacosX8664,
79 ConstraintPlatform::MacosAarch64,
80 ),
81 (_, _, true) => arch(
82 ConstraintPlatform::WindowsX8664,
83 ConstraintPlatform::WindowsAarch64,
84 ),
85 _ => None,
86 }
87}
88
89const fn arch(
90 x86_64: ConstraintPlatform,
91 aarch64: ConstraintPlatform,
92) -> Option<ConstraintPlatform> {
93 if cfg!(target_arch = "x86_64") {
94 Some(x86_64)
95 } else if cfg!(target_arch = "aarch64") {
96 Some(aarch64)
97 } else {
98 None
99 }
100}