alloy_trie/
mask.rs

1use core::fmt;
2use derive_more::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Deref, From, Not};
3
4/// A struct representing a mask of 16 bits, used for Ethereum trie operations.
5///
6/// Masks in a trie are used to efficiently represent and manage information about the presence or
7/// absence of certain elements, such as child nodes, within a trie. Masks are usually implemented
8/// as bit vectors, where each bit represents the presence (1) or absence (0) of a corresponding
9/// element.
10#[derive(
11    Default,
12    Clone,
13    Copy,
14    PartialEq,
15    Eq,
16    PartialOrd,
17    Ord,
18    Deref,
19    From,
20    BitAnd,
21    BitAndAssign,
22    BitOr,
23    BitOrAssign,
24    Not,
25)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27#[cfg_attr(feature = "arbitrary", derive(derive_arbitrary::Arbitrary, proptest_derive::Arbitrary))]
28pub struct TrieMask(u16);
29
30impl fmt::Debug for TrieMask {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        write!(f, "TrieMask({:016b})", self.0)
33    }
34}
35
36impl TrieMask {
37    /// Creates a new `TrieMask` from the given inner value.
38    #[inline]
39    pub const fn new(inner: u16) -> Self {
40        Self(inner)
41    }
42
43    /// Returns the inner value of the `TrieMask`.
44    #[inline]
45    pub const fn get(self) -> u16 {
46        self.0
47    }
48
49    /// Creates a new `TrieMask` from the given nibble.
50    #[inline]
51    pub const fn from_nibble(nibble: u8) -> Self {
52        Self(1u16 << nibble)
53    }
54
55    /// Returns `true` if the current `TrieMask` is a subset of `other`.
56    #[inline]
57    pub fn is_subset_of(self, other: Self) -> bool {
58        self & other == self
59    }
60
61    /// Returns `true` if a given bit is set in a mask.
62    #[inline]
63    pub const fn is_bit_set(self, index: u8) -> bool {
64        self.0 & (1u16 << index) != 0
65    }
66
67    /// Returns `true` if the mask is empty.
68    #[inline]
69    pub const fn is_empty(self) -> bool {
70        self.0 == 0
71    }
72
73    /// Returns the number of bits set in the mask.
74    #[inline]
75    pub const fn count_bits(self) -> u8 {
76        self.0.count_ones() as u8
77    }
78
79    /// Returns the index of the first bit set in the mask, or `None` if the mask is empty.
80    #[inline]
81    pub const fn first_set_bit_index(self) -> Option<u8> {
82        if self.is_empty() {
83            None
84        } else {
85            Some(self.0.trailing_zeros() as u8)
86        }
87    }
88
89    /// Set bit at a specified index.
90    #[inline]
91    pub fn set_bit(&mut self, index: u8) {
92        self.0 |= 1u16 << index;
93    }
94
95    /// Unset bit at a specified index.
96    #[inline]
97    pub fn unset_bit(&mut self, index: u8) {
98        self.0 &= !(1u16 << index);
99    }
100}