use std::fmt::{Debug, Display};
pub type Offset = u64;
pub type Tag = u64;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct VariantIdx(pub u32);
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Immediate<'a> {
        Null,
    Bool(bool),
    Int64(i64),
    Float(f64),
        String(&'a str),
        Bytes(&'a [u8]),
        Variant0(VariantIdx),
        Ref(Offset),
        Pointer(Offset),
}
impl<'a> Default for Immediate<'a> {
    fn default() -> Self {
        Immediate::Null
    }
}
macro_rules! impl_from {
    ($variant:path, $typ:ty, $typ_real:ty) => {
        impl<'a> From<$typ_real> for Immediate<'a> {
            fn from(v: $typ_real) -> Immediate<'a> {
                $variant(v as $typ)
            }
        }
    };
}
impl<'a> From<()> for Immediate<'a> {
    fn from(_v: ()) -> Self {
        Immediate::Null
    }
}
impl_from!(Immediate::Bool, bool, bool);
impl_from!(Immediate::Int64, i64, i64);
impl_from!(Immediate::Int64, i64, i32);
impl_from!(Immediate::Float, f64, f64);
impl_from!(Immediate::Float, f64, f32);
impl_from!(Immediate::String, &'a str, &'a str);
impl_from!(Immediate::Bytes, &'a [u8], &'a [u8]);
impl_from!(Immediate::Pointer, Offset, Offset);
#[derive(Debug, Clone, Copy)]
pub struct Error {
        pub msg: &'static str,
        pub off: Offset,
}
pub type Result<T> = core::result::Result<T, Error>;
impl Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Twine error: {} at offset=0x{:x} ({})",
            self.msg, self.off, self.off
        )
    }
}
impl std::error::Error for Error {}