use {super::*, std::num::TryFromIntError}; #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Ord, PartialOrd)] pub(crate) struct RuneId { pub(crate) height: u32, pub(crate) index: u16, } impl TryFrom for RuneId { type Error = TryFromIntError; fn try_from(n: u128) -> Result { Ok(Self { height: u32::try_from(n >> 16)?, index: u16::try_from(n & 0xFFFF).unwrap(), }) } } impl From for u128 { fn from(id: RuneId) -> Self { u128::from(id.height) << 16 | u128::from(id.index) } } impl Display for RuneId { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}/{}", self.height, self.index,) } } impl FromStr for RuneId { type Err = crate::Error; fn from_str(s: &str) -> Result { let (height, index) = s .split_once('/') .ok_or_else(|| anyhow!("invalid rune ID: {s}"))?; Ok(Self { height: height.parse()?, index: index.parse()?, }) } } #[cfg(test)] mod tests { use super::*;