Skip to main content

tfhe_safe_serialize/
traits.rs

1use std::marker::PhantomData;
2
3pub trait Named {
4    /// Default name for the type
5    const NAME: &'static str;
6    /// Aliases that should also be accepted for backward compatibility when checking the name of
7    /// values of this type
8    const BACKWARD_COMPATIBILITY_ALIASES: &'static [&'static str] = &[];
9}
10
11/// A trait for objects which can be checked to be conformant with a parameter set
12pub trait ParameterSetConformant {
13    type ParameterSet;
14
15    fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool;
16}
17
18/// A set of C-style enum values. This can be seen as a lightweight HashSet that derives Copy.
19///
20/// This can be used in conformance to let applications chose to accept previous config values
21/// during a transition period and then remove support for outdated values later.
22///
23/// # Warning
24/// As this is backed by a u128, it only supports enum of up to 128 elements
25#[derive(Debug, PartialEq, Eq, Clone, Copy)]
26pub struct EnumSet<T> {
27    mask: u128,
28    _phantom: PhantomData<T>,
29}
30
31impl<T> Default for EnumSet<T> {
32    fn default() -> Self {
33        Self::new()
34    }
35}
36
37impl<T> EnumSet<T> {
38    pub const fn new() -> Self {
39        Self {
40            mask: 0,
41            _phantom: PhantomData,
42        }
43    }
44}
45
46impl<T> EnumSet<T>
47where
48    T: Into<usize> + Copy,
49{
50    /// Checks if a given value is present in the set.
51    pub fn contains(&self, value: T) -> bool {
52        let index = value.into();
53
54        if index < 128 {
55            (self.mask & (1 << index)) != 0
56        } else {
57            false
58        }
59    }
60
61    /// Adds a value to the set.
62    ///
63    /// # Panic
64    /// Panics if the usize representation of `value` is >= 128
65    pub fn insert(&mut self, value: T) {
66        let index = value.into();
67
68        assert!(index < 128, "Config index too large for u128");
69
70        self.mask |= 1 << index;
71    }
72
73    /// Removes a value from the set.
74    pub fn remove(&mut self, value: T) {
75        let index = value.into();
76
77        if index < 128 {
78            self.mask &= !(1 << index);
79        }
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[derive(Debug, Clone, Copy, PartialEq)]
88    enum Color {
89        Red = 0,
90        Green = 1,
91        Blue = 2,
92    }
93
94    impl From<Color> for usize {
95        fn from(c: Color) -> Self {
96            c as Self
97        }
98    }
99
100    #[test]
101    fn insert_and_contains() {
102        let mut set = EnumSet::new();
103        assert!(!set.contains(Color::Red));
104
105        set.insert(Color::Red);
106        set.insert(Color::Blue);
107
108        assert!(set.contains(Color::Red));
109        assert!(!set.contains(Color::Green));
110        assert!(set.contains(Color::Blue));
111    }
112
113    #[test]
114    fn remove() {
115        let mut set = EnumSet::new();
116        set.insert(Color::Red);
117        set.insert(Color::Green);
118
119        set.remove(Color::Red);
120
121        assert!(!set.contains(Color::Red));
122        assert!(set.contains(Color::Green));
123    }
124
125    #[test]
126    fn contains_out_of_range_returns_false() {
127        #[derive(Debug, Clone, Copy)]
128        struct Big;
129
130        impl From<Big> for usize {
131            fn from(_: Big) -> Self {
132                200 // 128 is the max
133            }
134        }
135
136        let set = EnumSet::new();
137        assert!(!set.contains(Big));
138    }
139}