rustrict/
banned.rs

1use crate::feature_cell::FeatureCell;
2use crate::Set;
3use lazy_static::lazy_static;
4use std::ops::Deref;
5
6lazy_static! {
7    pub(crate) static ref BANNED: FeatureCell<Banned> = FeatureCell::new(Banned(
8        include_str!("banned_chars.txt")
9            .lines()
10            .filter(|s| s.starts_with("U+"))
11            .map(|s| {
12                u32::from_str_radix(&s[2..], 16)
13                    .ok()
14                    .and_then(char::from_u32)
15                    .unwrap()
16            })
17            // If you care about width, you probably also care about height.
18            .chain(if cfg!(feature = "width") {
19                    ['\u{A9C1}', '\u{A9C2}'].as_slice().into_iter().copied()
20                } else {
21                    [].as_slice().into_iter().copied()
22                })
23            .collect()
24    ));
25}
26
27/// Set of character to strip from input without replacement.
28#[derive(Clone, Debug)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct Banned(Set<char>);
31
32impl Default for Banned {
33    fn default() -> Self {
34        BANNED.deref().deref().clone()
35    }
36}
37
38impl Banned {
39    /// Empty.
40    pub fn new() -> Self {
41        Self(Default::default())
42    }
43
44    /// Allows direct mutable access to the global default set of banned characters.
45    ///
46    /// # Safety
47    ///
48    /// You must manually avoid concurrent access/censoring.
49    #[cfg(feature = "customize")]
50    #[cfg_attr(doc, doc(cfg(feature = "customize")))]
51    pub unsafe fn customize_default() -> &'static mut Self {
52        BANNED.get_mut()
53    }
54
55    pub(crate) fn contains(&self, c: char) -> bool {
56        self.0.contains(&c)
57    }
58
59    /// Adds a banned character.
60    pub fn insert(&mut self, c: char) {
61        self.0.insert(c);
62    }
63
64    /// Removes a banned character.
65    pub fn remove(&mut self, c: char) {
66        self.0.remove(&c);
67    }
68}