Documentation
mod class;
mod data;
mod os_abi;
mod version;

pub use self::{class::Class, data::Data, os_abi::OsAbi, version::Version};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum HeaderError {
    #[error("invalid magic number")]
    Magic,
    #[error("invalid class: {0}")]
    Class(u8),
    #[error("invalid data: {0}")]
    Data(u8),
    #[error("invalid version: {0}")]
    Version(u8),
    #[error("invalid os abi: {0}")]
    OsAbi(u8),
    #[error("invalid abi version: {0}")]
    AbiVersion(u8),
}

type Result<T> = core::result::Result<T, HeaderError>;

#[repr(C)]
#[derive(Debug)]
pub struct Header {
    pub(crate) magic: [u8; 4],
    pub(crate) class: u8,
    pub(crate) data: u8,
    pub(crate) version: u8,
    pub(crate) os_abi: u8,
    pub(crate) abi_version: u8,
    pub(crate) _padding: [u8; 7],
}

impl Header {
    pub fn class(&self) -> Class {
        Class::from(self.class)
    }
    pub fn data(&self) -> Data {
        Data::from(self.data)
    }

    pub fn version(&self) -> Version {
        Version::from(self.version)
    }

    pub fn os_abi(&self) -> OsAbi {
        OsAbi::from(self.os_abi)
    }

    pub fn abi_version(&self) -> u8 {
        self.abi_version
    }

    pub(crate) fn sanity_check(&self) -> Result<()> {
        if self.magic != *b"\x7fELF" {
            return Err(HeaderError::Magic);
        }

        Ok(())
    }
}