use crate::machine::{CpuSubType, CpuType};
use nom::{
self,
number::{complete::be_u32, streaming::be_u64},
IResult,
};
use nom_derive::{Nom, Parse};
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Nom)]
pub enum FatMagic {
Fat = 0xcafebabe,
Fat64 = 0xcafebabf,
}
#[derive(Debug, Clone, Copy)]
pub struct FatHeader {
pub magic: FatMagic,
pub nfat_arch: u32,
}
impl FatHeader {
pub fn parse(input: &[u8]) -> IResult<&[u8], FatHeader> {
let (input, magic) = FatMagic::parse_be(input)?;
let (input, nfat_arch) = be_u32(input)?;
Ok((input, FatHeader { magic, nfat_arch }))
}
}
#[derive(Debug, Clone, Copy)]
pub struct FatArch32 {
pub cputype: CpuType,
pub cpusubtype: CpuSubType,
pub offset: u32,
pub size: u32,
pub align: u32,
}
impl FatArch32 {
pub fn parse(input: &[u8]) -> IResult<&[u8], FatArch32> {
let (input, cputype) = CpuType::parse_be(input)?;
let (input, cpusubtype) = CpuSubType::parse_be(input, cputype)?;
let (input, offset) = be_u32(input)?;
let (input, size) = be_u32(input)?;
let (input, align) = be_u32(input)?;
Ok((
input,
FatArch32 {
cputype,
cpusubtype,
offset,
size,
align,
},
))
}
}
#[derive(Debug, Clone, Copy)]
pub struct FatArch64 {
pub cputype: CpuType,
pub cpusubtype: CpuSubType,
pub offset: u64,
pub size: u64,
pub align: u32,
pub reserved: u32,
}
impl FatArch64 {
pub fn parse(input: &[u8]) -> IResult<&[u8], FatArch64> {
let (input, cputype) = CpuType::parse_be(input)?;
let (input, cpusubtype) = CpuSubType::parse_be(input, cputype)?;
let (input, offset) = be_u64(input)?;
let (input, size) = be_u64(input)?;
let (input, align) = be_u32(input)?;
let (input, reserved) = be_u32(input)?;
Ok((
input,
FatArch64 {
cputype,
cpusubtype,
offset,
size,
align,
reserved,
},
))
}
}
#[derive(Debug, Clone, Copy)]
pub enum FatArch {
Arch32(FatArch32),
Arch64(FatArch64),
}
impl FatArch {
pub fn parse(input: &[u8], magic: FatMagic) -> IResult<&[u8], FatArch> {
match magic {
FatMagic::Fat => {
let (input, arch) = FatArch32::parse(input)?;
Ok((input, FatArch::Arch32(arch)))
}
FatMagic::Fat64 => {
let (input, arch) = FatArch64::parse(input)?;
Ok((input, FatArch::Arch64(arch)))
}
}
}
pub fn cputype(&self) -> CpuType {
match self {
FatArch::Arch32(arch) => arch.cputype,
FatArch::Arch64(arch) => arch.cputype,
}
}
pub fn cpusubtype(&self) -> CpuSubType {
match self {
FatArch::Arch32(arch) => arch.cpusubtype,
FatArch::Arch64(arch) => arch.cpusubtype,
}
}
pub fn offset(&self) -> u64 {
match self {
FatArch::Arch32(arch) => arch.offset as u64,
FatArch::Arch64(arch) => arch.offset,
}
}
pub fn size(&self) -> u64 {
match self {
FatArch::Arch32(arch) => arch.size as u64,
FatArch::Arch64(arch) => arch.size,
}
}
pub fn align(&self) -> u32 {
match self {
FatArch::Arch32(arch) => arch.align,
FatArch::Arch64(arch) => arch.align,
}
}
}