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 .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#[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 pub fn new() -> Self {
41 Self(Default::default())
42 }
43
44 #[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 pub fn insert(&mut self, c: char) {
61 self.0.insert(c);
62 }
63
64 pub fn remove(&mut self, c: char) {
66 self.0.remove(&c);
67 }
68}