/// the e_data index in e_ident.
pub const ELF_IDENT_DATA_INDEX: usize = 5;

/// invalid data encoding
pub const ELF_IDENT_DATA_NONE: u8 = 0;
/// 2's complement, little endian.
pub const ELF_IDENT_DATA_2LSB: u8 = 1;
/// 2's complement, big endian.
pub const ELF_IDENT_DATA_2MSB: u8 = 2;
/// the number of pre-defined e_data values.
pub const ELF_IDENT_DATA_NUM: u8 = 3;

/// the data encoding of the processor-specific data in the object file.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum ElfData {
    /// invalid data encoding
    None,
    /// 2's complement, little endian.
    TwosComplementLSB,
    /// 2's complement, big endian.
    TwosComplementMSB,
    /// the number of pre-defined e_data values.
    Num,
    /// custom value
    Any(u8),
}

impl std::fmt::Display for ElfData {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            Self::None => "None".to_string(),
            Self::TwosComplementLSB => "2's Complement Little Endian".to_string(),
            Self::TwosComplementMSB => "2's Complement Big Endian".to_string(),
            Self::Num => format!("Unknown!({})", ELF_IDENT_DATA_NUM),
            Self::Any(v) => format!("Unknown!({})", v),
        };

        write!(f, "{}", s)
    }
}

impl From<u8> for ElfData {
    fn from(value: u8) -> Self {
        match value {
            ELF_IDENT_DATA_NONE => Self::None,
            ELF_IDENT_DATA_2LSB => Self::TwosComplementLSB,
            ELF_IDENT_DATA_2MSB => Self::TwosComplementMSB,
            ELF_IDENT_DATA_NUM => Self::Num,
            _ => Self::Any(value),
        }
    }
}

impl From<ElfData> for u8 {
    fn from(value: ElfData) -> Self {
        match value {
            ElfData::None => ELF_IDENT_DATA_NONE,
            ElfData::TwosComplementLSB => ELF_IDENT_DATA_2LSB,
            ElfData::TwosComplementMSB => ELF_IDENT_DATA_2MSB,
            ElfData::Num => ELF_IDENT_DATA_NUM,
            ElfData::Any(v) => v,
        }
    }
}

impl Default for ElfData {
    fn default() -> Self {
        Self::None
    }
}
