Skip to main content

better_profanity/
charset.rs

1use rustc_hash::FxHashSet;
2
3/// A set of characters, such as `ALLOWED_CHARACTERS`, and which of them are whitespace to
4/// Python's `str.strip()`.
5#[derive(Clone, Debug)]
6pub struct CharSet {
7    bmp: Box<[u64]>,
8    astral: FxHashSet<char>,
9    spaces: FxHashSet<char>,
10    len: usize,
11}
12
13impl CharSet {
14    /// The set of `chars`; `is_space` tells which of them `str.strip()` removes.
15    pub fn new(chars: impl IntoIterator<Item = char>, is_space: impl Fn(char) -> bool) -> Self {
16        let mut set = CharSet {
17            bmp: vec![0; 0x10000 / 64].into_boxed_slice(),
18            astral: FxHashSet::default(),
19            spaces: FxHashSet::default(),
20            len: 0,
21        };
22        for c in chars {
23            if set.contains(c) {
24                continue;
25            }
26            set.len += 1;
27            let code = c as usize;
28            if code < 0x10000 {
29                set.bmp[code / 64] |= 1 << (code % 64);
30            } else {
31                set.astral.insert(c);
32            }
33            if is_space(c) {
34                set.spaces.insert(c);
35            }
36        }
37        set
38    }
39
40    #[inline]
41    pub fn contains(&self, c: char) -> bool {
42        let code = c as usize;
43        if code < 0x10000 {
44            self.bmp[code / 64] & (1 << (code % 64)) != 0
45        } else {
46            self.astral.contains(&c)
47        }
48    }
49
50    pub fn len(&self) -> usize {
51        self.len
52    }
53
54    pub fn is_empty(&self) -> bool {
55        self.len == 0
56    }
57
58    /// Whether `s.strip() == ""` for a string of characters from this set.
59    pub(crate) fn strips_to_empty(&self, s: &[char]) -> bool {
60        s.iter().all(|c| self.spaces.contains(c))
61    }
62}