mdp/state/
features.rs

1use std::ops::BitOrAssign;
2
3use borsh::{BorshDeserialize, BorshSerialize};
4
5/// Number of bytes used for feature flags, we set this value
6/// to 32, this gives 256 bits, i.e. 256 different features
7const FEATURESET_BYTES: usize = 32;
8
9/// Bit map of supported features
10#[derive(Debug, Default, BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone)]
11pub struct FeaturesSet([u8; FEATURESET_BYTES]);
12
13/// Individual custom extra feature supported by validator
14#[derive(Clone, Copy)]
15#[repr(u8)]
16pub enum Feature {
17    Randomness = 0,
18    HighResClock = 1,
19}
20
21impl FeaturesSet {
22    const SEGMENT: usize = u8::BITS as usize;
23
24    /// Enables given feature in featureset
25    pub fn activate(mut self, feature: Feature) -> Self {
26        let (segment, offset) = self.locate(feature);
27        segment.bitor_assign(1 << offset);
28        self
29    }
30
31    #[cfg(test)]
32    fn deactivate(&mut self, feature: Feature) {
33        use std::ops::{BitAndAssign, Not};
34        let (segment, offset) = self.locate(feature);
35        segment.bitand_assign((1u8 << offset).not());
36    }
37
38    fn locate(&mut self, feature: Feature) -> (&mut u8, u8) {
39        let index = feature as usize / Self::SEGMENT;
40        let offset = feature as usize % Self::SEGMENT;
41        // SAFETY: feature cannot exceed 255 (repr(u8)), 0..255 / 64 <= 3
42        let segment = unsafe { self.0.get_unchecked_mut(index) };
43        (segment, offset as u8)
44    }
45
46    /// Returns true if given featureset has requested feature enabled
47    pub fn contains(&mut self, feature: Feature) -> bool {
48        let (segment, offset) = self.locate(feature);
49        (*segment & (1 << offset)) >> offset == 1
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56    #[test]
57    fn test_features_op() {
58        let mut features = FeaturesSet::default()
59            .activate(Feature::Randomness)
60            .activate(Feature::HighResClock);
61        assert!(features.contains(Feature::Randomness));
62        features.deactivate(Feature::Randomness);
63        assert!(!features.contains(Feature::Randomness));
64        assert!(features.contains(Feature::HighResClock));
65    }
66}