ton_lib_core 0.0.7

A collection of types and utilities for interacting with the TON network
Documentation
use std::fmt::Display;
use std::ops::{BitOr, BitOrAssign, Shr, Sub};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd)]
pub struct LevelMask(u8);

impl LevelMask {
    pub const MIN_LEVEL: LevelMask = LevelMask(0);
    pub const MAX_LEVEL: LevelMask = LevelMask(3);

    pub const fn new(mask: u8) -> Self { Self(mask) }
    pub const fn level(&self) -> u8 { 8 - self.0.leading_zeros() as u8 }
    pub const fn mask(&self) -> u8 { self.0 }
    pub const fn hash_index(&self) -> usize { self.0.count_ones() as usize }
    pub const fn hash_count(&self) -> usize { self.hash_index() + 1 }
    pub const fn is_significant(&self, level: u8) -> bool { level == 0 || ((self.0 >> (level - 1)) % 2 != 0) }
    pub const fn apply(&self, level: u8) -> Self { LevelMask(self.0 & ((1u8 << level) - 1)) }
}

impl From<LevelMask> for u8 {
    fn from(val: LevelMask) -> Self { val.0 }
}

impl<T: Into<u8>> BitOr<T> for LevelMask {
    type Output = Self;
    fn bitor(self, rhs: T) -> Self::Output { LevelMask(self.0 | rhs.into()) }
}

impl<T: Into<u8>> BitOrAssign<T> for LevelMask {
    fn bitor_assign(&mut self, rhs: T) { self.0 |= rhs.into(); }
}

impl<T: Into<u8>> Shr<T> for LevelMask {
    type Output = Self;
    fn shr(self, rhs: T) -> Self::Output { LevelMask(self.0 >> rhs.into()) }
}

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

impl<T: Into<u8>> Sub<T> for LevelMask {
    type Output = LevelMask;
    fn sub(self, rhs: T) -> Self::Output { LevelMask(self.0 - rhs.into()) }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_level_mask() {
        let mask = LevelMask::new(0b1010);
        assert_eq!(mask.level(), 4);
        assert_eq!(mask.hash_index(), 2);
        assert_eq!(mask.hash_count(), 3);
        assert_eq!(mask.apply(0), LevelMask::new(0));
        assert!(!mask.is_significant(1));
        assert!(mask.is_significant(2));
        assert!(!mask.is_significant(3));
        assert!(mask.is_significant(4));

        assert_eq!(mask | 0b100, LevelMask::new(0b1110));
        assert_eq!(mask >> 1, LevelMask::new(0b101));
    }
}