//! Integer constants used as immediate operands.
use num_bigint::BigInt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use crate::types::primary::IType;

/// An integer literal paired with its `IType` width.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct IConst {
    /// Integer type describing the bit-width of the literal.
    pub ty: IType,
    /// Literal payload stored with unbounded precision.
    pub value: BigInt,
}

impl std::fmt::Display for IConst {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} {}", self.ty, self.value)
    }
}

impl From<u8> for IConst {
    /// Create an 8‑bit integer constant from a primitive value.
    fn from(value: u8) -> Self {
        Self {
            ty: IType::I8,
            value: value.into(),
        }
    }
}

impl From<u16> for IConst {
    /// Create a 16‑bit integer constant from a primitive value.
    fn from(value: u16) -> Self {
        Self {
            ty: IType::I16,
            value: value.into(),
        }
    }
}

impl From<u32> for IConst {
    /// Create a 32‑bit integer constant from a primitive value.
    fn from(value: u32) -> Self {
        Self {
            ty: IType::I32,
            value: value.into(),
        }
    }
}

impl From<u64> for IConst {
    /// Create a 64‑bit integer constant from a primitive value.
    fn from(value: u64) -> Self {
        Self {
            ty: IType::I64,
            value: value.into(),
        }
    }
}
